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.
-
-[](https://www.oracle.com/java/technologies/javase/jdk21-archive-downloads.html)
-[](https://spring.io/projects/spring-boot)
-[](.github/workflows/devsecops.yml)
-[](#phase-3-security-and-identity-configuration)
-
-
-
-
+
+
+
+
---
+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`.
-
- 
-
-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`
-
- 
-
- - Attach it to Application EC2. Select EC2 -> Actions -> Security -> Modify IAM role -> Attach created IAM role.
-
- 
-
- - 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.
-
- 
-
- - Automate initialization using the [ollama-setup.sh](scripts/ollama-setup.sh) script via EC2 User Data.
-
- 
-
- - Verify the AI engine is responsive and the model is pulled in `AI engine EC2`:
-
- ```bash
- ollama list
- ```
-
- 
+- **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`
-
- 
+## 🔄 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:
- 
-
- - Assign `AmazonEC2ContainerRegistryPowerUser` permissions.
-
- 
-
- - Click on `Next`, Enter name of role and click on `Create role`.
-
- 
+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` |
-
-
-
-#### 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**.
-
- 
-
-**Step 2: Activate the API Key**
-- Check your email inbox for a message from `nvd-noreply@nist.gov`.
-
- 
+## 🔐 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.
-
- 
-
-**Step 3: Get the API Key**
-- After clicking the activation link, the page will generate your API key.
-- Copy and save it securely.
-
- 
-
-**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**.
-
-
+- 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
- 
-
-- Artifacts
-
- 
-
---
-## 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
- 
+---
-- **Application Working**:
+## 📸 Screenshots
+- Docker Containers creations and testing.
+
+- CICD Github actions
+
- 
-- **Database Connectivity**:
+---
- ```bash
- docker exec -it db mysql -u -p bankappdb -e "SELECT * FROM accounts;"
- ```
+## 🤝 Credits
- 
+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
- 
+- 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