Access Control and Policy Enforcement

Access Control and Policy Enforcement

Granular access control enables least-privilege registry usage. Repository-level permissions separate team namespaces. Tag-based permissions distinguish between development and production images. Action-based permissions control push, pull, and delete operations. Time-based access enables temporary permissions for CI/CD systems.

Policy engines automate security enforcement across registries. Policies can prevent unsigned images, require vulnerability scans, or enforce naming conventions. Policy as code enables version control and testing. Admission controllers integrate with Kubernetes to enforce policies at deployment time. Clear policy violation messages guide developers toward compliance.

// Example: OPA policy for registry admission control
package registry.admission

import future.keywords.contains
import future.keywords.if

default allow = false

# Allow if image is signed and scanned
allow if {
    signed
    scanned
    vulnerabilities_acceptable
}

# Check if image is properly signed
signed if {
    input.image.signatures[_].verified == true
    input.image.signatures[_].signer in data.trusted_signers
}

# Check if image has been scanned
scanned if {
    input.image.scan_results.status == "completed"
    time.parse_rfc3339_ns(input.image.scan_results.timestamp) > time.now_ns() - (24 * 60 * 60 * 1000000000)  # 24 hours
}

# Check vulnerability levels
vulnerabilities_acceptable if {
    input.image.scan_results.summary.critical == 0
    input.image.scan_results.summary.high <= data.max_high_vulnerabilities
}

# Generate detailed denial reasons
denial_reasons[reason] {
    not signed
    reason := "Image is not signed by a trusted signer"
}

denial_reasons[reason] {
    not scanned
    reason := "Image has not been scanned within the last 24 hours"
}

denial_reasons[reason] {
    input.image.scan_results.summary.critical > 0
    reason := sprintf("Image contains %d critical vulnerabilities", [input.image.scan_results.summary.critical])
}

denial_reasons[reason] {
    input.image.scan_results.summary.high > data.max_high_vulnerabilities
    reason := sprintf("Image contains %d high vulnerabilities (max allowed: %d)", [input.image.scan_results.summary.high, data.max_high_vulnerabilities])
}

# Special exemptions for emergency deployments
allow if {
    input.exemption.approved == true
    input.exemption.expires > time.now_ns()
    input.exemption.approver in data.security_team
}