Gsd-skill-creator compliance-governance

Provides compliance, governance, and supply chain security guidance for cloud-native systems. Covers OPA Rego policies, Kyverno cluster policies, SBOM generation, SLSA provenance, audit trail design, and regulatory framework mapping. Use when user mentions 'compliance', 'governance', 'OPA', 'kyverno', 'SBOM', 'SLSA', 'audit', 'policy-as-code', 'SOC2', 'HIPAA', 'PCI-DSS', 'artifact signing'.

install
source · Clone the upstream repo
git clone https://github.com/Tibsfox/gsd-skill-creator
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/Tibsfox/gsd-skill-creator "$T" && mkdir -p ~/.claude/skills && cp -r "$T/examples/skills/patterns/compliance-governance" ~/.claude/skills/tibsfox-gsd-skill-creator-compliance-governance && rm -rf "$T"
manifest: examples/skills/patterns/compliance-governance/SKILL.md
source content

Compliance and Governance

Best practices for implementing policy-as-code, supply chain security, audit trails, and regulatory compliance in cloud-native environments. This skill covers the full lifecycle from policy authoring to continuous compliance monitoring and evidence generation.

Regulatory Framework Comparison

Understanding which controls map to which framework prevents duplicate work and identifies gaps.

Control DomainSOC 2 (TSC)HIPAAPCI-DSS v4.0FedRAMPISO 27001
Access ControlCC6.1-CC6.8164.312(a)Req 7, 8AC familyA.9
Audit LoggingCC7.1-CC7.4164.312(b)Req 10AU familyA.12.4
Encryption at RestCC6.1164.312(a)(2)(iv)Req 3SC-28A.10.1
Encryption in TransitCC6.7164.312(e)Req 4SC-8A.13.1
Vulnerability MgmtCC7.1164.308(a)(5)(ii)Req 6, 11RA-5, SI-2A.12.6
Incident ResponseCC7.3-CC7.5164.308(a)(6)Req 12.10IR familyA.16
Change ManagementCC8.1164.308(a)(5)(ii)Req 6.5CM familyA.12.1
Data ClassificationCC6.5164.312(d)Req 3.2-3.4RA-2A.8.2
Backup & RecoveryCC7.5, A1.2164.308(a)(7)Req 9.5CP familyA.12.3
Vendor ManagementCC9.2164.308(b)Req 12.8SA familyA.15

Framework Selection Guidance

Your IndustryStart WithAdd When Needed
SaaS B2BSOC 2 Type IIISO 27001 for international
HealthcareHIPAA + SOC 2HITRUST for certification
E-commerce / PaymentsPCI-DSSSOC 2 for broader trust
Government / DefenseFedRAMPNIST 800-171 for CUI
FinanceSOC 2 + PCI-DSSSOX for public companies

Policy-as-Code with OPA

Open Policy Agent (OPA) evaluates policies written in Rego against structured data. Policies are version-controlled, tested, and deployed alongside application code.

OPA Architecture

                    +------------------+
                    |  Policy Bundle   |
                    |  (Git repo)      |
                    +--------+---------+
                             |
                    +--------v---------+
  Request -------->|   OPA Server     |-------> Allow / Deny
  (JSON input)     |   (Rego engine)  |         + Reasons
                    +--------+---------+
                             |
                    +--------v---------+
                    |   Decision Log   |
                    |   (audit trail)  |
                    +------------------+

OPA Rego Policy: Kubernetes Admission Control

package kubernetes.admission

import rego.v1

# Deny containers running as root
deny contains msg if {
    input.request.kind.kind == "Pod"
    some container in input.request.object.spec.containers
    not container.securityContext.runAsNonRoot
    msg := sprintf(
        "Container '%s' in Pod '%s' must set securityContext.runAsNonRoot=true",
        [container.name, input.request.object.metadata.name]
    )
}

# Deny images without digest pinning
deny contains msg if {
    input.request.kind.kind == "Pod"
    some container in input.request.object.spec.containers
    not contains(container.image, "@sha256:")
    not startswith(container.image, "registry.internal.company.com/")
    msg := sprintf(
        "Container '%s' uses unpinned image '%s'. Pin with @sha256: digest.",
        [container.name, container.image]
    )
}

# Require resource limits on all containers
deny contains msg if {
    input.request.kind.kind == "Pod"
    some container in input.request.object.spec.containers
    not container.resources.limits.memory
    msg := sprintf(
        "Container '%s' must define resources.limits.memory",
        [container.name]
    )
}

# Require labels for cost tracking
deny contains msg if {
    input.request.kind.kind in {"Deployment", "StatefulSet", "DaemonSet"}
    not input.request.object.metadata.labels["cost-center"]
    msg := sprintf(
        "%s '%s' must have label 'cost-center' for cost allocation",
        [input.request.kind.kind, input.request.object.metadata.name]
    )
}

OPA Policy Testing

package kubernetes.admission_test

import rego.v1

test_deny_root_container if {
    result := deny with input as {
        "request": {
            "kind": {"kind": "Pod"},
            "object": {
                "metadata": {"name": "test-pod"},
                "spec": {
                    "containers": [{
                        "name": "app",
                        "image": "nginx@sha256:abc123",
                        "securityContext": {},
                        "resources": {"limits": {"memory": "128Mi"}}
                    }]
                }
            }
        }
    }
    count(result) > 0
    some msg in result
    contains(msg, "runAsNonRoot")
}

test_allow_nonroot_container if {
    result := deny with input as {
        "request": {
            "kind": {"kind": "Pod"},
            "object": {
                "metadata": {"name": "test-pod"},
                "spec": {
                    "containers": [{
                        "name": "app",
                        "image": "nginx@sha256:abc123",
                        "securityContext": {"runAsNonRoot": true},
                        "resources": {"limits": {"memory": "128Mi"}}
                    }]
                }
            }
        }
    }
    count(result) == 0
}

Policy-as-Code with Kyverno

Kyverno uses Kubernetes-native YAML for policies. No new language to learn.

Kyverno ClusterPolicy: Image Registry Restriction

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: restrict-image-registries
  annotations:
    policies.kyverno.io/title: Restrict Image Registries
    policies.kyverno.io/category: Supply Chain Security
    policies.kyverno.io/severity: high
    policies.kyverno.io/description: >-
      Only allow images from approved registries to prevent
      supply chain attacks via untrusted image sources.
spec:
  validationFailureAction: Enforce
  background: true
  rules:
    - name: validate-registries
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: >-
          Image '{{ images.containers.*.registry }}' is not from an
          approved registry. Allowed: ghcr.io/our-org, registry.internal.company.com
        pattern:
          spec:
            containers:
              - image: "ghcr.io/our-org/* | registry.internal.company.com/*"
            =(initContainers):
              - image: "ghcr.io/our-org/* | registry.internal.company.com/*"

    - name: require-digest
      match:
        any:
          - resources:
              kinds:
                - Pod
      validate:
        message: "Images must use digest (@sha256:) not tags for reproducibility."
        pattern:
          spec:
            containers:
              - image: "*@sha256:*"

    - name: add-image-pull-secret
      match:
        any:
          - resources:
              kinds:
                - Pod
      mutate:
        patchStrategicMerge:
          spec:
            imagePullSecrets:
              - name: registry-credentials

OPA vs Kyverno Comparison

AspectOPA / GatekeeperKyverno
Policy LanguageRego (purpose-built)YAML (K8s-native)
Learning CurveSteep (new language)Gentle (familiar YAML)
Mutation SupportLimitedFirst-class
Generation SupportNoYes (create resources)
Image VerificationVia external dataBuilt-in (cosign/notary)
Audit ReportsCustomBuilt-in PolicyReport
Multi-clusterBundle serverShared policies via Git
Best ForComplex logic, multi-systemK8s-only, team adoption

Supply Chain Security

SBOM Generation with Syft

A Software Bill of Materials (SBOM) catalogs every component in your software. Required by executive orders and increasingly by enterprise customers.

# Generate SBOM from container image
syft ghcr.io/our-org/api:v1.2.3 -o spdx-json > sbom-api-v1.2.3.spdx.json

# Generate SBOM from source directory
syft dir:./src -o cyclonedx-json > sbom-source.cdx.json

# Generate SBOM from Dockerfile
syft docker:Dockerfile -o spdx-json > sbom-dockerfile.spdx.json

# Scan SBOM for vulnerabilities with Grype
grype sbom:./sbom-api-v1.2.3.spdx.json --fail-on high

# CI integration: generate + scan + attest in one pipeline
syft ghcr.io/our-org/api:v1.2.3 -o spdx-json | \
  tee sbom.spdx.json | \
  grype --fail-on critical

SBOM Format Comparison

AspectSPDXCycloneDX
OriginLinux FoundationOWASP
ISO StandardISO/IEC 5962:2021ECMA-424
Primary FocusLicensing + provenanceSecurity + dependencies
Gov. RequirementUS EO 14028 (preferred)Widely accepted
ToolingBroader ecosystemBetter vulnerability focus
Best ForLicense complianceSecurity analysis

SLSA Provenance

Supply-chain Levels for Software Artifacts (SLSA) provides a framework for ensuring artifact integrity.

SLSA LevelRequirementsTrust
Level 0No guaranteesNone
Level 1Build process documentedProvenance exists
Level 2Hosted build, signed provenanceTamper-resistant provenance
Level 3Hardened build platformTamper-proof provenance

SLSA Provenance with GitHub Actions

name: Release with SLSA Provenance

on:
  push:
    tags: ['v*']

permissions:
  contents: write
  packages: write
  id-token: write       # OIDC for keyless signing
  attestations: write   # GitHub artifact attestations

jobs:
  build:
    runs-on: ubuntu-latest
    outputs:
      digest: ${{ steps.build.outputs.digest }}
    steps:
      - uses: actions/checkout@v4

      - uses: docker/setup-buildx-action@v3

      - uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Build and push
        id: build
        uses: docker/build-push-action@v6
        with:
          context: .
          push: true
          tags: ghcr.io/${{ github.repository }}:${{ github.ref_name }}

      - name: Generate SBOM
        uses: anchore/sbom-action@v0
        with:
          image: ghcr.io/${{ github.repository }}:${{ github.ref_name }}
          format: spdx-json
          output-file: sbom.spdx.json

      - name: Attest SBOM
        uses: actions/attest-sbom@v2
        with:
          subject-name: ghcr.io/${{ github.repository }}
          subject-digest: ${{ steps.build.outputs.digest }}
          sbom-path: sbom.spdx.json

      - name: Attest build provenance
        uses: actions/attest-build-provenance@v2
        with:
          subject-name: ghcr.io/${{ github.repository }}
          subject-digest: ${{ steps.build.outputs.digest }}

Artifact Signing with Cosign

# Install cosign
go install github.com/sigstore/cosign/v2/cmd/cosign@latest

# Keyless signing (recommended -- uses OIDC identity)
cosign sign ghcr.io/our-org/api@sha256:abc123def456

# Verify signature
cosign verify ghcr.io/our-org/api@sha256:abc123def456 \
  --certificate-identity=https://github.com/our-org/api/.github/workflows/release.yml@refs/tags/v1.2.3 \
  --certificate-oidc-issuer=https://token.actions.githubusercontent.com

# Sign with key pair (for air-gapped environments)
cosign generate-key-pair
cosign sign --key cosign.key ghcr.io/our-org/api@sha256:abc123def456
cosign verify --key cosign.pub ghcr.io/our-org/api@sha256:abc123def456

# Attach SBOM as attestation
cosign attest --predicate sbom.spdx.json \
  --type spdxjson \
  ghcr.io/our-org/api@sha256:abc123def456

Audit Trail Architecture

Every compliance framework requires audit logging. Design for immutability and completeness.

Audit Event Schema

{
  "event_id": "uuid-v7",
  "timestamp": "2025-03-15T14:30:00.000Z",
  "actor": {
    "type": "user|service|system",
    "id": "user-123",
    "ip": "10.0.1.50",
    "session_id": "sess-abc"
  },
  "action": {
    "type": "create|read|update|delete|login|export|approve",
    "resource": "patient-record",
    "resource_id": "rec-456"
  },
  "context": {
    "service": "api-gateway",
    "environment": "production",
    "request_id": "req-789",
    "correlation_id": "corr-012"
  },
  "outcome": {
    "status": "success|failure|denied",
    "reason": "insufficient_permissions",
    "policy_violated": "rbac-admin-only"
  },
  "changes": {
    "before": {"status": "active"},
    "after": {"status": "suspended"}
  },
  "metadata": {
    "compliance_scope": ["hipaa", "soc2"],
    "data_classification": "pii",
    "retention_days": 2555
  }
}

Audit Trail Pipeline

Application --> Structured Log --> Log Aggregator --> Immutable Store
    |                                    |                   |
    v                                    v                   v
  stdout/          Fluentd/Vector    S3 (WORM) +
  event bus        with schema       CloudTrail
                   validation        Lake
                                         |
                                         v
                                   SIEM / Query
                                   (Athena, Splunk,
                                    Elastic)

Retention Requirements by Framework

FrameworkMinimum RetentionRecommendedNotes
SOC 21 year3 yearsAuditor needs rolling 12 months
HIPAA6 years7 yearsFrom date of creation or last effective date
PCI-DSS1 year3 yearsImmediate access to 3 months
FedRAMP3 years6 yearsMay vary by data classification
GDPRNo minimumCase-by-caseMust justify retention period

RBAC and Access Control

Kubernetes RBAC Policy

# Principle: least privilege, namespace-scoped, no wildcard verbs
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: app-developer
  namespace: team-alpha
rules:
  - apiGroups: ["apps"]
    resources: ["deployments", "replicasets"]
    verbs: ["get", "list", "watch", "create", "update", "patch"]
  - apiGroups: [""]
    resources: ["pods", "pods/log", "services", "configmaps"]
    verbs: ["get", "list", "watch"]
  # Explicitly NO access to: secrets, persistent volumes, cluster roles
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: app-developer-binding
  namespace: team-alpha
subjects:
  - kind: Group
    name: team-alpha-devs
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: app-developer
  apiGroup: rbac.authorization.k8s.io

Access Control Comparison

ModelWhen to UseComplexityExample
RBACStandard team structuresLowDeveloper, Admin, Viewer roles
ABACDynamic, attribute-drivenMedium"Allow if department=engineering AND env=staging"
ReBACRelationship-heavy domainsHigh"Allow if user is owner of parent folder"
PBACCompliance-drivenMediumOPA/Cedar policies

Policy-as-Code Workflow

Author Policy --> Unit Test --> Review PR --> Merge --> Deploy to OPA/Kyverno
    |                |              |            |              |
    v                v              v            v              v
  Rego/YAML      opa test      Peer +        Main           Gatekeeper
  in Git         conftest      Security      branch         admission
                                review                      controller
                                                               |
                                                               v
                                                         Audit + Alert
                                                         on violations

CI Pipeline for Policy Testing

name: Policy CI

on:
  pull_request:
    paths:
      - 'policies/**'

jobs:
  test-opa:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install OPA
        run: |
          curl -L -o opa https://openpolicyagent.org/downloads/latest/opa_linux_amd64_static
          chmod +x opa && sudo mv opa /usr/local/bin/

      - name: Run policy unit tests
        run: opa test policies/ -v

      - name: Check policy formatting
        run: opa fmt --diff policies/

      - name: Validate against sample resources
        run: |
          for fixture in test-fixtures/*.json; do
            echo "Testing: $fixture"
            opa eval -i "$fixture" -d policies/ "data.kubernetes.admission.deny" \
              --format pretty
          done

  test-kyverno:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Install Kyverno CLI
        run: |
          curl -LO https://github.com/kyverno/kyverno/releases/latest/download/kyverno-cli_linux_x86_64.tar.gz
          tar xzf kyverno-cli_linux_x86_64.tar.gz
          sudo mv kyverno /usr/local/bin/

      - name: Test Kyverno policies
        run: kyverno test policies/kyverno/tests/

Anti-Patterns

Anti-PatternProblemFix
Manual compliance checksInconsistent, unscalable, audit failuresAutomate with OPA/Kyverno in admission control
Policies in wikis, not codeDrift between docs and enforcementPolicy-as-code in Git with CI testing
ClusterRole
with wildcard verbs
Grants full cluster access, violates least privilegeNamespace-scoped Roles with explicit verb lists
SBOM generated once, never updatedStale dependency data, missed CVEsGenerate SBOM on every build, scan continuously
Audit logs in application databaseMutable, deletable, single point of failureWrite-once storage (S3 Object Lock, immutable volumes)
Tag-based image referencesMutable tags allow supply chain attacksPin images by
@sha256:
digest
Unsigned artifacts in productionNo provenance, no tamper detectionSign with cosign, verify in admission control
"We'll add compliance later"Retrofit is 10x more expensiveBuild compliance controls into CI from day one
Single compliance framework mappingDuplicate control implementationsMap controls across frameworks (unified control matrix)
No policy dry-run before enforcePolicies break production workloadsUse
Audit
mode first, review PolicyReport, then
Enforce
Shared service accounts across teamsNo accountability, impossible to auditPer-team service accounts with scoped permissions
Storing secrets in ConfigMapsConfigMaps are not encrypted at restUse Secrets with encryption, or external secret managers
No evidence collection automationScramble before audits, missing proofAutomate evidence gathering with scheduled jobs

Compliance Automation Checklist

  • Policy-as-code repository established with CI/CD pipeline
  • OPA or Kyverno deployed as admission controller in all clusters
  • Policies run in audit mode before enforcement
  • SBOM generated on every container build
  • SBOM scanned for vulnerabilities with severity thresholds
  • Artifacts signed with cosign (keyless via OIDC preferred)
  • Signature verification enforced in admission control
  • Audit logs written to immutable storage (WORM/Object Lock)
  • Audit log retention meets framework requirements
  • RBAC follows least privilege (no wildcard verbs, namespace-scoped)
  • Service accounts scoped per team/application
  • Regulatory control matrix maintained mapping controls across frameworks
  • Evidence collection automated for audit preparation
  • SLSA Level 2+ achieved for production artifacts
  • Policy test coverage tracked (aim for >90%)
  • Compliance dashboard with real-time violation metrics
  • Incident response runbook includes compliance notification procedures
  • Third-party dependencies reviewed for license compliance
  • Data classification labels applied to all storage resources
  • Access reviews scheduled quarterly with automated reports