Custom resources¶
All KIMO resources live in API group kimo.kimo.io/v1alpha1 and are namespaced.
ChallengeTemplate¶
Defines a challenge: what to run and under what rules. Instances reference a template by name.
apiVersion: kimo.kimo.io/v1alpha1
kind: ChallengeTemplate
metadata:
name: web-sqli-101
spec:
category: web # freeform metadata
difficulty: easy # freeform metadata
points: 100 # freeform metadata
flagSecretRef: # required — must exist for the template to be Ready
name: web-sqli-101-flag
instanceMode: perTeam # shared | perTeam | perPlayer
ttl: 30m # required — instance lifetime (Go duration)
maxInstances: 200 # concurrent-instance cap (0 = unlimited)
pow: # optional proof-of-work gate
enabled: true
difficulty: 20 # leading zero bits
algorithm: sha256
ttl: 5m # puzzle validity
container:
image: registry.example.com/challenges/web-sqli:v1 # required
ports:
- name: http
containerPort: 8080
expose: true # exposed via Service + allowed through the fence
resources:
requests: { cpu: 100m, memory: 128Mi }
limits: { cpu: 500m, memory: 256Mi }
env: [] # standard corev1 EnvVar list
readiness:
type: tcp # tcp | http | none
port: 8080
path: / # http only
restartPolicy: Always # only Always (or omitted) is accepted
unhealthyThreshold: 3 # readiness failures before Unhealthy
Status: ready (validation passed), instanceCount (instances referencing this template), message (why not ready).
ChallengeInstance¶
One running copy of a challenge for a team/player. Usually created through the REST API, but applying one directly works too.
apiVersion: kimo.kimo.io/v1alpha1
kind: ChallengeInstance
metadata:
name: web-sqli-101-team-alpha
spec:
templateRef: web-sqli-101 # required
team: team-alpha # required
player: alice # optional
ttlOverride: 2h # optional — replaces the template's ttl
Status: phase (lifecycle), reason, endpoint (in-cluster service address), startedAt, expiresAt, podName, unhealthyCount.
The instance owns its Deployment, Service, and NetworkFence — deleting the instance cascades to all of them.
ChallengeSet¶
Groups challenges and activates them inside a time window.
apiVersion: kimo.kimo.io/v1alpha1
kind: ChallengeSet
metadata:
name: round-1
spec:
challenges: [web-sqli-101, web-xss-201] # template names
schedule: # optional — omit for always-active
startAt: "2026-09-01T10:00:00Z" # RFC 3339
endAt: "2026-09-01T18:00:00Z"
Status: active, message. The controller requeues itself at the next schedule boundary, so sets flip on time without external triggers.
NetworkFence¶
Network isolation for one instance, rendered as a NetworkPolicy. Auto-created per instance — apply one manually only to add extra rules. See Network isolation.
apiVersion: kimo.kimo.io/v1alpha1
kind: NetworkFence
metadata:
name: web-sqli-101-team-alpha
spec:
instanceRef: web-sqli-101-team-alpha # required — selects pods by kimo.io/instance label
allowRules:
- port: 8080
- cidr: 10.0.0.0/8
denyRules:
- to: kimo-system
allowEgress: false
Status: applied, message.
Labels¶
KIMO stamps these on everything it creates, and the API's list filters use them:
| Label | Value |
|---|---|
kimo.io/challenge |
Template name |
kimo.io/team |
Team |
kimo.io/instance |
Instance name |