Skip to content

Namespace Isolation and Grants Enforcement

Overview

This page defines the per-project Kubernetes namespace security boundary and the grants block that controls cross-kernel access. Together, they implement defence in depth: namespace isolation prevents network-level access, while grants enforcement prevents application-level access.

WARNING

Network policy alone is insufficient -- a kernel that can reach NATS can potentially subscribe to any topic. Grants enforcement alone is insufficient -- a compromised kernel could bypass application-level checks by accessing the filesystem directly. Both layers are required. Neither is optional.

Per-Project Namespace Resources

CK.Operator MUST create the following five Kubernetes resources in each project namespace. These resources establish the security boundary within which all project kernels operate.

ResourceNamePurpose
ServiceAccountckp-runtimePod identity; automountServiceAccountToken: false
NetworkPolicyckp-default-denyDeny all ingress and egress by default
NetworkPolicyckp-allow-natsAllow egress to NATS service (port 4222)
NetworkPolicyckp-allow-dnsAllow egress to kube-dns (port 53)
NetworkPolicyckp-allow-gatewayAllow ingress from gateway namespace (port 80)

Default Deny

All pods in the project namespace are isolated by default. Only explicitly allowed traffic passes. The ckp-default-deny NetworkPolicy matches all pods in the namespace and denies all ingress and egress.

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: ckp-default-deny
  namespace: ck-{project}
spec:
  podSelector: {}
  policyTypes:
    - Ingress
    - Egress

Why Default Deny

Default-deny is the only safe starting point for a namespace that runs untrusted or semi-trusted workloads. Kernel tool code is developer-written and may contain vulnerabilities. By denying all traffic and explicitly allowing only NATS, DNS, and gateway ingress, the blast radius of a compromised kernel is limited to its own DATA loop volume.

ServiceAccount

The ckp-runtime ServiceAccount has automountServiceAccountToken: false. This prevents processor pods from accessing the Kubernetes API. The separation axiom extends to the control plane -- kernel code cannot inspect or modify cluster resources.

yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: ckp-runtime
  namespace: ck-{project}
automountServiceAccountToken: false

A kernel that can access the Kubernetes API can read secrets, list pods, or even delete resources. Disabling the service account token mount removes this attack vector entirely. CK.Operator manages cluster resources on behalf of kernels; kernels never manage themselves.

Allowed Egress: NATS

Kernels need to reach the NATS server for all inter-kernel communication. This policy allows egress to the NATS namespace on port 4222 only.

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: ckp-allow-nats
  namespace: ck-{project}
spec:
  podSelector: {}
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: nats
      ports:
        - protocol: TCP
          port: 4222

Allowed Egress: DNS

Kernels need DNS resolution for service discovery within the cluster. This policy allows egress to kube-dns on port 53 (both UDP and TCP).

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: ckp-allow-dns
  namespace: ck-{project}
spec:
  podSelector: {}
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kube-system
      ports:
        - protocol: UDP
          port: 53
        - protocol: TCP
          port: 53

Allowed Ingress: Gateway

The gateway namespace needs to reach kernel web servers to serve the web shell and handle HTTP requests.

yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: ckp-allow-gateway
  namespace: ck-{project}
spec:
  podSelector: {}
  policyTypes:
    - Ingress
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: gateway
      ports:
        - protocol: TCP
          port: 80

Grants Block -- Access Control

The grants block in conceptkernel.yaml is the sole source of cross-kernel permission truth. It replaces all binary access declarations. The grants block implements a subset of ODRL permission semantics mapped to CKP's action-scoped model.

yaml
grants:
  - identity:  spiffe://{domain}/ck/CK.Query/9a1b-...
    actions:   [read-storage, read-index, read-llm]
    expires:   2027-01-01T00:00:00Z
    audit:     true

  - identity:  anon
    actions:   [status, check.identity]
    expires:   never
    audit:     false

  - identity:  auth
    actions:   [read-identity, invoke-tool]
    expires:   never
    audit:     true

  - identity:  owner
    actions:   [read-identity, read-storage, invoke-tool, kernel.stop]
    expires:   never
    audit:     true

Grant Entry Fields

FieldTypeRequiredDescription
identitystringREQUIREDSPIFFE ID, anon, auth, or owner
actionslist[string]REQUIREDPermitted action names from the CKP action vocabulary
expiresstringREQUIREDISO 8601 timestamp or never
auditbooleanOPTIONALIf true, every access MUST be written to storage/ledger/

ODRL Projection

The following table shows how grants block primitives project from ODRL concepts. This is a subset, not full equivalence. Prohibitions, policy composition, duty chains, and conflict resolution are not modelled.

ODRL ConceptCKP Grants EquivalentNotes
odrl:PolicyThe entire grants: blockOne policy per kernel
odrl:Permissionactions: list for a given identityExplicit allow list
odrl:ProhibitionAbsence from actions: listImplicit deny (not modelled explicitly)
odrl:Constraintexpires: fieldTime-based only
odrl:Dutyaudit: trueObligation to log access
odrl:AssetThe kernel itself (all three volumes)Target is the kernel URN
odrl:PartySPIFFE identity string or access tierCaller identity

TIP

CKP uses implicit deny: if an action is not listed in the grants block for a given identity, it is forbidden. There is no explicit "prohibit" entry. This simplifies the model at the cost of not supporting complex ODRL policy composition. If fine-grained policy composition becomes necessary across a fleet, ODRL adoption is the planned upgrade path (see Ontology Model -- Deliberately Skipped Ontologies).

Grantable Actions

ActionTypePermits Access ToLoop
read-identityinspectconceptkernel.yaml, README.md, CLAUDE.md, ontology.yamlCK
read-skillinspectSKILL.md onlyCK
read-tool-refinspectserving.json -- current version infoCK
read-storageinspectstorage/instance-*/data.json, proof/DATA
read-indexinspectstorage/index/*DATA
read-ledgerinspectstorage/ledger/audit.jsonlDATA
read-llminspectstorage/llm/DATA
read-webinspectstorage/web/DATA
invoke-tooloperateCreate CKI triggering tool executionTOOL

DANGER

No external identity MUST ever be granted write-storage, write-tool, or any action that mutates the CK loop. These are reserved for the kernel's own runtime and the operator CI pipeline. The sovereign boundary of the Material Entity is absolute.

Grant Lifecycle

Lifecycle EventHow It HappensWhat Changes
Grant createdOperator edits grants block, commits to CK loop repoNew grant active on next version promotion
Grant expiresexpires field passesAccess silently blocked; ledger entry on next attempt
Grant revokedOperator removes grant, commits + promotesExisting SVIDs expire within TTL (max 1h)
SVID rotationSPIRE rotates automatically before TTLNo disruption to active connections
CK decommissionedPlatform removes SPIRE entriesAll grants revoked within 1h

Namespace Isolation Verification

These resources are verified as part of the deployment proof:

CheckMethodExpected
serviceaccount_existskubectl get sa ckp-runtime -n ck-{project}Exists
default_deny_existskubectl get networkpolicy ckp-default-deny -n ck-{project}Exists
nats_egress_existskubectl get networkpolicy ckp-allow-nats -n ck-{project}Exists
dns_egress_existskubectl get networkpolicy ckp-allow-dns -n ck-{project}Exists
gateway_ingress_existskubectl get networkpolicy ckp-allow-gateway -n ck-{project}Exists
token_mount_disabledInspect ServiceAccount automountServiceAccountTokenfalse

Conformance Requirements

CriterionLevel
CK.Operator MUST create all 5 security resources per project namespaceREQUIRED
Processor pods MUST use the ckp-runtime ServiceAccountREQUIRED
NetworkPolicy MUST deny all traffic by defaultREQUIRED
Only NATS (port 4222), DNS (port 53), and gateway (port 80) traffic MUST be allowedREQUIRED
automountServiceAccountToken MUST be false on ckp-runtimeREQUIRED
Grants block MUST be the sole access control sourceREQUIRED
write-* actions MUST NOT be grantable to external identitiesREQUIRED
All audited access attempts MUST be logged to storage/ledger/REQUIRED
JWT verification MUST occur before handler dispatch on NATSREQUIRED
Grant expiration MUST be enforced at verification timeREQUIRED

See also: Loop Isolation for volume-level enforcement that complements namespace isolation, Authentication for the three-level auth model and JWT verification, NATS Messaging for topic ACLs by auth level.

Released under the MIT License.