feature: pipeline governance hardening — secrets, build provenance, Flyway schema control, change control, audit logging - #294
Open
achalc wants to merge 3 commits into
Conversation
…nge control, audit logging) - ITGC-SEC-06: remove committed DB credentials from application.properties, docker-compose, Kubernetes and Helm; add a blocking gitleaks gate in Jenkins and GitHub Actions - ITGC-CM-08: build and GitOps pipelines now check out the audited COG-GTM repository - ITGC-SDLC-09: Trivy/OWASP/Sonar findings above threshold and failing tests break the build - ITGC-DATA-10: replace hibernate ddl-auto=update with a Flyway baseline migration - ITGC-CM-07: add CODEOWNERS and a PR template so author != approver is enforceable - ITGC-LOG-11: structured audit logging of deposits, withdrawals and transfers with correlation ids
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
…on gate The trivy-action binary install failed on the runner; using the same pinned aquasec/trivy image as Jenkins makes CI and Jenkins reproduce each other. Secrets and vulnerabilities block at HIGH,CRITICAL; infrastructure misconfiguration blocks at CRITICAL, with the pre-existing HIGH Kubernetes pod-security findings reported rather than waived.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Change summary
Governance / DevSecOps hardening of the pipeline and the runtime controls around it. No money-movement logic is changed — every change closes an ITGC control gap and is traceable to it.
Change record / ticket: Western Union governance review (demo #4)
application.propertiesshippedroot/Test@123; the same literal was indocker-compose.yml,kubernetes/secrets.yaml(base64) andhelm/bankapp/values.yamlSPRING_DATASOURCE_USERNAME/_PASSWORD, no defaults → fail-fast startup). Compose uses${VAR:?...}, the Helm template usesrequired,kubernetes/secrets.yamlis replaced by a value-freesecrets.[REDACTED SECRET].yaml. Contract indocs/configuration-contract.md;.env.[REDACTED SECRET]+.gitignorefor local use. A blocking gitleaks stage runs in both Jenkins and GitHub Actions with a repo rule (.gitleaks.toml) that treats anyMYSQL_ROOT_PASSWORD/spring.datasource.passwordassignment as a finding unless the value is resolved outside the repo ($...,{{ }},<placeholder>, empty).JenkinsfileandGitOps/Jenkinsfilechecked outLondheShubham153/Springboot-BankApp— the pipeline was not building the audited repositoryhttps://github.com/COG-GTM/Springboot-BankApp.gitvia a singleAPP_REPO_URL/MANIFEST_REPO_URLenv var, and the CD job pushes back to the same URL. The CD manifestsedalso targetedbankapp-deployment.yaml, a file that does not exist (.yml), so the image tag was silently never updated; fixed and asserted with agrep -q.HIGH,CRITICALfor vulnerabilities and secrets and atCRITICALfor infrastructure misconfiguration, OWASP runs with--failOnCVSS 7, Sonar withwaitForQualityGate abortPipeline: true, plus./mvnw -B clean verify. Jenkins and GitHub Actions run the same pinnedaquasec/trivy:0.71.2container so a finding in one reproduces in the other. Reports are archived as build evidence. Nothing is waived: the 8 pre-existing HIGH pod-security findings inkubernetes/are reported and listed as follow-on work below instead of being silenced with a.trivyignore.spring.jpa.hibernate.ddl-auto=updatelet the running application mutate the production schemaV1__baseline_bankapp_schema.sqlmatching the current entities,ddl-auto=validate, and aflyway-maven-pluginconfiguration so a DBA can apply migrations without starting the app (./mvnw flyway:migrate)..github/CODEOWNERS(per-area owners for services, config, migrations, pipelines, k8s/Helm) and a PR template carrying the control attestations. This is only enforceable once branch protection onDevOpsrequires code-owner review, ≥1 approval and disallows bypass — that setting is outside the repo and still needs to be applied.auditlogger for deposit / withdrawal / transfer, success and failure, with actor, account ids, amount, currency, reason, timestamp and a correlation id (X-Correlation-Id, sanitised/generated byCorrelationIdFilter). No passwords, balances or full PII are logged; injected control characters are escaped so one event stays one record..github/workflows/ci.ymlruns on every PR and push toDevOps: gitleaks, then build + migrate-on-a-clean-MySQL + tests, then Trivy secret/misconfig (blocking) and dependency scanning.Change classification
Control attestations
src/main/resources/db/migration/; no existing migration was edited andspring.jpa.hibernate.ddl-autoremainsvalidate.Money movement impact
Balances, limits and authorisation are untouched;
AccountServicegains audit calls only.Rollback plan
Revert the commit. The migration is backward compatible:
V1creates the existing tablesIF NOT EXISTSand only adds aflyway_schema_historytable, so an environment that already has the schema is baselined rather than altered; reverting simply stops Flyway from running. Deployments must keep the datasource environment variables in place — after this change the application will not start with a missing credential (by design).Evidence
Build and tests (local, MySQL 8.0):
Migrations against a clean database (
CREATE DATABASE bankapp_clean→./mvnw flyway:migrate), after which the app started withddl-auto=validate, i.e. Hibernate validated the Flyway-built schema:Audit log output — real requests against the running app (deposit, withdrawal, rejected withdrawal, transfer, transfer to an unknown recipient), correlation ids supplied by the caller:
{"timestamp":"2026-08-24T13:38:55.182346675Z","event":"DEPOSIT","outcome":"SUCCESS","actor":"alice","accountId":"1","amount":"250.00","currency":"USD","correlationId":"wu-demo-0001"} {"timestamp":"2026-08-24T13:38:55.197296379Z","event":"WITHDRAWAL","outcome":"SUCCESS","actor":"alice","accountId":"1","amount":"40.00","currency":"USD","correlationId":"wu-demo-0002"} {"timestamp":"2026-08-24T13:38:55.204298531Z","event":"WITHDRAWAL","outcome":"FAILURE","actor":"alice","accountId":"1","amount":"10000.00","currency":"USD","reason":"INSUFFICIENT_FUNDS","correlationId":"wu-demo-0003"} {"timestamp":"2026-08-24T13:38:55.274072014Z","event":"TRANSFER","outcome":"SUCCESS","actor":"alice","accountId":"1","counterpartyAccountId":"2","amount":"75.00","currency":"USD","correlationId":"wu-demo-0004"} {"timestamp":"2026-08-24T13:38:55.283350993Z","event":"TRANSFER","outcome":"FAILURE","actor":"alice","accountId":"1","amount":"5.00","currency":"USD","reason":"RECIPIENT_NOT_FOUND","correlationId":"wu-demo-0005"}Secret gate proves it blocks, not just passes — clean tree scans green; re-adding
spring.datasource.password=Test@123to a properties file fails the scan:Follow-on gaps left in this PR (money-movement controls, deliberately out of scope)
amounton deposit inflates the balance and a negative transfer drains the recipient.BigDecimalamounts are taken straight from the request.src/main/java/com/[REDACTED SECRET]/bankapp/service/AccountService.java:60(deposit),:79(withdraw),:125(transfer); unvalidated request binding atsrc/main/java/com/[REDACTED SECRET]/bankapp/controller/BankController.java:51,:59,:83savecalls with no@Transactionalboundary; a failure between the debit and the credit destroys money.src/main/java/com/[REDACTED SECRET]/bankapp/service/AccountService.java:125-163(debit at:138-139, credit at:142-143)src/main/java/com/[REDACTED SECRET]/bankapp/service/AccountService.java:125anyRequest().authenticated(); no separation between customer and operator actions.src/main/java/com/[REDACTED SECRET]/bankapp/config/SecurityConfig.java:31-33POST /deposit,/withdraw,/transferendpoints are forgeable.src/main/java/com/[REDACTED SECRET]/bankapp/config/SecurityConfig.java:30| INFRA-K8S-06 — pod security context | 8 HIGH Trivy misconfiguration findings on the existing manifests: containers run with the default (root-capable) security context, no
runAsNonRoot, no resource limits. Reported by CI, not yet fixed. |kubernetes/mysql-deployment.yml:17-41,kubernetes/bankapp-deployment.yml|Also outstanding and outside a code change: the credentials in this repository's git history are disclosed and must be rotated (
docs/configuration-contract.md#rotation), and branch protection onDevOpsmust be set to require code-owner review before CODEOWNERS enforces ITGC-CM-07.Devin-Org: engineering
Link to Devin session: https://app.devin.ai/sessions/f4b7908a8b434230afc87c28e95e3f68
Requested by: @achalc
Devin Review