diff --git a/.env b/.env new file mode 100644 index 0000000..f3b84c5 --- /dev/null +++ b/.env @@ -0,0 +1,10 @@ +MYSQL_ROOT_USER=root +MYSQL_ROOT_PASSWORD=Test@123 +MYSQL_DATABASE=bankappdb + +MYSQL_HOST=mysql +MYSQL_PORT=3306 +MYSQL_USER=root +MYSQL_PASSWORD=Test@123 + +OLLAMA_URL=http://ollama:11434 \ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 4801575..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,107 +0,0 @@ -name: Build - Container Build & Push - -on: - workflow_call: - -permissions: - id-token: write # Required for OIDC - contents: read - -jobs: - - # ============================================================ - # GATE 5: BUILD - # ============================================================ - build: - name: Build & Package - runs-on: ubuntu-latest - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Set up JDK 21 - uses: actions/setup-java@v4 - with: - java-version: '21' - distribution: 'temurin' - cache: maven - - - name: Build with Maven - run: mvn clean package -DskipTests - - - name: Upload Build Artifact - uses: actions/upload-artifact@v4 - with: - name: app-jar - path: target/*.jar - - # ============================================================ - # GATE 6: CONTAINER IMAGE SCAN - Trivy - # ============================================================ - image_scan: - name: Container Scan - Trivy - runs-on: ubuntu-latest - needs: build - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Build Docker Image (for scanning) - run: docker build --pull -t bankapp:scan-${{ github.sha }} . - - - name: Cache Trivy DB - uses: actions/cache@v4 - with: - path: ~/.cache/trivy - key: trivy-db-${{ runner.os }}-${{ github.run_id }} - restore-keys: | - trivy-db-${{ runner.os }}- - - - name: Run Trivy Image Scan - uses: aquasecurity/trivy-action@master - with: - image-ref: bankapp:scan-${{ github.sha }} - format: 'table' - exit-code: '1' # Enforce: fail pipeline on CRITICAL/HIGH findings - ignore-unfixed: true - vuln-type: 'os,library' - severity: 'CRITICAL,HIGH' - output: trivy-report.txt - trivy-config: trivy.yaml - - - name: Upload Trivy Report - uses: actions/upload-artifact@v4 - if: always() - with: - name: trivy-scan-report - path: trivy-report.txt - - # ============================================================ - # GATE 7: PUSH TO ECR - # ============================================================ - push_to_ecr: - name: Push to ECR - runs-on: ubuntu-latest - needs: image_scan - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Configure AWS Credentials (OIDC) - uses: aws-actions/configure-aws-credentials@v4 - with: - role-to-assume: ${{ secrets.AWS_ROLE_ARN }} - aws-region: ${{ secrets.AWS_REGION }} - - - name: Login to Amazon ECR - id: login-ecr - uses: aws-actions/amazon-ecr-login@v2 - - - name: Build, Tag, and Push Image - env: - ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} - ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }} - IMAGE_TAG: ${{ github.sha }} - run: | - docker build --pull -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG . - docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml deleted file mode 100644 index af8419e..0000000 --- a/.github/workflows/cd.yml +++ /dev/null @@ -1,94 +0,0 @@ -name: CD - Deploy & DAST - -on: - workflow_call: - -permissions: - id-token: write # Required for OIDC - contents: read - -jobs: - - # ============================================================ - # GATE 8: DEPLOY - # ============================================================ - deploy: - name: Deploy to EC2 via SSH - runs-on: ubuntu-latest - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Create Deployment Directory - uses: appleboy/ssh-action@master - with: - host: ${{ secrets.EC2_HOST }} - username: ${{ secrets.EC2_USER }} - key: ${{ secrets.EC2_SSH_KEY }} - script: mkdir -p ~/bankapp - - - name: Copy app-tier.yml to EC2 - uses: appleboy/scp-action@master - with: - host: ${{ secrets.EC2_HOST }} - username: ${{ secrets.EC2_USER }} - key: ${{ secrets.EC2_SSH_KEY }} - source: "app-tier.yml" - target: "~/bankapp" - - - name: Deploy via SSH - uses: appleboy/ssh-action@master - with: - host: ${{ secrets.EC2_HOST }} - username: ${{ secrets.EC2_USER }} - key: ${{ secrets.EC2_SSH_KEY }} - script: | - # Login to ECR - aws ecr get-login-password --region ${{ secrets.AWS_REGION }} | docker login --username AWS --password-stdin ${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com - - cd ~/bankapp - - # Fetch secrets from Secrets Manager and create .env - aws secretsmanager get-secret-value --secret-id bankapp/prod-secrets --query SecretString --output text > secrets.json - - # Extract variables and write to .env - echo "DB_HOST=$(jq -r .DB_HOST secrets.json)" > .env - echo "DB_PORT=$(jq -r .DB_PORT secrets.json)" >> .env - echo "DB_NAME=$(jq -r .DB_NAME secrets.json)" >> .env - echo "DB_USER=$(jq -r .DB_USER secrets.json)" >> .env - echo "DB_PASSWORD=$(jq -r .DB_PASSWORD secrets.json)" >> .env - echo "OLLAMA_URL=$(jq -r .OLLAMA_URL secrets.json)" >> .env - echo "ECR_REGISTRY=${{ secrets.AWS_ACCOUNT_ID }}.dkr.ecr.${{ secrets.AWS_REGION }}.amazonaws.com" >> .env - echo "ECR_REPOSITORY=${{ secrets.ECR_REPOSITORY }}" >> .env - echo "IMAGE_TAG=${{ github.sha }}" >> .env - - # Clean up - rm secrets.json - - # Pull and Deploy using the app-tier.yml transferred via SCP - docker compose -f app-tier.yml pull - docker compose -f app-tier.yml up -d --build - - # ============================================================ - # GATE 9: DAST - Dynamic Application Security Testing - # ============================================================ - dast: - name: DAST - OWASP ZAP Baseline Scan - runs-on: ubuntu-latest - needs: deploy - steps: - - name: Run OWASP ZAP Baseline Scan - uses: zaproxy/action-baseline@v0.15.0 - continue-on-error: true # Workaround for ZAP's internal artifact upload bug - with: - target: 'http://${{ secrets.EC2_HOST }}:8080' - artifact_name: zapreport - fail_action: false - allow_issue_writing: false - - - name: Upload ZAP Report - uses: actions/upload-artifact@v4 - if: always() - with: - name: zap-dast-report - path: report_html.html \ No newline at end of file diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 5955a8c..0000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,108 +0,0 @@ -name: CI - Security Scanning - -on: - workflow_call: - -permissions: - contents: read - security-events: write - -jobs: - - # ============================================================ - # GATE 1: SECRET SCANNING (Gitleaks) - # ============================================================ - gitleaks: - name: Secret Scan - Gitleaks - runs-on: ubuntu-latest - steps: - - name: Checkout Code - uses: actions/checkout@v4 - with: - fetch-depth: 0 # Gitleaks needs full history to scan all commits - - - name: Run Gitleaks - uses: gitleaks/gitleaks-action@v2 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - # ============================================================ - # GATE 2: LINT - Java Checkstyle - # ============================================================ - lint: - name: Lint - Checkstyle - runs-on: ubuntu-latest - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Set up JDK 21 - uses: actions/setup-java@v4 - with: - java-version: '21' - distribution: 'temurin' - cache: maven - - - name: Run Checkstyle - run: mvn checkstyle:check || true # Audit mode for now to avoid blocking on style - - # ============================================================ - # GATE 3: SAST - Static Application Security Testing - # ============================================================ - sast: - name: SAST - Semgrep - runs-on: ubuntu-latest - needs: [gitleaks, lint] - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Run Semgrep SAST Scan - uses: semgrep/semgrep-action@v1 - with: - config: >- - p/java - p/owasp-top-ten - p/secrets - - # ============================================================ - # GATE 4: SCA - Software Composition Analysis - # ============================================================ - sca: - name: SCA - OWASP Dependency Check - runs-on: ubuntu-latest - needs: [gitleaks, lint] - steps: - - name: Checkout Code - uses: actions/checkout@v4 - - - name: Set up JDK 21 - uses: actions/setup-java@v4 - with: - java-version: '21' - distribution: 'temurin' - cache: maven - - - name: Cache OWASP NVD Database - uses: actions/cache@v4 - with: - path: ~/.m2/repository/org/owasp/dependency-check-data - key: owasp-nvd-${{ runner.os }}-${{ hashFiles('**/pom.xml') }} - restore-keys: | - owasp-nvd-${{ runner.os }}- - - - name: Run OWASP Dependency Check - env: - NVD_API_KEY: ${{ secrets.NVD_API_KEY }} - run: | - mvn org.owasp:dependency-check-maven:check \ - -DfailBuildOnCVSS=7 \ - -DnvdApiKey="${NVD_API_KEY}" \ - -DsuppressionFile=suppression.xml - - - name: Upload Dependency Check Report - uses: actions/upload-artifact@v4 - if: always() - with: - name: owasp-dependency-check-report - path: target/dependency-check-report.html diff --git a/.github/workflows/cicd.yml b/.github/workflows/cicd.yml new file mode 100644 index 0000000..66d05b5 --- /dev/null +++ b/.github/workflows/cicd.yml @@ -0,0 +1,144 @@ +name: CI-CD-bankapp + +on: + push: + branches: + - main + workflow_dispatch: + +jobs: + build-test-scan-deploy: + runs-on: ubuntu-latest + + steps: + + - name: Checkout Code + uses: actions/checkout@v4 + + - name: Set up Java 21 + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: '21' + + - name: Cache Maven Dependencies + uses: actions/cache@v4 + with: + path: ~/.m2 + key: maven-${{ hashFiles('**/pom.xml') }} + + - name: Build and Test + run: ./mvnw clean verify + + - name: Run Trivy FS Scan + uses: aquasecurity/trivy-action@0.35.0 + with: + scan-type: fs + format: table + exit-code: '0' + severity: CRITICAL,HIGH + + - name: Clean project + run: ./mvnw clean + + - name: Build Docker Image + run: | + docker build --no-cache -t ${{ vars.DOCKER_USERNAME }}/bankapp:${{ github.sha }} . + docker tag sachin8801/bankapp:${{ github.sha }} sachin8801/bankapp:v1 + + - name: Run Trivy Image Scan + uses: aquasecurity/trivy-action@0.35.0 + with: + image-ref: ${{ vars.DOCKER_USERNAME }}/bankapp:${{ github.sha }} + format: table + exit-code: '0' + severity: CRITICAL,HIGH + + - name: Docker Hub Login + uses: docker/login-action@v3 + with: + username: ${{ vars.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Push Docker Image + run: | + docker push ${{ vars.DOCKER_USERNAME }}/bankapp:${{ github.sha }} + docker push sachin8801/bankapp:v1 + + - name: Setup Terraform + uses: hashicorp/setup-terraform@v3 + + - name: Terraform Init + working-directory: terraform + run: terraform init + - name: Terraform Apply + working-directory: terraform + run: terraform apply -auto-approve + env: + AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }} + + - name: Get Public IP + id: tf + working-directory: terraform + run: echo "ip=$(terraform output -raw public_ip)" >> $GITHUB_OUTPUT + + - name: Setup SSH + run: | + echo "${{ secrets.EC2_SSH_KEY }}" > key.pem + chmod 400 key.pem + + - name: Fetch kubeconfig + run: | + sleep 60 + + ssh -o StrictHostKeyChecking=no -i key.pem ubuntu@${{ steps.tf.outputs.ip }} \ + "sudo cat /etc/rancher/k3s/k3s.yaml" > kubeconfig + + sed -i "s/127.0.0.1/${{ steps.tf.outputs.ip }}/g" kubeconfig + sed -i 's/certificate-authority-data:/#certificate-authority-data:/g' kubeconfig + sed -i 's/server: https:/insecure-skip-tls-verify: true\n server: https:/g' kubeconfig + + mkdir -p $HOME/.kube + mv kubeconfig $HOME/.kube/config + # 1. Namespace FIRST + - name: Deploy Namespace + run: kubectl apply -f setup-k8s/namespace.yaml --validate=false + + # 2. Core configs + - name: Deploy Secrets + run: kubectl apply -f setup-k8s/secrets.yaml --validate=false + + - name: Deploy ConfigMap + run: kubectl apply -f setup-k8s/configmap.yaml --validate=false + + # 3. Database layer + - name: Deploy MySQL + run: | + kubectl apply -f setup-k8s/mysql/pvc.yaml --validate=false + kubectl apply -f setup-k8s/mysql/deployment.yaml --validate=false + kubectl apply -f setup-k8s/mysql/service.yaml --validate=false + + # Wait for DB to be ready (CRITICAL) + - name: Wait for MySQL + run: kubectl rollout status deployment/mysql-deployment -n bank-app + + # 3. Deploy Ollama- AI Tiny Lama + - name: Deploy Ollama + run: | + kubectl apply -f setup-k8s/ollama/deployment.yaml --validate=false + kubectl apply -f setup-k8s/ollama/service.yaml --validate=false + + # Wait for Ollama to be ready (CRITICAL) + - name: Wait for Ollama + run: kubectl rollout status deployment/ollama -n bank-app + + # 5. Frontend layer + - name: Deploy Frontend + run: | + kubectl apply -f setup-k8s/bank-app/deployment.yaml --validate=false + kubectl apply -f setup-k8s/bank-app/service.yaml --validate=false + + - name: Verify + run: kubectl rollout status deployment/bankapp-deployment -n bank-app + diff --git a/.github/workflows/devsecops-main.yml b/.github/workflows/devsecops-main.yml deleted file mode 100644 index a20e7b8..0000000 --- a/.github/workflows/devsecops-main.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: DevSecOps Main Pipeline - -on: - push: - branches: [ main, devsecops, k8s ] - paths-ignore: - - '**.md' - - '.gitignore' - - 'LICENSE' - - 'screenshots/**' - - 'scripts/**' - -permissions: - id-token: write - contents: read - security-events: write - -jobs: - # ============================================================ - # STAGE 1: CI - Security Scanning (SAST + SCA) - # ============================================================ - ci: - uses: ./.github/workflows/ci.yml - secrets: inherit - - # ============================================================ - # STAGE 2: Build - Maven + Trivy + ECR Push - # ============================================================ - build: - needs: ci - uses: ./.github/workflows/build.yml - secrets: inherit - - # ============================================================ - # STAGE 3: CD - Deploy + DAST - # ============================================================ - cd: - needs: build - uses: ./.github/workflows/cd.yml - secrets: inherit \ No newline at end of file diff --git a/.gitignore b/.gitignore index 05f19eb..ed669a5 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,10 @@ build/ ### Claude ### CLAUDE.md + +##Terrform ## + +# Terraform +.terraform/ +*.tfstate +*.tfstate.backup diff --git a/Dockerfile b/Dockerfile index 92c47d4..746ba3c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,22 +1,12 @@ -# Build stage -FROM eclipse-temurin:21-jdk-alpine AS build +# Stage 1: Build +FROM maven:3.9.9-eclipse-temurin-21 AS builder WORKDIR /app COPY . . -RUN chmod +x mvnw && ./mvnw clean package -DskipTests -B +RUN mvn clean package -DskipTests -# Run stage - alpine has significantly fewer CVEs than ubuntu/jammy -FROM eclipse-temurin:21-jre-alpine +# Stage 2: Run +FROM eclipse-temurin:21-jdk-jammy WORKDIR /app +COPY --from=builder /app/target/*.jar app.jar -# Pull latest security patches for OS libraries -RUN apk update && apk upgrade --no-cache - -# Create a non-root user for security (Alpine uses addgroup/adduser instead of groupadd/useradd) -RUN addgroup -S devsecops && adduser -S -G devsecops devsecops -USER devsecops - -# Copy only the built artifact -COPY --from=build /app/target/*.jar app.jar - -EXPOSE 8080 -ENTRYPOINT ["java", "-jar", "app.jar"] +ENTRYPOINT ["java", "-jar", "app.jar"] \ No newline at end of file diff --git a/README.md b/README.md index 0b0c464..de73cfe 100644 --- a/README.md +++ b/README.md @@ -1,326 +1,111 @@ -
+# AI Banking Application – DevOps Implementation 🚀 -# DevSecOps Banking Application - -A high-performance, containerized financial platform built with Spring Boot 3, Java 21, and integrated Contextual AI. This project implements a secure "DevSecOps Pipeline" using GitHub Actions, OIDC authentication, and AWS managed services. - -[![Java Version](https://img.shields.io/badge/Java-21-blue.svg)](https://www.oracle.com/java/technologies/javase/jdk21-archive-downloads.html) -[![Spring Boot](https://img.shields.io/badge/Spring%20Boot-3.4.1-brightgreen.svg)](https://spring.io/projects/spring-boot) -[![GitHub Actions](https://img.shields.io/badge/CI%2FCD-GitHub%20Actions-orange.svg)](.github/workflows/devsecops.yml) -[![AWS OIDC](https://img.shields.io/badge/Security-OIDC-red.svg)](#phase-3-security-and-identity-configuration) - -
- -![dashboard](screenshots/1.png) +![CI Pipeline](https://github.com/Sachin8801/AI-BankApp-DevOps/actions/workflows/ci.yml/badge.svg) +![Docker](https://img.shields.io/badge/docker-enabled-blue) +![Security](https://img.shields.io/badge/security-trivy-green) +![Java](https://img.shields.io/badge/java-21-orange) --- +This project demonstrates an end-to-end DevOps and DevSecOps implementation for an AI Banking Application. -## Technical Architecture - -The application is deployed across a multi-tier, segmented AWS environment. The control plane leverages GitHub Actions with integrated security gates at every stage. - -```mermaid -graph TD - subgraph "External Control Plane" - GH[GitHub Actions] - User[User Browser] - end - - subgraph "AWS Infrastructure (VPC)" - subgraph "Application Tier" - AppEC2[App EC2 - Ubuntu/Docker] - DB[(MySQL 8.0 Container)] - end - - subgraph "Artificial Intelligence Tier" - Ollama[Ollama EC2 - AI Engine] - end - - subgraph "Identity & Secrets" - Secrets[AWS Secrets Manager] - OIDC[IAM OIDC Provider] - end - - subgraph "Registry" - ECR[Amazon ECR] - end - end - - GH -->|1. OIDC Authentication| OIDC - GH -->|2. Push Scanned Image| ECR - GH -->|3. SSH Orchestration| AppEC2 - GH -->|4. DAST Scan| AppEC2 - - User -->|Port 8080| AppEC2 - AppEC2 -->|JDBC Connection| DB - AppEC2 -->|REST Integration| Ollama - AppEC2 -->|Runtime Secrets| Secrets - AppEC2 -->|Pull Image| ECR -``` +The goal is to simulate a real-world production workflow by integrating containerization, CI/CD automation, security scanning, and Kubernetes-based deployment. --- -## Security Pipeline (DevSecOps Pipeline) +## 🎯 Project Objective -The CI/CD pipeline enforces **9 sequential security gates** before any code reaches production: - -| Gate | Name | Tool | Purpose | -| :---: | :--- | :--- | :--- | -| 1 | Secret Scan | Gitleaks | Scans entire Git history for leaked secrets | -| 2 | Lint | Checkstyle | Enforces Java Google-Style coding standards | -| 3 | SAST | Semgrep | Scans Java source code for security flaws and OWASP Top 10 | -| 4 | SCA | OWASP Dependency Check (first time run can take more than 30+ minutes) | Scans Maven dependencies for known CVEs | -| 5 | Build | Maven | Compiles and packages the application | -| 6 | Container Scan | Trivy | Scans the Docker image for OS and library vulnerabilities | -| 7 | Push | Amazon ECR | Pushes the image only after Trivy passes | -| 8 | Deploy | SSH / Docker Compose | Automated deployment to AWS EC2 | -| 9 | DAST | OWASP ZAP | Dynamic attack surface scanning on live app | +- Automate application build and deployment +- Implement CI/CD pipeline using GitHub Actions +- Integrate security scanning (DevSecOps) +- Deploy and manage application on Kubernetes +- Ensure scalability, reliability, and automation --- -## Technology Stack +## 🧱 **Flow:** -- **Backend Framework**: Java 21, Spring Boot 3.4.1 -- **Security Strategy**: Spring Security, IAM OIDC, Secrets Manager -- **Persistence Layer**: MySQL 8.0 (Docker Container) -- **AI Integration**: Ollama (TinyLlama) -- **DevOps Tooling**: Docker, Docker Compose, GitHub Actions, AWS CLI, jq -- **Infrastructure**: Amazon EC2, Amazon ECR, Amazon VPC +GitHub → GitHub Actions → Docker → Security Scan → Kubernetes → Users --- -## Implementation Phases - -### Phase 1: AWS Infrastructure Initialization - -1. **Container Registry (ECR)**: - - - Establish a private ECR repository named `devsecops-bankapp`. - - ![ECR](screenshots/2.png) - -2. **Application Server (EC2)**: - - - Deploy an Ubuntu 22.04 instance with below `User Data`. - - ```bash - #!/bin/bash - - sudo apt update - sudo apt install -y docker.io docker-compose-v2 jq - sudo usermod -aG docker ubuntu - sudo newgrp docker - sudo snap install aws-cli --classic - ``` - - - Configure Security Group to open inbound rule for Port 22 (Management) and Port 8080 (Service). - - > Better to give `name` to Security Group created. +## ⚙️ Tech Stack - - Create an IAM Instance Profile(IAM EC2 role) containing permissions: - - `AmazonEC2ContainerRegistryPowerUser` - - `AWSSecretsManagerClientReadOnlyAccess` - - ![Permissions](screenshots/3.png) - - - Attach it to Application EC2. Select EC2 -> Actions -> Security -> Modify IAM role -> Attach created IAM role. - - ![IAM role](screenshots/4.png) - - - Connect to EC2 Instance and Run below command to check whether IAM role is working or not. - - ```bash - aws sts get-caller-identity - ``` - - You will get your account details with IAM role assumed. - -3. **AI Engine Tier (Ollama)**: - - Deploy a dedicated Ubuntu EC2 instance. - - Open Inbound Port `11434` from the Application EC2 Security Group. - - > Better to give `name` to Security Group created. - - ![ollama-sg](screenshots/8.png) - - - Automate initialization using the [ollama-setup.sh](scripts/ollama-setup.sh) script via EC2 User Data. - - ![user-data](screenshots/9.png) - - - Verify the AI engine is responsive and the model is pulled in `AI engine EC2`: - - ```bash - ollama list - ``` - - ![ollama-list](screenshots/21.png) +- **Containerization**: Docker +- **CI/CD**: GitHub Actions +- **Orchestration**: Kubernetes +- **Scripting**: Bash +- **Platform**: Linux --- -### Phase 2: Security and Identity Configuration - -The deployment pipeline utilizes OpenID Connect (OIDC) for secure, keyless authentication between GitHub and AWS. - -1. **IAM Identity Provider**: - - Provider URL: `https://token.actions.githubusercontent.com` - - Audience: `sts.amazonaws.com` - - ![identity-provider](screenshots/10.png) +## 🔄 DevOps Pipeline -2. **Deployment Role**: - - Click on created `Identity provider` - - Asign & Create a role named `GitHubActionsRole`. - - Enter following details: - - `Identity provider`: Select created one. - - `Audience`: Select created one. - - `GitHub organization`: Your GitHub Username or Orgs Name where this repo is located. - - `GitHub repository`: Write the Repository name of this project. `(e.g, DevSecOps-Bankapp)` - - `GitHub branch`: branch to use for this project `(e.g, devsecops)` - - Click on `Next` +The application follows an automated pipeline: - ![role](screenshots/11.png) - - - Assign `AmazonEC2ContainerRegistryPowerUser` permissions. - - ![iam permission](screenshots/12.png) - - - Click on `Next`, Enter name of role and click on `Create role`. - - ![iam role](screenshots/13.png) +1. Code pushed to GitHub repository +2. GitHub Actions pipeline is triggered +3. Application is built and validated +4. Docker image is created +5. Security scan is performed on the image +6. Application is deployed to Kubernetes cluster --- -### Phase 3: Secrets and Pipeline Configuration - -#### 1. AWS Secrets Manager -Create a secret named `bankapp/prod-secrets` in `Other type of secret` with the following key-value pairs: - -| Secret Key | Description | Sample/Default Value | -| :--- | :--- | :--- | -| `DB_HOST` | The MySQL container service name | `db` | -| `DB_PORT` | The database port | `3306` | -| `DB_NAME` | The application database name | `bankappdb` | -| `DB_USER` | The database username | `bankuser` | -| `DB_PASSWORD` | The database password | `Test@123` | -| `OLLAMA_URL` | The private URL for the AI tier | `http://:11434` | - -![aws-ssm](screenshots/14.png) - -#### 2. GitHub Repository Secrets -Configure the following Action Secrets within your GitHub repository settings: - -| Secret Name | Description | -| :--- | :--- | -| `AWS_ROLE_ARN` | The ARN of the `GitHubActionsRole` | -| `AWS_REGION` | The AWS region where resources are deployed | -| `AWS_ACCOUNT_ID` | Your 12-digit AWS account number | -| `ECR_REPOSITORY` | The name of the ECR repository (`devsecops-bankapp`) | -| `EC2_HOST` | The public IP address of the Application EC2 | -| `EC2_USER` | The SSH username (default is `ubuntu`) | -| `EC2_SSH_KEY` | The content of your private SSH key (`.pem` file) | -| `NVD_API_KEY` | Free API key from [nvd.nist.gov](https://nvd.nist.gov/developers/request-an-api-key) for OWASP SCA scans | - -> **Note**: The `NVD_API_KEY` raises the NVD API rate limit from ~5 requests/30s to 50 requests/30s, reducing the OWASP Dependency Check scan time from 30+ minutes to under 8 minutes. Without it the SCA job will time out. - -#### Obtaining the NVD API Key - -**Step 1: Request the API Key** -- Go to [https://nvd.nist.gov/developers/request-an-api-key](https://nvd.nist.gov/developers/request-an-api-key). -- Enter your `Organzation name`, `email address`, and select `organization type`. -- Accept **Terms of Use** and Click **Submit**. - - ![request](screenshots/22.png) - -**Step 2: Activate the API Key** -- Check your email inbox for a message from `nvd-noreply@nist.gov`. - - ![email](screenshots/25.png) +## 🔐 DevSecOps Integration -- Click the **activation link** in the email. -- Enter `UUID` provided in email and Enter `Email` to activate -- The link confirms your key and marks it as active. - - ![api-activate](screenshots/23.png) - -**Step 3: Get the API Key** -- After clicking the activation link, the page will generate your API key. -- Copy and save it securely. - - ![api-key](screenshots/24.png) - -**Step 4: Add as GitHub Secret** -- Go to your repository on GitHub. -- Navigate to **Settings** → **Secrets and variables** → **Actions** → **New repository secret**. -- Name: `NVD_API_KEY` -- Value: Paste the copied API key. -- Click **Add Secret**. - -![github-secret](screenshots/15.png) +- Container vulnerability scanning (Trivy) +- Basic pipeline security checks +- Ensures only secure builds are deployed --- -## Continuous Integration and Deployment - -The DevSecOps lifecycle is orchestrated through the [DevSecOps Main Pipeline](.github/workflows/devsecops-main.yml), which securely sequences three modular workflows: [CI](.github/workflows/ci.yml), [Build](.github/workflows/build.yml), and [CD](.github/workflows/cd.yml). Together they enforce **9 sequential security gates** before any code reaches production. Every `git push` to the `main` or `devsecops` branch triggers the full pipeline automatically. - -| Gate | Job | Tool | Action | -| :---: | :--- | :--- | :--- | -| 1 | `gitleaks` | Gitleaks | **Strict**: Fails if any secrets are found in history. | -| 2 | `lint` | Checkstyle | **Audit**: Reports style violations but doesn't block (Google Style). | -| 3 | `sast` | Semgrep | **Strict**: Scans code for vulnerabilities. Fails on findings. | -| 4 | `sca` | OWASP Dependency Check | **Strict**: Fails if any dependency has CVSS > 7.0. | -| 5 | `build` | Maven | Standard build and test stage. | -| 6 | `image_scan` | Trivy | **Strict**: Scans Docker image layers. Fails on any High/Critical CVE. | -| 7 | `push_to_ecr` | Amazon ECR | Pushes the verified image to AWS ECR using OIDC. | -| 8 | `deploy` | SSH / Docker Compose | Fetches secrets from AWS Secrets Manager and recreates the container. | -| 9 | `dast` | OWASP ZAP | **Audit Mode**: Comprehensive scan that reports findings as artifacts, but does not block the pipeline. | +## 📦 Project Implementation (5-Day Plan) -All scan reports (OWASP, Trivy, ZAP) are uploaded as downloadable **Artifacts** in each GitHub Actions run, YOu can look into the **Artifacts**. +This project is being built step-by-step: -- CI/CD +- **Day 1**: Dockerization of application +- **Day 2**: CI/CD pipeline implementation +- **Day 3**: DevSecOps integration +- **Day 4**: Kubernetes deployment +- **Day 5**: Final optimization and documentation - ![github-actions](screenshots/16.png) - -- Artifacts - - ![artifacts](screenshots/26.png) - --- -## Operational Verification +## 📊 Key Features -- **Process Status**: `docker ps` +- Automated CI/CD pipeline +- Containerized application deployment +- Security integrated into pipeline +- Kubernetes-based orchestration +- Scalable and self-healing architecture - ![docker ps](screenshots/19.png) +--- -- **Application Working**: +## 📸 Screenshots +- Docker Containers creations and testing. + image +- CICD Github actions + image - ![app](screenshots/20.png) -- **Database Connectivity**: +--- - ```bash - docker exec -it db mysql -u -p bankappdb -e "SELECT * FROM accounts;" - ``` +## 🤝 Credits - ![mysql-result](screenshots/17.png) +Base application sourced from an open-source repository: +https://github.com/TrainWithShubham/AI-BankApp-DevOps - > **ZAP** is automatically created by **DAST - OWASP ZAP Baseline Scan** job in [cd.yml](.github/workflows/cd.yml). Read more about it(How, Why it does) on google... +Enhanced with DevOps practices including containerization, CI/CD, security scanning, and Kubernetes deployment. -- **Network Validation**: +--- - ```bash - nc -zv 11434 - ``` +## 📬 Connect With Me - ![ollama-success](screenshots/18.png) +- GitHub: https://github.com/Sachin8801 +- LinkedIn: https://linkedin.com/in/sachin-singh-8166b3134 --- -
- -Happy Learning - -**TrainWithShubham** +## 🚀 Note -
\ No newline at end of file +This project is part of my transition from System Administration to DevOps Engineering, focusing on building real-world, production-style DevOps workflows. diff --git a/app-tier.yml b/app-tier.yml deleted file mode 100644 index 21a6bf9..0000000 --- a/app-tier.yml +++ /dev/null @@ -1,47 +0,0 @@ -services: - db: - image: mysql:8.0 - container_name: db - environment: - MYSQL_ROOT_PASSWORD: ${DB_PASSWORD} - MYSQL_DATABASE: ${DB_NAME} - MYSQL_USER: ${DB_USER} - MYSQL_PASSWORD: ${DB_PASSWORD} - ports: - - "3306:3306" - volumes: - - mysql-data:/var/lib/mysql - restart: always - networks: - - bankapp-net - healthcheck: - test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] - interval: 10s - timeout: 5s - retries: 5 - - bankapp: - image: ${ECR_REGISTRY}/${ECR_REPOSITORY}:${IMAGE_TAG} - container_name: bankapp - ports: - - "8080:8080" - environment: - MYSQL_HOST: db - MYSQL_PORT: ${DB_PORT:-3306} - MYSQL_DATABASE: ${DB_NAME} - MYSQL_USER: ${DB_USER} - MYSQL_PASSWORD: ${DB_PASSWORD} - OLLAMA_URL: ${OLLAMA_URL} - depends_on: - db: - condition: service_healthy - restart: always - networks: - - bankapp-net - -networks: - bankapp-net: - driver: bridge - -volumes: - mysql-data: diff --git a/docker-compose.yml b/docker-compose.yml index 2220669..2a372d3 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,77 +1,68 @@ +version: '3.9' + +networks: + bankapp-net: + +volumes: + mysql-data: + ollama-data: + + services: + mysql: image: mysql:8.0 - container_name: bankapp-mysql + container_name: bank_app environment: - MYSQL_ROOT_PASSWORD: Test@123 - MYSQL_DATABASE: bankappdb - ports: + MYSQL_DATABASE: ${MYSQL_DATABASE} + MYSQL_ROOT_USER: ${MYSQL_ROOT_USER} + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} + ports: - "3306:3306" volumes: - mysql-data:/var/lib/mysql + networks: + - bankapp-net healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] - interval: 10s + interval: 3s timeout: 5s - retries: 5 - start_period: 30s - networks: - - bankapp-net + retries: 10 + start_period: 10s + ollama: image: ollama/ollama - container_name: bankapp-ollama + container_name: ollama ports: - "11434:11434" - volumes: - - ollama-data:/root/.ollama + networks: + - bankapp-net healthcheck: test: ["CMD", "ollama", "list"] - interval: 10s + interval: 5s timeout: 5s - retries: 5 - networks: - - bankapp-net + retries: 15 + start_period: 30s - ollama-pull-model: - image: ollama/ollama - container_name: ollama-pull-model - environment: - - OLLAMA_HOST=ollama - volumes: - - ollama-data:/root/.ollama - depends_on: - ollama: - condition: service_healthy - entrypoint: /bin/sh - command: -c "ollama pull tinyllama" - networks: - - bankapp-net - bankapp: + bank-app: build: . container_name: bankapp ports: - - "8080:8080" - environment: - MYSQL_HOST: mysql - MYSQL_PORT: 3306 - MYSQL_DATABASE: bankappdb - MYSQL_USER: root - MYSQL_PASSWORD: Test@123 - OLLAMA_URL: http://ollama:11434 + - "80:8080" depends_on: mysql: condition: service_healthy - ollama-pull-model: - condition: service_completed_successfully + ollama: + condition: service_healthy + + environment: + MYSQL_HOST: ${MYSQL_HOST} + MYSQL_PORT: ${MYSQL_PORT} + MYSQL_DATABASE: ${MYSQL_DATABASE} + MYSQL_USER: ${MYSQL_USER} + MYSQL_PASSWORD: ${MYSQL_PASSWORD} + OLLAMA_URL: ${OLLAMA_URL} networks: - - bankapp-net - -volumes: - mysql-data: - ollama-data: - -networks: - bankapp-net: - driver: bridge + - bankapp-net \ No newline at end of file diff --git a/pom.xml b/pom.xml index ebe89b7..85180a2 100644 --- a/pom.xml +++ b/pom.xml @@ -33,6 +33,42 @@ 2.18.6 + + + + + + com.fasterxml.jackson + jackson-bom + 2.18.6 + pom + import + + + + + commons-io + commons-io + 2.14.0 + + + + + org.assertj + assertj-core + 3.27.7 + test + + + + + org.apache.tomcat.embed + tomcat-embed-core + 10.1.52 + + + + org.springframework.boot @@ -76,12 +112,23 @@ org.springframework.boot spring-boot-starter-test test + + + commons-io + commons-io + + org.springframework.security spring-security-test test + + com.h2database + h2 + test + diff --git a/screenshots/1.png b/screenshots/1.png deleted file mode 100644 index b0c823a..0000000 Binary files a/screenshots/1.png and /dev/null differ diff --git a/screenshots/10.png b/screenshots/10.png deleted file mode 100644 index 46b032d..0000000 Binary files a/screenshots/10.png and /dev/null differ diff --git a/screenshots/11.png b/screenshots/11.png deleted file mode 100644 index 8640dfc..0000000 Binary files a/screenshots/11.png and /dev/null differ diff --git a/screenshots/12.png b/screenshots/12.png deleted file mode 100644 index 3cfe83a..0000000 Binary files a/screenshots/12.png and /dev/null differ diff --git a/screenshots/13.png b/screenshots/13.png deleted file mode 100644 index 9ea11a8..0000000 Binary files a/screenshots/13.png and /dev/null differ diff --git a/screenshots/14.png b/screenshots/14.png deleted file mode 100644 index 3113269..0000000 Binary files a/screenshots/14.png and /dev/null differ diff --git a/screenshots/15.png b/screenshots/15.png deleted file mode 100644 index cb8113f..0000000 Binary files a/screenshots/15.png and /dev/null differ diff --git a/screenshots/16.png b/screenshots/16.png deleted file mode 100644 index 33b0436..0000000 Binary files a/screenshots/16.png and /dev/null differ diff --git a/screenshots/17.png b/screenshots/17.png deleted file mode 100644 index 2159b9b..0000000 Binary files a/screenshots/17.png and /dev/null differ diff --git a/screenshots/18.png b/screenshots/18.png deleted file mode 100644 index c42caf8..0000000 Binary files a/screenshots/18.png and /dev/null differ diff --git a/screenshots/19.png b/screenshots/19.png deleted file mode 100644 index 47cce8e..0000000 Binary files a/screenshots/19.png and /dev/null differ diff --git a/screenshots/2.png b/screenshots/2.png deleted file mode 100644 index 236829b..0000000 Binary files a/screenshots/2.png and /dev/null differ diff --git a/screenshots/20.png b/screenshots/20.png deleted file mode 100644 index 9a472bd..0000000 Binary files a/screenshots/20.png and /dev/null differ diff --git a/screenshots/21.png b/screenshots/21.png deleted file mode 100644 index 180e0d5..0000000 Binary files a/screenshots/21.png and /dev/null differ diff --git a/screenshots/22.png b/screenshots/22.png deleted file mode 100644 index 16fc627..0000000 Binary files a/screenshots/22.png and /dev/null differ diff --git a/screenshots/23.png b/screenshots/23.png deleted file mode 100644 index a880c93..0000000 Binary files a/screenshots/23.png and /dev/null differ diff --git a/screenshots/24.png b/screenshots/24.png deleted file mode 100644 index ff440bb..0000000 Binary files a/screenshots/24.png and /dev/null differ diff --git a/screenshots/25.png b/screenshots/25.png deleted file mode 100644 index bcaa20b..0000000 Binary files a/screenshots/25.png and /dev/null differ diff --git a/screenshots/26.png b/screenshots/26.png deleted file mode 100644 index f8f473e..0000000 Binary files a/screenshots/26.png and /dev/null differ diff --git a/screenshots/3.png b/screenshots/3.png deleted file mode 100644 index c5f9ab1..0000000 Binary files a/screenshots/3.png and /dev/null differ diff --git a/screenshots/4.png b/screenshots/4.png deleted file mode 100644 index 95530eb..0000000 Binary files a/screenshots/4.png and /dev/null differ diff --git a/screenshots/5.png b/screenshots/5.png deleted file mode 100644 index 5135050..0000000 Binary files a/screenshots/5.png and /dev/null differ diff --git a/screenshots/6.png b/screenshots/6.png deleted file mode 100644 index 2e966bc..0000000 Binary files a/screenshots/6.png and /dev/null differ diff --git a/screenshots/7.png b/screenshots/7.png deleted file mode 100644 index 8452559..0000000 Binary files a/screenshots/7.png and /dev/null differ diff --git a/screenshots/8.png b/screenshots/8.png deleted file mode 100644 index 647947c..0000000 Binary files a/screenshots/8.png and /dev/null differ diff --git a/screenshots/9.png b/screenshots/9.png deleted file mode 100644 index f61115b..0000000 Binary files a/screenshots/9.png and /dev/null differ diff --git a/setup-k8s/bank-app/deployment.yaml b/setup-k8s/bank-app/deployment.yaml new file mode 100644 index 0000000..5b640d2 --- /dev/null +++ b/setup-k8s/bank-app/deployment.yaml @@ -0,0 +1,96 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: bankapp-deployment + namespace: bank-app + labels: + app: bankapp + tier: backend + +spec: + replicas: 2 + + strategy: + type: RollingUpdate + rollingUpdate: + maxUnavailable: 0 + maxSurge: 1 + + selector: + matchLabels: + app: bankapp + + template: + metadata: + labels: + app: bankapp + + spec: + containers: + - name: bankapp + image: sachin8801/bankapp:v1 + imagePullPolicy: Always + + ports: + - containerPort: 8080 + + env: + - name: MYSQL_HOST + value: mysql-service + + - name: MYSQL_PORT + value: "3306" + + - name: MYSQL_DATABASE + valueFrom: + configMapKeyRef: + name: bankapp-configmap + key: MYSQL_DATABASE + + - name: MYSQL_USER + valueFrom: + secretKeyRef: + name: bankapp-secrets + key: MYSQL_USER + + - name: MYSQL_PASSWORD + valueFrom: + secretKeyRef: + name: bankapp-secrets + key: MYSQL_PASSWORD + + - name: OLLAMA_URL + value: http://ollama-service:11434 + + resources: + requests: + memory: "256Mi" + cpu: "250m" + limits: + memory: "512Mi" + cpu: "500m" + + startupProbe: + httpGet: + path: /actuator/health + port: 8080 + failureThreshold: 30 + periodSeconds: 10 + + livenessProbe: + httpGet: + path: /actuator/health + port: 8080 + initialDelaySeconds: 40 + periodSeconds: 10 + + readinessProbe: + httpGet: + path: /actuator/health + port: 8080 + initialDelaySeconds: 30 + periodSeconds: 5 + + securityContext: + runAsNonRoot: true + runAsUser: 1000 diff --git a/setup-k8s/bank-app/service.yaml b/setup-k8s/bank-app/service.yaml new file mode 100644 index 0000000..78209df --- /dev/null +++ b/setup-k8s/bank-app/service.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Service +metadata: + name: bankapp-service + namespace: bank-app +spec: + type: NodePort + selector: + app: bankapp + ports: + - port: 80 + targetPort: 8080 + nodePort: 30007 \ No newline at end of file diff --git a/setup-k8s/configmap.yaml b/setup-k8s/configmap.yaml new file mode 100644 index 0000000..317fe0e --- /dev/null +++ b/setup-k8s/configmap.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: bankapp-configmap + namespace: bank-app +data: + MYSQL_DATABASE: bankappdb + MYSQL_HOST: mysql-service + MYSQL_PORT: "3306" \ No newline at end of file diff --git a/setup-k8s/mysql/deployment.yaml b/setup-k8s/mysql/deployment.yaml new file mode 100644 index 0000000..a1e588d --- /dev/null +++ b/setup-k8s/mysql/deployment.yaml @@ -0,0 +1,51 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mysql-deployment + namespace: bank-app +spec: + replicas: 1 + selector: + matchLabels: + app: mysql + template: + metadata: + labels: + app: mysql + spec: + containers: + - name: mysql + image: mysql:8.0 + + ports: + - containerPort: 3306 + + env: + - name: MYSQL_DATABASE + valueFrom: + configMapKeyRef: + name: bankapp-configmap + key: MYSQL_DATABASE + + - name: MYSQL_ROOT_PASSWORD + valueFrom: + secretKeyRef: + name: bankapp-secrets + key: MYSQL_ROOT_PASSWORD + + resources: + requests: + memory: "256Mi" + cpu: "250m" + limits: + memory: "512Mi" + cpu: "500m" + + volumeMounts: + - name: mysql-storage + mountPath: /var/lib/mysql + + volumes: + - name: mysql-storage + persistentVolumeClaim: + claimName: mysql-pvc \ No newline at end of file diff --git a/setup-k8s/mysql/pv.yaml b/setup-k8s/mysql/pv.yaml new file mode 100644 index 0000000..1a4bc97 --- /dev/null +++ b/setup-k8s/mysql/pv.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + name: mysql-pv +spec: + capacity: + storage: 1Gi + accessModes: + - ReadWriteOnce + hostPath: + path: /mnt/data/mysql \ No newline at end of file diff --git a/setup-k8s/mysql/pvc.yaml b/setup-k8s/mysql/pvc.yaml new file mode 100644 index 0000000..8180a3c --- /dev/null +++ b/setup-k8s/mysql/pvc.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: mysql-pvc + namespace: bank-app +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/setup-k8s/mysql/service.yaml b/setup-k8s/mysql/service.yaml new file mode 100644 index 0000000..da81cf9 --- /dev/null +++ b/setup-k8s/mysql/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: mysql-service + namespace: bank-app +spec: + type: ClusterIP + selector: + app: mysql + ports: + - port: 3306 + targetPort: 3306 \ No newline at end of file diff --git a/setup-k8s/namespace.yaml b/setup-k8s/namespace.yaml new file mode 100644 index 0000000..fe6cfb1 --- /dev/null +++ b/setup-k8s/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: bank-app \ No newline at end of file diff --git a/setup-k8s/ollama/deployment.yaml b/setup-k8s/ollama/deployment.yaml new file mode 100644 index 0000000..05543dc --- /dev/null +++ b/setup-k8s/ollama/deployment.yaml @@ -0,0 +1,29 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: ollama + namespace: bank-app +spec: + replicas: 1 + selector: + matchLabels: + app: ollama + template: + metadata: + labels: + app: ollama + spec: + containers: + - name: ollama + image: ollama/ollama + + ports: + - containerPort: 11434 + + resources: + requests: + memory: "512Mi" + cpu: "500m" + limits: + memory: "1Gi" + cpu: "1" \ No newline at end of file diff --git a/setup-k8s/ollama/service.yaml b/setup-k8s/ollama/service.yaml new file mode 100644 index 0000000..ab9a992 --- /dev/null +++ b/setup-k8s/ollama/service.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Service +metadata: + name: ollama-service + namespace: bank-app +spec: + selector: + app: ollama + ports: + - port: 11434 + targetPort: 11434 \ No newline at end of file diff --git a/setup-k8s/secrets.yaml b/setup-k8s/secrets.yaml new file mode 100644 index 0000000..2fe5768 --- /dev/null +++ b/setup-k8s/secrets.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Secret +metadata: + name: bankapp-secrets + namespace: bank-app +type: Opaque +data: + MYSQL_ROOT_PASSWORD: VGVzdEAxMjM= + MYSQL_USER: cm9vdA== + MYSQL_PASSWORD: VGVzdEAxMjM= \ No newline at end of file diff --git a/setup-k8s/test.yaml b/setup-k8s/test.yaml new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/setup-k8s/test.yaml @@ -0,0 +1 @@ + diff --git a/src/test/java/com/example/bankapp/BankappApplicationTests.java b/src/test/java/com/example/bankapp/BankappApplicationTests.java index 63c64e9..6184e84 100644 --- a/src/test/java/com/example/bankapp/BankappApplicationTests.java +++ b/src/test/java/com/example/bankapp/BankappApplicationTests.java @@ -2,8 +2,10 @@ import org.junit.jupiter.api.Test; import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; @SpringBootTest +@ActiveProfiles("test") class BankappApplicationTests { @Test diff --git a/src/test/resources/application-test.properties b/src/test/resources/application-test.properties new file mode 100644 index 0000000..6fc2827 --- /dev/null +++ b/src/test/resources/application-test.properties @@ -0,0 +1,10 @@ +spring.datasource.url=jdbc:h2:mem:testdb +spring.datasource.driver-class-name=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password= + +spring.jpa.database-platform=org.hibernate.dialect.H2Dialect +spring.jpa.hibernate.ddl-auto=update + +# Disable external dependencies +ollama.url=http://localhost:11434 \ No newline at end of file diff --git a/suppression.xml b/suppression.xml deleted file mode 100644 index 6a91c65..0000000 --- a/suppression.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - False positive: CVE-2025-68161 only affects log4j-core, not log4j-api - ^pkg:maven/org\.apache\.logging\.log4j/log4j\-api@.*$ - CVE-2025-68161 - - diff --git a/terraform/main.tf b/terraform/main.tf new file mode 100644 index 0000000..128bfa1 --- /dev/null +++ b/terraform/main.tf @@ -0,0 +1,57 @@ +provider "aws" { + region = "ap-south-1" +} + +resource "aws_security_group" "k8s_sg" { + name = "k8s-sg" + + ingress { + from_port = 22 + to_port = 22 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = 6443 + to_port = 6443 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + ingress { + from_port = 30000 + to_port = 32767 + protocol = "tcp" + cidr_blocks = ["0.0.0.0/0"] + } + + egress { + from_port = 0 + to_port = 0 + protocol = "-1" + cidr_blocks = ["0.0.0.0/0"] + } +} + +resource "aws_instance" "k8s_server" { + ami = "ami-0f58b397bc5c1f2e8" + instance_type = "t2.medium" + key_name = var.key_name + + vpc_security_group_ids = [aws_security_group.k8s_sg.id] + + user_data = <<-EOF + #!/bin/bash + apt update -y + apt install -y docker.io curl + systemctl start docker + systemctl enable docker + + # Install K3s + curl -sfL https://get.k3s.io | sh - + + # Wait for cluster + sleep 60 + EOF +} diff --git a/terraform/outputs.tf b/terraform/outputs.tf new file mode 100644 index 0000000..7187764 --- /dev/null +++ b/terraform/outputs.tf @@ -0,0 +1,3 @@ +output "public_ip" { + value = aws_instance.k8s_server.public_ip +} diff --git a/terraform/terraform.tfvars b/terraform/terraform.tfvars new file mode 100644 index 0000000..1af6ee3 --- /dev/null +++ b/terraform/terraform.tfvars @@ -0,0 +1 @@ +key_name = "bankapp-key" \ No newline at end of file diff --git a/terraform/variables.tf b/terraform/variables.tf new file mode 100644 index 0000000..d71dde0 --- /dev/null +++ b/terraform/variables.tf @@ -0,0 +1,4 @@ +variable "key_name" { + description = "AWS key pair name" + type = string +} \ No newline at end of file diff --git a/trivy.yaml b/trivy.yaml deleted file mode 100644 index c7ca33f..0000000 --- a/trivy.yaml +++ /dev/null @@ -1,10 +0,0 @@ -cache: - dir: ~/.cache/trivy - -db: - no-progress: false - -vulnerability: - ignore-unfixed: true - severity: - - CRITICAL