Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Copy to .env.local (git-ignored) and fill in locally. Never commit real values.
# See docs/configuration-contract.md.
DUSER=
IMAGE=springboot-application

MYSQL_DATABASE=BankDB
MYSQL_ROOT_PASSWORD=
SPRING_DATASOURCE_USERNAME=root
SPRING_DATASOURCE_PASSWORD=
33 changes: 33 additions & 0 deletions .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Code owners for Springboot-BankApp (control ITGC-CM-07: changes are independently
# reviewed and approved; the author of a change can never be its sole approver).
#
# GitHub enforces this only when the branch protection rule for `DevOps` has
# "Require review from Code Owners" and "Require approvals >= 1" enabled, and
# "Allow specified actors to bypass required pull requests" left empty.

# Default owner for everything not matched below.
* @COG-GTM/engineering

# Money movement and authentication: reviewed by application owners.
/src/main/java/com/example/bankapp/service/ @COG-GTM/engineering
/src/main/java/com/example/bankapp/controller/ @COG-GTM/engineering
/src/main/java/com/example/bankapp/config/ @COG-GTM/engineering

# Audit trail: changes here weaken or strengthen evidence, so they are owned by security.
/src/main/java/com/example/bankapp/audit/ @COG-GTM/engineering

# Schema changes are controlled: migrations are append-only and reviewed by data owners.
/src/main/resources/db/migration/ @COG-GTM/engineering

# Pipeline, security gates and change-control configuration.
/Jenkinsfile @COG-GTM/engineering
/GitOps/ @COG-GTM/engineering
/vars/ @COG-GTM/engineering
/.github/ @COG-GTM/engineering
/.gitleaks.toml @COG-GTM/engineering

# Deployment configuration and secret plumbing.
/kubernetes/ @COG-GTM/engineering
/helm/ @COG-GTM/engineering
/Dockerfile @COG-GTM/engineering
/docker-compose.yml @COG-GTM/engineering
32 changes: 32 additions & 0 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Change summary

<!-- What changes, and why. Link the ticket / change record. -->

Change record / ticket:

## Change classification

- [ ] Standard (pre-approved, low risk)
- [ ] Normal (requires review + approval before merge)
- [ ] Emergency (retrospective approval; state the incident reference)

## Control attestations

- [ ] **ITGC-CM-07** — I am not the approver of this change; an independent code owner will review it.
- [ ] **ITGC-SEC-06** — No credentials, tokens or keys are committed; configuration is read from the environment. The gitleaks job is green.
- [ ] **ITGC-DATA-10** — Any schema change is an append-only Flyway migration under `src/main/resources/db/migration/`; no existing migration was edited and `spring.jpa.hibernate.ddl-auto` remains `validate`.
- [ ] **ITGC-SDLC-09** — Tests and security scans pass in CI; scanner findings above threshold are fixed, not waived.
- [ ] **ITGC-LOG-11** — Financial or security-relevant behaviour changes emit audit events, and no secrets or full PII are written to logs.
- [ ] **ITGC-CM-08** — Build provenance unchanged: the pipeline still builds this repository.

## Money movement impact

- [ ] This change affects deposit, withdraw or transfer behaviour. If checked, describe the balance / limit / authorisation impact and the tests covering it:

## Rollback plan

<!-- How this change is reverted, including whether the migration is backward compatible. -->

## Evidence

<!-- Test output, audit log samples, scan reports, screenshots. -->
122 changes: 122 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
name: CI

# Change control: every pull request into a protected branch runs the test gate and the
# security scans, and every job below is a required check (ITGC-CM-07, ITGC-SDLC-09).
on:
pull_request:
branches: [DevOps]
push:
branches: [DevOps]

permissions:
contents: read

jobs:
secret-scan:
name: Secret scan (gitleaks)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run gitleaks
run: |
docker run --rm -v "$PWD:/repo" -w /repo zricethezav/gitleaks:v8.18.4 \
detect --source=/repo --no-git --config=/repo/.gitleaks.toml \
--redact --no-banner --exit-code 1 \
--report-format sarif --report-path gitleaks-report.sarif
- uses: actions/upload-artifact@v4
if: always()
with:
name: gitleaks-report
path: gitleaks-report.sarif
if-no-files-found: ignore

build-and-test:
name: Build, migrate and test
runs-on: ubuntu-latest
services:
mysql:
image: mysql:8.0
env:
# Ephemeral CI database credentials; the application itself reads them from the environment.
MYSQL_ROOT_PASSWORD: ${{ secrets.CI_MYSQL_ROOT_PASSWORD || 'ci-only-password' }}
MYSQL_DATABASE: bankappdb
ports:
- 3306:3306
options: >-
--health-cmd="mysqladmin ping -h 127.0.0.1 --silent"
--health-interval=10s
--health-timeout=5s
--health-retries=10
env:
SPRING_DATASOURCE_URL: jdbc:mysql://127.0.0.1:3306/bankappdb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
SPRING_DATASOURCE_USERNAME: root
SPRING_DATASOURCE_PASSWORD: ${{ secrets.CI_MYSQL_ROOT_PASSWORD || 'ci-only-password' }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
distribution: temurin
java-version: '17'
cache: maven
- name: Wait for MySQL
run: |
for i in $(seq 1 30); do
if mysql -h 127.0.0.1 -P 3306 -uroot -p"$SPRING_DATASOURCE_PASSWORD" -e 'SELECT 1' >/dev/null 2>&1; then
exit 0
fi
sleep 5
done
echo "MySQL did not become available" >&2
exit 1
- name: Verify migrations apply to a clean database
run: |
mysql -h 127.0.0.1 -uroot -p"$SPRING_DATASOURCE_PASSWORD" \
-e "DROP DATABASE IF EXISTS bankappdb; CREATE DATABASE bankappdb;"
chmod +x ./mvnw
./mvnw -B flyway:migrate
mysql -h 127.0.0.1 -uroot -p"$SPRING_DATASOURCE_PASSWORD" bankappdb \
-e "SELECT version, description, success FROM flyway_schema_history;"
- name: Build and test
run: ./mvnw -B clean verify
- uses: actions/upload-artifact@v4
if: always()
with:
name: surefire-reports
path: target/surefire-reports/
if-no-files-found: ignore

security-scan:
name: Dependency and config scan (Trivy)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# The pinned container is the same scanner the Jenkins pipeline runs, so a finding
# here reproduces there.
- name: Trivy secret scan (blocking on HIGH,CRITICAL)
run: |
docker run --rm -v "$PWD:/repo" -w /repo aquasec/trivy:0.71.2 \
fs --scanners secret --severity HIGH,CRITICAL --no-progress \
--offline-scan --skip-version-check --exit-code 1 /repo
# Infrastructure misconfiguration gate. CRITICAL is blocking; the HIGH findings in the
# existing Kubernetes manifests (pod security contexts) are reported and tracked as
# follow-on work rather than waived with an ignore file.
- name: Trivy misconfiguration scan (blocking on CRITICAL)
run: |
docker run --rm -v "$PWD:/repo" -w /repo aquasec/trivy:0.71.2 \
fs --scanners misconfig --severity CRITICAL --no-progress \
--offline-scan --skip-version-check --exit-code 1 /repo
- name: Trivy misconfiguration and dependency report
if: always()
run: |
docker run --rm -v "$PWD:/repo" -w /repo aquasec/trivy:0.71.2 \
fs --scanners vuln,misconfig --severity HIGH,CRITICAL --ignore-unfixed \
--no-progress --offline-scan --skip-version-check \
--format table --output /repo/trivy-dependencies.txt /repo
- uses: actions/upload-artifact@v4
if: always()
with:
name: trivy-dependency-report
path: trivy-dependencies.txt
if-no-files-found: ignore
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,12 @@ build/

### VS Code ###
.vscode/

### Local secrets (never commit) ###
.env.local
.env.*.local

### Scan reports ###
gitleaks-report.sarif
trivy-fs-report.xml
dependency-check-report.*
47 changes: 47 additions & 0 deletions .gitleaks.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Gitleaks configuration for the bank application (control ITGC-SEC-06:
# no secrets or credentials committed to source or configuration).
#
# CI scans the working tree (`--no-git`), so the gate is "no credential may be
# (re)introduced into the code base". Credentials that were committed historically are
# rotated out-of-band; see docs/configuration-contract.md.
#
# Run locally exactly as CI does:
# docker run --rm -v "$PWD:/repo" -w /repo zricethezav/gitleaks:v8.18.4 \
# detect --source=/repo --no-git --config=/repo/.gitleaks.toml --redact --no-banner --exit-code 1

title = "Springboot-BankApp secret scanning"

[extend]
useDefault = true

# A database password assignment is a finding unless its value is a reference resolved
# outside the repository: an environment/Helm/Actions interpolation ($..., {{...}}),
# a documented placeholder (<...>) or an empty value.
[[rules]]
id = "database-password-assignment"
description = "Hardcoded database password in source or configuration"
regex = '''(?i)(?:mysql_root_password|mysql_password|spring[._]datasource[._]password)[ \t]*[=:][ \t]*([^\s#][^\n#]*)'''
secretGroup = 1
tags = ["password", "database"]

[rules.allowlist]
description = "Values resolved outside the repository"
regexTarget = "secret"
regexes = [
'''^["']?\$''',
'''^["']?\{\{''',
'''^["']?<''',
'''^["']{2}\s*$''',
'''^["']?\s*$''',
]

[allowlist]
description = "Files that describe credential handling but contain no credentials"
paths = [
'''(^|/)\.gitleaks\.toml$''',
'''(^|/)docs/configuration-contract\.md$''',
'''(^|/)\.github/workflows/ci\.yml$''',
'''(^|/)README(-K8S)?\.md$''',
'''(^|/)kubernetes/README\.md$''',
'''(^|/)mvnw(\.cmd)?$''',
]
17 changes: 12 additions & 5 deletions GitOps/Jenkinsfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
pipeline {
agent any

environment{
// Manifest repository under audit; CD must update this repository and nothing else (ITGC-CM-08).
MANIFEST_REPO_URL = "https://github.com/COG-GTM/Springboot-BankApp.git"
MANIFEST_REPO_BRANCH = "DevOps"
}

parameters {
string(name: 'DOCKER_TAG', defaultValue: '', description: 'Docker tag of the image built by the CI job')
}
Expand All @@ -18,7 +24,7 @@ pipeline {
stage('Git: Code Checkout') {
steps {
script{
code_checkout("https://github.com/LondheShubham153/Springboot-BankApp.git","DevOps")
code_checkout("${env.MANIFEST_REPO_URL}","${env.MANIFEST_REPO_BRANCH}")
}
}
}
Expand All @@ -37,7 +43,8 @@ pipeline {
script{
dir('kubernetes'){
sh """
sed -i -e 's|trainwithshubham/bankapp-eks:.*|trainwithshubham/bankapp-eks:${params.DOCKER_TAG}|g' bankapp-deployment.yaml
sed -i -e 's|trainwithshubham/bankapp-eks:.*|trainwithshubham/bankapp-eks:${params.DOCKER_TAG}|g' bankapp-deployment.yml
grep -q 'trainwithshubham/bankapp-eks:${params.DOCKER_TAG}' bankapp-deployment.yml
"""
}
}
Expand All @@ -48,7 +55,7 @@ pipeline {
steps{
script{
withCredentials([gitUsernamePassword(credentialsId: 'Github-cred', gitToolName: 'Default')]) {
sh '''
sh """
echo "Checking repository status: "
git status

Expand All @@ -59,8 +66,8 @@ pipeline {
git commit -m "Updated K8s Deployment Docker Image Version"

echo "Pushing changes to github: "
git push https://github.com/LondheShubham153/Springboot-BankApp.git DevOps
'''
git push ${env.MANIFEST_REPO_URL} ${env.MANIFEST_REPO_BRANCH}
"""
}
}
}
Expand Down
Loading
Loading