Checkpoint Lab — Security Policies, Scan Execution, Pipeline Execution, Approval Policies, and Compliance Controls
Design a synthetic top-level-group policy set, predict its scope and enforcement, inject a violation and a legitimate exception, prove ownership boundaries, and clean up verified training resources.
Learning objectives
- Map synthetic organizational requirements to one enforcement or evidence mechanism each.
- Predict inherited and scoped project coverage before evaluating policy fixtures.
- Inject one policy violation and diagnose it without weakening the baseline.
- Document one legitimate exception with ownership, expiry, compensating control, and evidence.
- Prove separation of duties and perform verified cleanup of temporary policy artifacts.
1. Checkpoint scenario: govern a synthetic top-level group
You are the platform/security architect for a fictional group
training/platform with three projects:
| ID | Project | Classification | Owner |
|---|---|---|---|
| 101 | payments-api | regulated | payments-team |
| 102 | docs-site | standard | docs-team |
| 103 | legacy-worker | regulated but temporary exception | legacy-team |
The security team owns
training/security-policy-management. Application teams
do not own or merge changes to that repository. The mandatory
exercise is local; any live Ultimate/trial step is optional and
disposable.
2. Map requirements before writing policy
Write the mapping first:
| Requirement | Mechanism | Evidence |
|---|---|---|
| R1: regulated projects run Secret Detection on main | Scan execution policy scoped by compliance framework | Policy commit + target pipeline scanner job/report. |
| R2: projects 101/102 run provenance preflight before normal jobs | Pipeline execution policy, inject_policy |
Policy job log + target pipeline SHA. |
| R3: security violations on protected target branch require independent approval | Merge request approval policy (Ultimate live/fixture here) | MR approval rule/violation + completed scanner evidence. |
| R4: policy changes require independent security review | Protected policy-project default branch + MR approval/change process | Policy MR + approver + commit SHA + audit event where available. |
| R5: legacy exception expires | External exception register plus narrow technical scope/bypass only if needed | Owner + expiry + compensating control + removal proof. |
3. Make two predictions before creating files
Prediction A: if the policy project is linked to
training/platform, all three descendants are candidates
through inheritance; individual policy scopes then select the
effective set.
Prediction B: the provenance policy below targets
project IDs 101 and 102 only. Project 103 does not receive that job
unless policy scope changes. Write these expected sets into
evidence/predictions.txt.
4. Build the policy and evidence fixtures
---
scan_execution_policy:
- name: Regulated secret detection
description: Synthetic Chapter 27 policy
enabled: true
rules:
- type: pipeline
branches: [main]
actions:
- scan: secret_detection
policy_scope:
compliance_frameworks:
- id: 27
pipeline_execution_policy:
- name: Required provenance preflight
description: Synthetic Chapter 27 policy
enabled: true
pipeline_config_strategy: inject_policy
content:
include:
- project: training/security-policy-ci
file: provenance.yml
ref: v1.0.0
suffix: on_conflict
policy_scope:
projects:
including:
- id: 101
- id: 102
provenance-preflight:
stage: .pipeline-policy-pre
script:
- echo "synthetic provenance gate"
- test -f provenance.attested
Also create a synthetic MR evaluation record for R3 rather than claiming Free can enforce it:
{
"merge_request": 27,
"target_branch": "main",
"protected": true,
"scanner_reports_complete": true,
"new_high_findings": 1,
"policy_result": "approval_required",
"required_approvals": 1,
"synthetic": true
}
5. Validate provenance and scope locally
mkdir -p .gitlab/security-policies policy-ci evidence
# Save policy.yml and provenance.yml exactly as shown.
git add .
git commit -m "Add Chapter 27 checkpoint policy fixtures"
POLICY_SHA=$(git rev-parse HEAD)
printf 'policy_sha=%s
' "$POLICY_SHA" | tee evidence/policy-identity.txt
sha256sum .gitlab/security-policies/policy.yml policy-ci/provenance.yml | tee evidence/policy-hashes.txt
# Verify intended project IDs appear exactly where expected:
grep -nE 'id: (101|102|103)|compliance_frameworks|pipeline_execution_policy|scan_execution_policy' .gitlab/security-policies/policy.yml
6. Inject one violation and preserve the original cause
Project 101 has no provenance.attested. Simulate the
policy job:
set +e
test -f provenance.attested
rc=$?
printf 'policy_job=provenance-preflight exit_code=%s cause=%s
' "$rc" 'provenance.attested missing' | tee evidence/violation.txt
test "$rc" -ne 0 || exit 1
set -e
Do not “fix” this by removing the policy. For project 101, create the expected synthetic attestation only after confirming the requirement is legitimate:
printf 'sha256:synthetic-ch27
' > provenance.attested
test -f provenance.attested
printf '%s
' 'policy_job=provenance-preflight result=pass' | tee evidence/repair.txt
7. Process one legitimate exception instead of a hidden bypass
Project 103 cannot yet produce the attestation. Record an exception:
{
"exception_id": "EX-27-001",
"project_id": 103,
"requirement": "provenance-preflight",
"owner": "legacy-team-owner",
"approved_by": "security-governance",
"reason": "training fixture: legacy build lacks marker",
"expires_on": "2026-09-30",
"compensating_control": "manual provenance verification before release",
"status": "approved-training-fixture"
}
The expiry date is outside the policy syntax on purpose. Technical bypass settings do not replace governance lifecycle metadata. In a real system, schedule review before expiry and record the evidence that the exclusion/bypass was removed.
8. Prove separation-of-duties assumptions
Write an ownership matrix and challenge each row:
| Action | Security governance | App Maintainer | Why |
|---|---|---|---|
| Merge policy.yml change | Required independent owner/reviewer | Should not be sole authority | Policy subject cannot silently rewrite control. |
| Change application source | No routine ownership required | Yes | Developers remain productive inside constraints. |
| Link/unlink security policy project | Owner / manage_security_policy_link | No unless explicitly delegated | Assignment is governance-sensitive. |
| Approve documented exception | Security/compliance owner | Requester may supply evidence, not self-approve | Maintains separation between request and authorization. |
On a live Ultimate sandbox, verify actual role memberships and protected-branch rules rather than assuming the matrix matches reality.
9. Optional Ultimate/trial validation
If you already have a disposable Ultimate/trial group, create a disabled or narrowly scoped test policy first. Use a merge request to change policy YAML, merge it, record the policy commit, then trigger one tiny project pipeline/MR. Verify policy-originated jobs/approval state and audit events. Never enable broad group scope until the one-project test behaves as predicted.
10. Evidence packet
Retain only sanitized evidence:
- GitLab version/offering/tier assumption;
- synthetic group/project IDs and expected scope;
- policy commit SHA and file hashes;
- policy-type-to-requirement map;
- violation and repaired result;
- exception owner/expiry/compensating control;
- separation-of-duties matrix;
- optional live pipeline/MR/audit IDs—but no tokens or complete environment dumps.
11. Cleanup and rollback
git status --short
git log --oneline --decorate -3
# After retaining sanitized evidence, remove local training files/repository as appropriate.
# In a live Ultimate sandbox: unlink policies first, verify enforcement/link removal,
# then delete only disposable policy/target projects after proving no other targets depend on them.
Policy deletion and unlinking are not interchangeable: deleting a target project removes the lab target, while unlinking changes enforcement relationships. Verify both through read-back.
12. Final verification checklist
- Each requirement maps to exactly one primary enforcement/evidence mechanism.
- Expected project scope is written before enforcement.
- Policy file identity is pinned by commit/hash.
- The violation retains its original reason and exit state.
- The repair satisfies the control without disabling it.
- The legitimate exception has owner, rationale, expiry, compensating control, and approval.
- Policy owners are separate from application maintainers for critical control changes.
- Cleanup is verified rather than assumed.
Knowledge check
Why does the checkpoint separate requirement mapping from policy YAML?
It prevents choosing a feature first and inventing a control around it; the enforcement mechanism should follow the requirement and evaluation timing.
Project 103 is under the linked group but excluded from one policy. Is inheritance broken?
No. Inheritance makes it a candidate target; the individual policy scope can narrow or exclude it.
Why is exception expiry kept in an explicit register even if GitLab has a technical bypass setting?
Technical bypass configuration does not inherently provide full business owner, rationale, review/expiry, compensating-control, and removal-governance metadata.
The provenance job fails on project 101. What is the safer correction?
Preserve the failure cause and satisfy the project requirement or process an approved exception; do not silently disable central policy.
What does this chapter add to a production GitLab operating model?
A governed bridge from security/compliance intent to centrally assigned enforcement, explicit scope, separation of duties, evidence, exceptions, auditability, and safe rollout.
What is the natural next topic after central policy enforcement?
Chapter 28: Kubernetes Agent, GitOps workflows, cluster access, environments, and deployment integration—where GitLab policy/identity boundaries meet cluster operations.
13. Chapter close and bridge to Chapter 28
Chapter 27 turns project-level security evidence into organization-level governance. You can now distinguish policy intent from execution, scope from inheritance, enforcement from evidence, and bypass from a governed exception. Chapter 28 moves this operating model to Kubernetes: how GitLab’s Agent, CI/CD identities, environments, and GitOps workflows cross the trust boundary into a cluster.
Primary sources and version notes
These lessons were finalized against current official GitLab documentation on 2026-08-22. Re-check tier, feature status, policy schema, permission, audit-event, and Self-Managed-version behavior before applying the same design later.
- GitLab 19.3 release
- Security policies
- Policy enforcement
- Security policy projects
- Scan execution policies
- Pipeline execution policies
- Scheduled pipeline execution policies
- Merge request approval policies
- Compliance frameworks
- Compliance and security policy groups
- Compliance and policy settings API
- Audit event types
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0Send only Ethereum/ERC-20 compatible assets to this
address.