Security
RBAC footprint
The operator requires the following cluster-level permissions. Your security team can audit the generated manifests at config/rbac/ in the repository.
ClusterRoles granted to the operator
| Resource | Verbs | Why |
|---|---|---|
arkagents, arkteams, arkruns, arkevents, arksettings, arkmemories, arkservices | get, list, watch, create, update, patch, delete | Core CRD management |
deployments, replicasets | get, list, watch, create, update, patch, delete | Creates and manages agent pod Deployments |
pods | get, list, watch | Reads pod status for readyReplicas and health checks |
services | get, list, watch, create, update, patch, delete | Creates ArkService-backed k8s Services |
configmaps | get, list, watch | Reads systemPromptRef ConfigMap keys |
secrets | get, list, watch | Reads systemPromptRef Secret keys and MCP auth headers |
events | create, patch | Emits audit events (TaskStarted, TaskCompleted, etc.) |
The operator can read Secrets in any namespace it watches — this is required to support systemPromptRef and MCP server auth headers that reference Secret keys. Restrict the operator’s watched namespaces via the --namespace flag if you need to limit its Secret access scope.
Agent pod permissions
Agent pods run with the operator’s service account by default. They require no k8s API access. You can create a dedicated minimal ServiceAccount with no RBAC bindings and set agentServiceAccount in Helm values to use it.
API key management
Never pass API keys via --set flags. They appear in shell history, the process table, helm get values, and Helm release history in plaintext.
The correct pattern is a Kubernetes Secret referenced by name:
kubectl create secret generic ark-api-keys \
--from-literal=OPENAI_API_KEY=sk-... \
--from-literal=ANTHROPIC_API_KEY=sk-ant-... \
--namespace ark-system
helm install ark-operator arkonis/ark-operator \
--set apiKeys.existingSecret=ark-api-keys
The chart mounts this Secret as environment variables into all agent pods. The key values are never stored in the Helm release object.
Key rotation
To rotate an API key without restarting the operator:
kubectl create secret generic ark-api-keys \
--from-literal=OPENAI_API_KEY=sk-new-key \
--namespace ark-system \
--dry-run=client -o yaml | kubectl apply -f -
kubectl rollout restart deployment -n ai-workloads -l arkonis.dev/managed=true
The operator propagates the updated Secret to new pods on the next reconcile. Existing pods pick it up on the next restart.
systemPrompt in pod environment variables
ArkAgent.spec.systemPrompt is injected into agent pods as the AGENT_SYSTEM_PROMPT environment variable. This means:
- The system prompt is visible in
kubectl describe podand in process listings. - It is stored in the
ArkAgentobject in etcd (subject to etcd encryption at rest if configured). - It appears in Kubernetes audit logs when the pod spec is created.
For regulated environments or prompts containing sensitive instructions:
- Use
systemPromptRefto load the prompt from aConfigMaporSecretkey instead of inline. This avoids the prompt appearing in the CR spec. - Enable encryption at rest for Secrets in etcd.
- Restrict
kubectl describe podaccess via RBAC.
Network policies
By default the operator applies no NetworkPolicy resources. For production deployments, consider:
# Allow agent pods to reach Redis and LLM provider only
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: ark-agent-egress
namespace: ai-workloads
spec:
podSelector:
matchLabels:
app.kubernetes.io/managed-by: ark-operator
policyTypes:
- Egress
egress:
# Redis (task queue)
- ports:
- port: 6379
# LLM provider (OpenAI, Anthropic, or your in-cluster endpoint)
- ports:
- port: 443
# MCP tool servers (adjust to your actual ports)
- ports:
- port: 8080
Restrict ingress to agent pods to the operator namespace only — agent pods do not serve inbound connections in normal operation.
Pod security
Agent pods do not require elevated privileges. A restrictive PodSecurityContext is safe:
securityContext:
runAsNonRoot: true
runAsUser: 65534
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: [ALL]
Set these via agentPodSecurityContext in Helm values. The ark-runtime binary has no filesystem writes at runtime (logs go to stdout).
The operator pod itself also runs non-root. No hostNetwork, hostPID, or privileged containers are used.
Admission webhook security
The admission webhook (ValidatingWebhookConfiguration) validates systemPrompt size (warns at 50 KB, denies at 512 KB per role). The webhook is configured with failurePolicy: Ignore — if the webhook is unreachable, the request is allowed through. For stricter enforcement, change failurePolicy to Fail in config/webhook/.
See also
- Getting Started — API key setup walkthrough
- Helm Values —
apiKeys.existingSecret,agentServiceAccount,agentPodSecurityContext - Environment Variables — all variables injected into agent pods