Skip to content

Commit cd3db53

Browse files
feature: compliance-as-code — control-to-regulation mapping + ITGC-SEC-06 remediation and CI gate
- audit/compliance/gpn_control_mapping.md: RACM controls mapped to PCI DSS 4.0, SOX (ICFR), GDPR with PASS/FAIL and file:line evidence - Remediate ITGC-SEC-06: externalize DB credentials from application.properties to env (no committed password) - CredentialManagementControlTest: re-performs ITGC-SEC-06 (proves control now passes) - .github/workflows/compliance-gate.yml + audit/compliance/ci/check_committed_secrets.sh: CI gate that fails build if a secret is re-committed Co-Authored-By: Achal Channarasappa <achal.channarasappa@cognition.ai>
1 parent d3b5984 commit cd3db53

5 files changed

Lines changed: 282 additions & 3 deletions

File tree

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
name: compliance-gate
2+
3+
# Wires audit control re-performance into CI as a merge gate (mirrors
4+
# audit/ccm/continuous-controls-monitoring.md). Fails the build if a remediated
5+
# control regresses. Currently gates ITGC-SEC-06 (Credential & secrets management):
6+
# PCI DSS 4.0 Req 8.6.2, SOX ICFR, GDPR Art. 32.
7+
8+
on:
9+
push:
10+
branches: ["**"]
11+
pull_request:
12+
13+
jobs:
14+
itgc-sec-06-credentials:
15+
name: ITGC-SEC-06 — no committed credentials
16+
runs-on: ubuntu-latest
17+
steps:
18+
- uses: actions/checkout@v4
19+
20+
- name: Fast scan for committed secrets (bash gate)
21+
run: bash audit/compliance/ci/check_committed_secrets.sh
22+
23+
- name: Set up JDK 17
24+
uses: actions/setup-java@v4
25+
with:
26+
distribution: temurin
27+
java-version: "17"
28+
cache: maven
29+
30+
- name: Re-perform control test (CredentialManagementControlTest)
31+
run: ./mvnw -B -ntp -Dtest=CredentialManagementControlTest -DfailIfNoTests=false test
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#!/usr/bin/env bash
2+
# =============================================================================
3+
# Compliance CI gate for control ITGC-SEC-06 (Credential & secrets management).
4+
# Regulations: PCI DSS 4.0 Req 8.6.2 / Req 2.2, SOX ICFR, GDPR Art. 32.
5+
#
6+
# Fails the build if committed configuration contains a hard-coded credential
7+
# instead of an environment-injected ${ENV} placeholder. Lightweight: pure bash,
8+
# no JVM/DB required, so it can run first as a fast pre-check in CI.
9+
# =============================================================================
10+
set -euo pipefail
11+
12+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
13+
CONFIG="$REPO_ROOT/src/main/resources/application.properties"
14+
15+
fail() { echo "FAIL [ITGC-SEC-06] $*" >&2; exit 1; }
16+
17+
[ -f "$CONFIG" ] || fail "config not found: $CONFIG"
18+
19+
# 1) The previously-committed DB password must never reappear.
20+
if grep -q 'Test@123' "$CONFIG"; then
21+
fail "hard-coded DB password 'Test@123' found in application.properties"
22+
fi
23+
24+
# 2) Any secret-bearing property must be a bare \${ENV} reference (no literal, no inline default).
25+
# Matches keys containing password/passwd/secret/token/apikey.
26+
while IFS= read -r line; do
27+
key="${line%%=*}"
28+
val="${line#*=}"
29+
# trim whitespace
30+
val="$(echo "$val" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
31+
if [[ ! "$val" =~ ^\$\{[A-Za-z0-9_.]+\}$ ]]; then
32+
fail "secret-bearing property '$key' is not a bare \${ENV} reference: '$val'"
33+
fi
34+
done < <(grep -iE '^[[:space:]]*[^#][^=]*(password|passwd|secret|token|apikey|api[-_.]?key)[^=]*=' "$CONFIG" || true)
35+
36+
echo "PASS [ITGC-SEC-06] no committed credentials in application.properties"
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# Control-to-Regulation Mapping — BankApp (Springboot-BankApp)
2+
3+
> **Engagement:** Compliance-as-code demo for a payments customer (Global Payments).
4+
> **Approach:** Map a [FINOS Common Cloud Controls](https://github.com/finos/common-cloud-controls)-style
5+
> control catalogue (this repo's `audit/racm.yaml`) to the payments regulations that
6+
> govern a card-processing / payments platform, then **re-perform each control against the
7+
> actual code** and record a PASS / FAIL result with `file:line` evidence.
8+
>
9+
> **Auditee:** `COG-GTM/Springboot-BankApp` — a Spring Boot banking/payments application.
10+
> **Control source of truth:** `audit/racm.yaml` (11 controls, Group Audit RACM ontology).
11+
> **Result basis:** design + operating effectiveness, tested by inspection / re-performance.
12+
> Every assertion cites `file:line`. Line numbers reference the code at the time of writing.
13+
14+
## Regulations in scope (mapped to)
15+
16+
| Tag | Regulation | Why it applies to a payments platform |
17+
|---|---|---|
18+
| **PCI DSS 4.0** | Payment Card Industry Data Security Standard v4.0 | Cardholder-data environment: secure coding (Req 6), access control (Req 7/8), secure config & stored-data protection (Req 2/3), logging (Req 10). |
19+
| **SOX (ICFR)** | Sarbanes-Oxley §302/§404 — Internal Control over Financial Reporting | Money-movement code and the systems that change it are ICFR-relevant: completeness/accuracy of financial transactions, segregation of duties, change management. |
20+
| **GDPR** | UK GDPR / DPA 2018 | Customer account data is personal data: Art. 32 (security of processing — confidentiality & integrity), Art. 5(1)(d)/(f) (accuracy, integrity & confidentiality), Art. 33 (breach detection). |
21+
22+
Nature legend: `preventive` / `detective` / `corrective` · `automated` / `manual` / `hybrid` · `key` = key control.
23+
24+
---
25+
26+
## Control-to-regulation matrix
27+
28+
| Control ID | Objective (short) | Nature | PCI DSS 4.0 | SOX (ICFR) | GDPR | Result | Sev | Evidence (`file:line`) |
29+
|---|---|---|---|---|---|---|---|---|
30+
| **APP-TXN-01** | Monetary amounts validated positive & in-bounds before posting | preventive · automated · key | Req 6.2.4 (secure coding — business-logic flaws) | §404 — completeness & accuracy of transactions | Art. 5(1)(d) accuracy; Art. 32(1)(b) integrity | **FAIL** | High | `service/AccountService.java:51-62` (deposit), `:64-78` (withdraw), `:103-135` (transfer); `controller/BankController.java:50-96` |
31+
| **APP-TXN-02** | Transfers execute atomically (one transaction boundary) | preventive · automated · key | Req 6.2.4 (secure coding) | §404 — accuracy & reconcilability of balances | Art. 32(1)(b) integrity | **FAIL** | High | `service/AccountService.java:103-135` (4 writes, no `@Transactional`; debit `:113`, credit `:117`) |
32+
| **APP-TXN-03** | Limits + maker-checker on high-value transfers | preventive · hybrid · key | Req 7.2 (least privilege / authorization) | §404 — authorization of transactions | Art. 32 | **FAIL** | High | `service/AccountService.java:103-135` (no limit / second-approver); `controller/BankController.java:82-96` |
33+
| **APP-ACC-04** | Role-based access & segregation of duties | preventive · automated · key | Req 7.2 / 7.3 (RBAC, least privilege) | §404 — segregation of duties | Art. 32; Art. 5(1)(f) | **FAIL** | Medium | `service/AccountService.java:99-101` (single hardcoded `"USER"` authority); `config/SecurityConfig.java:31-34` (no role-restricted endpoints) |
34+
| **APP-SEC-05** | State-changing endpoints protected (CSRF) | preventive · automated | Req 6.2.4 (secure coding — CSRF is a named attack) | §404 — integrity of financial transactions | Art. 32 | **FAIL** | Medium | `config/SecurityConfig.java:30` (`csrf.disable()`); endpoints `controller/BankController.java:50,58,82` |
35+
| **ITGC-SEC-06** | No secrets/credentials committed to source/config | preventive · automated · key | Req 8.6.2 (no hard-coded passwords in config/property files); Req 2.2 (secure config); Req 3.x (protect stored auth data) | §404 — access to financial systems | Art. 32(1)(b) confidentiality | **FAIL** | High | `src/main/resources/application.properties:4-5` (DB user `root` / password `Test@123` in plaintext) |
36+
| **ITGC-CM-07** | Changes independently reviewed & approved (author≠approver) | preventive · hybrid · key | Req 6.2.3 (code reviewed before release) | §404 — change management | Art. 32 (org measures) | **FAIL** | High | No `CODEOWNERS`; direct commits to default branch `DevOps` (e.g. commits `Update Jenkinsfile`, `Update bankapp-deployment.yml` in `git log`) |
37+
| **ITGC-CM-08** | Build provenance: pipeline builds the audited repo | preventive · automated · key | Req 6.3 / 6.5 (change control & provenance) | §404 — change management provenance | Art. 32 | **FAIL** | Medium | `Jenkinsfile:26` checks out `LondheShubham153/Springboot-BankApp.git` (a different upstream repo) |
38+
| **ITGC-SDLC-09** | SAST/SCA scans + automated test gate in pipeline | detective · automated · key | Req 6.3.1 (identify vulnerabilities); Req 6.2.4 | §404 — SDLC control | Art. 32 | **PARTIAL** | Medium | Strengths: `Jenkinsfile:31` (Trivy), `:39` (OWASP), `:47-61` (SonarQube gate). Gap: only test is `BankappApplicationTests.contextLoads()` (`src/test/java/com/example/bankapp/BankappApplicationTests.java:9-10`); no test-execution stage |
39+
| **ITGC-DATA-10** | Controlled schema changes (no runtime auto-mutation) | preventive · automated | Req 6.3 / 6.5 (change control) | §404 — change management | Art. 32 | **FAIL** | Medium | `src/main/resources/application.properties:9` (`spring.jpa.hibernate.ddl-auto=update`) |
40+
| **ITGC-LOG-11** | Financial/security events are audit-logged | detective · automated · key | Req 10.2 (audit logs); Req 10.3 (protect logs) | §404 — monitoring & audit trail | Art. 32; Art. 33 (breach detection) | **FAIL** | Medium | No audit logging in `service/AccountService.java:51-135`; only `spring.jpa.show-sql=true` (`application.properties:11`) which leaks SQL/data to stdout |
41+
42+
**Summary:** 11 controls tested — **10 FAIL, 1 PARTIAL, 0 PASS** at baseline.
43+
High-severity FAILs: APP-TXN-01, APP-TXN-02, APP-TXN-03, ITGC-SEC-06, ITGC-CM-07.
44+
45+
---
46+
47+
## Re-performance detail per control
48+
49+
Each control below records the **test procedure**, the **re-performed observation** against
50+
the actual code, and the **regulation rationale** for the mapping.
51+
52+
### APP-TXN-01 — Transaction amount validation — **FAIL (High)**
53+
- **Procedure:** inspect deposit/withdraw/transfer; re-perform with `0`, negative, and very large amounts.
54+
- **Observation:** `deposit` adds `amount` unconditionally (`service/AccountService.java:51-62`); `withdraw` (`:64-78`) and `transferAmount` (`:103-135`) check `balance >= amount` but never `amount > 0`. The controller passes `BigDecimal amount` straight through (`controller/BankController.java:50-96`). A **negative transfer** debits a negative (i.e. *credits* the sender) and credits a negative to the recipient — fund misappropriation.
55+
- **Mapping rationale:** PCI DSS 4.0 **Req 6.2.4** requires software to be engineered to prevent business-logic / input-tampering attacks. SOX **ICFR** requires transaction completeness & accuracy. GDPR **Art. 5(1)(d)** (accuracy) & **Art. 32(1)(b)** (integrity).
56+
57+
### APP-TXN-02 — Transfer atomicity — **FAIL (High)**
58+
- **Procedure:** inspect `transferAmount` for a transaction boundary; reason about partial-failure between debit and credit.
59+
- **Observation:** `transferAmount` performs four separate repository writes — sender save (`:113`), recipient save (`:117`), two transaction-record saves (`:126`, `:134`) — with **no `@Transactional`**. A failure after `:113` but before `:117` destroys money and leaves balances non-reconcilable.
60+
- **Mapping rationale:** PCI DSS **Req 6.2.4** (secure coding). SOX **ICFR** (accuracy/reconcilability). GDPR **Art. 32(1)(b)** (integrity of processing).
61+
62+
### APP-TXN-03 — Authorisation & dual-control on value movement — **FAIL (High)**
63+
- **Procedure:** check for per-transaction / daily limits and a second-approver step on transfers.
64+
- **Observation:** `transferAmount` (`service/AccountService.java:103-135`) enforces no limit and has no maker-checker. Any authenticated user moves any amount up to balance in one unreviewed action (`controller/BankController.java:82-96`).
65+
- **Mapping rationale:** PCI DSS **Req 7.2** (least privilege / authorized access). SOX **ICFR** (authorization of transactions). GDPR **Art. 32**.
66+
67+
### APP-ACC-04 — Role-based access & least privilege — **FAIL (Medium)**
68+
- **Procedure:** inspect granted-authorities and endpoint authorization rules.
69+
- **Observation:** `authorities()` hardcodes a single `"USER"` authority for every account (`service/AccountService.java:99-101`); `SecurityConfig` only distinguishes `permitAll` on `/register` vs `authenticated` for everything else (`config/SecurityConfig.java:31-34`) — no admin/operator segregation.
70+
- **Mapping rationale:** PCI DSS **Req 7.2 / 7.3** (RBAC, least privilege). SOX **ICFR** (segregation of duties). GDPR **Art. 32**, **Art. 5(1)(f)**.
71+
72+
### APP-SEC-05 — CSRF protection on state-changing endpoints — **FAIL (Medium)**
73+
- **Procedure:** inspect security config for CSRF on POST endpoints.
74+
- **Observation:** `SecurityConfig` calls `csrf.disable()` (`config/SecurityConfig.java:30`); `/deposit`, `/withdraw`, `/transfer` POSTs (`controller/BankController.java:50,58,82`) are exposed to cross-site request forgery.
75+
- **Mapping rationale:** PCI DSS **Req 6.2.4** explicitly names CSRF among attacks secure coding must mitigate. SOX **ICFR** (integrity of financial transactions). GDPR **Art. 32**.
76+
77+
### ITGC-SEC-06 — Credential & secrets management — **FAIL (High)***remediated in this PR*
78+
- **Procedure:** scan committed configuration for embedded credentials.
79+
- **Observation (baseline):** `application.properties:4-5` commits DB username `root` and password `Test@123` in plaintext. Anyone with repo read access obtains DB credentials.
80+
- **Mapping rationale:** PCI DSS 4.0 **Req 8.6.2** — "passwords/passphrases for application and system accounts are not hard-coded in scripts, configuration/property files, or bespoke and custom source code"; also **Req 2.2** (secure configuration) and **Req 3.x** (protect stored authentication data). SOX **ICFR** (controlled access to financial systems). GDPR **Art. 32(1)(b)** (confidentiality of processing).
81+
- **Remediation (this PR):** credentials externalised to environment variables with no committed default for the password (`application.properties:4-5`); enforced by `CredentialManagementControlTest` and the `compliance-gate` CI workflow. See `## Remediation` below.
82+
83+
### ITGC-CM-07 — Change management: independent review & approval — **FAIL (High)**
84+
- **Procedure:** inspect branch protection & CODEOWNERS; sample changes to the protected branch.
85+
- **Observation:** no `CODEOWNERS` file; `git log` on `DevOps` shows direct commits (e.g. `Update Jenkinsfile`, `Update bankapp-deployment.yml`) with no associated reviewed PR — production pipeline & k8s manifests changed without independent approval.
86+
- **Mapping rationale:** PCI DSS **Req 6.2.3** (code reviewed prior to release). SOX **ICFR** (change management). GDPR **Art. 32** (organizational measures).
87+
88+
### ITGC-CM-08 — Pipeline integrity & source traceability — **FAIL (Medium)**
89+
- **Procedure:** trace the CI checkout source against the audited repo.
90+
- **Observation:** `Jenkinsfile:26` checks out `https://github.com/LondheShubham153/Springboot-BankApp.git` (branch `DevOps`) — a different upstream repo than the one under audit. Deployed-artifact provenance is not tied to reviewed source.
91+
- **Mapping rationale:** PCI DSS **Req 6.3 / 6.5** (change control & provenance). SOX **ICFR** (change management provenance). GDPR **Art. 32**.
92+
93+
### ITGC-SDLC-09 — Secure SDLC: scanning & test gating — **PARTIAL (Medium)**
94+
- **Procedure:** inspect pipeline for SAST/SCA/filesystem scanning and a test-execution gate.
95+
- **Observation:** Trivy (`Jenkinsfile:31`), OWASP dependency-check (`:39`) and SonarQube quality gate (`:47-61`) are present. **Gap:** the only test is `contextLoads()` (`src/test/java/com/example/bankapp/BankappApplicationTests.java:9-10`) — no business-logic coverage and no test-execution stage in the pipeline.
96+
- **Mapping rationale:** PCI DSS **Req 6.3.1** (identify vulnerabilities) & **6.2.4**. SOX **ICFR** (SDLC control). GDPR **Art. 32**.
97+
- **Note:** this PR adds the first business-logic-adjacent automated test and a CI test gate (see Remediation), improving this control.
98+
99+
### ITGC-DATA-10 — Production schema/data change control — **FAIL (Medium)**
100+
- **Procedure:** inspect ORM/schema config for uncontrolled runtime auto-migration.
101+
- **Observation:** `application.properties:9` sets `spring.jpa.hibernate.ddl-auto=update` — Hibernate mutates the schema at runtime in every environment with no review or migration trail.
102+
- **Mapping rationale:** PCI DSS **Req 6.3 / 6.5** (change control). SOX **ICFR** (change management). GDPR **Art. 32**.
103+
104+
### ITGC-LOG-11 — Logging & monitoring of financial events — **FAIL (Medium)**
105+
- **Procedure:** inspect transaction paths for audit logging.
106+
- **Observation:** no audit logging around deposit/withdraw/transfer (`service/AccountService.java:51-135`). The only logging signal is `spring.jpa.show-sql=true` (`application.properties:11`), which leaks SQL to stdout and is not a protected audit trail.
107+
- **Mapping rationale:** PCI DSS **Req 10.2** (audit logs for events) & **Req 10.3** (protect logs). SOX **ICFR** (monitoring & audit trail). GDPR **Art. 32** & **Art. 33** (breach detection). The `show-sql` leak is itself a GDPR **Art. 5(1)(f)** concern.
108+
109+
---
110+
111+
## Remediation delivered in this PR (ITGC-SEC-06)
112+
113+
| Field | Value |
114+
|---|---|
115+
| **Control** | ITGC-SEC-06 — Credential & secrets management |
116+
| **Regulations** | PCI DSS 4.0 Req 8.6.2, Req 2.2, Req 3.x · SOX ICFR (§404) · GDPR Art. 32 |
117+
| **Before** | `application.properties:4-5` committed `spring.datasource.password=Test@123` (plaintext DB credentials in source control). |
118+
| **After** | Credentials read from environment variables; **no committed default for the password**`spring.datasource.password=${SPRING_DATASOURCE_PASSWORD}`. |
119+
| **Proving test** | `CredentialManagementControlTest` re-performs the control: it parses `application.properties` and fails if any credential value is a hard-coded literal rather than a `${ENV}` placeholder. |
120+
| **CI gate** | `.github/workflows/compliance-gate.yml` runs the control test on every push/PR, failing the build if the control regresses (a secret is re-committed). |
121+
122+
The control now **PASSES** (proven by the test) and is **wired into CI as a gate**, mirroring
123+
the continuous-controls-monitoring model in `audit/ccm/continuous-controls-monitoring.md`.

src/main/resources/application.properties

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
spring.application.name=bankapp
22
# MySQL Database configuration
3-
spring.datasource.url=jdbc:mysql://localhost:3306/bankappdb?useSSL=false&serverTimezone=UTC
4-
spring.datasource.username=root
5-
spring.datasource.password=Test@123
3+
# Credentials are injected from the environment / secret store — never committed (ITGC-SEC-06).
4+
# PCI DSS 4.0 Req 8.6.2, GDPR Art. 32. The password has no in-source default by design.
5+
spring.datasource.url=${SPRING_DATASOURCE_URL:jdbc:mysql://localhost:3306/bankappdb?useSSL=false&serverTimezone=UTC}
6+
spring.datasource.username=${SPRING_DATASOURCE_USERNAME:root}
7+
spring.datasource.password=${SPRING_DATASOURCE_PASSWORD}
68
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
79

810
# JPA & Hibernate configuration

0 commit comments

Comments
 (0)