Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion contrib/tools/mcp-grafana/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ spec:
- "-t"
- "streamable-http"
- -debug
{{- with .Values.securityContext }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
{{- toYaml . | nindent 12 }}
{{- end }}
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy | default "IfNotPresent" }}
resources:
Expand Down
12 changes: 10 additions & 2 deletions helm/kagent/templates/controller-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,10 @@ spec:
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with (.Values.controller.podSecurityContext | default .Values.podSecurityContext) }}
securityContext:
{{- toYaml (.Values.controller.podSecurityContext | default .Values.podSecurityContext) | nindent 8 }}
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "kagent.fullname" . }}-controller
{{- if or (eq .Values.database.type "sqlite") (gt (len .Values.controller.volumes) 0) }}
volumes:
Expand Down Expand Up @@ -65,6 +67,10 @@ spec:
valueFrom:
fieldRef:
fieldPath: spec.nodeName
{{- if eq .Values.database.type "sqlite" }}
- name: XDG_CACHE_HOME
value: /sqlite-volume/.cache
{{- end }}
{{- with .Values.controller.env }}
{{- toYaml . | nindent 12 }}
{{- end }}
Expand All @@ -80,8 +86,10 @@ spec:
protocol: TCP
resources:
{{- toYaml .Values.controller.resources | nindent 12 }}
{{- with (.Values.controller.securityContext | default .Values.securityContext) }}
securityContext:
{{- toYaml .Values.controller.securityContext | nindent 12 }}
{{- toYaml . | nindent 12 }}
{{- end }}
startupProbe:
httpGet:
path: /health
Expand Down
20 changes: 18 additions & 2 deletions helm/kagent/templates/ui-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,18 @@ spec:
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with (.Values.ui.podSecurityContext | default .Values.podSecurityContext) }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "kagent.fullname" . }}-ui
volumes:
- name: nextjs-cache
emptyDir:
sizeLimit: {{ .Values.ui.volumes.nextjsCache }}
- name: tmp
emptyDir:
sizeLimit: {{ .Values.ui.volumes.tmp }}
{{- with .Values.ui.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
Expand All @@ -36,8 +45,10 @@ spec:
{{- end }}
containers:
- name: ui
{{- with (.Values.ui.securityContext | default .Values.securityContext) }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
{{- toYaml . | nindent 12 }}
{{- end }}
image: "{{ .Values.ui.image.registry | default .Values.registry }}/{{ .Values.ui.image.repository }}:{{ coalesce .Values.tag .Values.ui.image.tag .Chart.Version }}"
imagePullPolicy: {{ .Values.ui.image.pullPolicy | default .Values.imagePullPolicy }}
env:
Expand All @@ -50,6 +61,11 @@ spec:
- name: http
containerPort: {{ .Values.ui.service.ports.targetPort }}
protocol: TCP
volumeMounts:
- name: nextjs-cache
mountPath: /app/ui/.next/cache
- name: tmp
mountPath: /tmp
resources:
{{- toYaml .Values.ui.resources | nindent 12 }}
startupProbe:
Expand Down
190 changes: 190 additions & 0 deletions helm/kagent/tests/security-context_test.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
suite: test security context configuration
templates:
- _helpers.tpl
- controller-configmap.yaml
- controller-deployment.yaml
- ui-deployment.yaml
tests:
# =============================================================================
# Controller Security Context Tests
# =============================================================================
- it: should apply default pod security context to controller
template: controller-deployment.yaml
asserts:
- equal:
path: spec.template.spec.securityContext.runAsNonRoot
value: true

- it: should apply default container security context to controller
template: controller-deployment.yaml
asserts:
- equal:
path: spec.template.spec.containers[0].securityContext.readOnlyRootFilesystem
value: true

- it: should allow controller pod security context override
template: controller-deployment.yaml
set:
controller:
podSecurityContext:
runAsNonRoot: true
fsGroup: 2000
asserts:
- equal:
path: spec.template.spec.securityContext.runAsNonRoot
value: true
- equal:
path: spec.template.spec.securityContext.fsGroup
value: 2000

- it: should allow controller container security context override
template: controller-deployment.yaml
set:
controller:
securityContext:
readOnlyRootFilesystem: false
runAsUser: 1000
asserts:
- equal:
path: spec.template.spec.containers[0].securityContext.readOnlyRootFilesystem
value: false
- equal:
path: spec.template.spec.containers[0].securityContext.runAsUser
value: 1000

- it: should fallback to global pod security context for controller
template: controller-deployment.yaml
set:
podSecurityContext:
runAsNonRoot: true
fsGroup: 3000
asserts:
- equal:
path: spec.template.spec.securityContext.runAsNonRoot
value: true
- equal:
path: spec.template.spec.securityContext.fsGroup
value: 3000

- it: should fallback to global container security context for controller
template: controller-deployment.yaml
set:
securityContext:
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
asserts:
- equal:
path: spec.template.spec.containers[0].securityContext.readOnlyRootFilesystem
value: true
- contains:
path: spec.template.spec.containers[0].securityContext.capabilities.drop
content: ALL

# =============================================================================
# UI Security Context Tests
# =============================================================================
- it: should apply UI-specific container security context override
template: ui-deployment.yaml
asserts:
- equal:
path: spec.template.spec.containers[0].securityContext.readOnlyRootFilesystem
value: true

- it: should have nextjs-cache volume for UI
template: ui-deployment.yaml
asserts:
- contains:
path: spec.template.spec.volumes
content:
name: nextjs-cache
emptyDir:
sizeLimit: 100Mi

- it: should have tmp volume for UI
template: ui-deployment.yaml
asserts:
- contains:
path: spec.template.spec.volumes
content:
name: tmp
emptyDir:
sizeLimit: 50Mi

- it: should have nextjs-cache volume mount for UI
template: ui-deployment.yaml
asserts:
- contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: nextjs-cache
mountPath: /app/ui/.next/cache

- it: should have tmp volume mount for UI
template: ui-deployment.yaml
asserts:
- contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: tmp
mountPath: /tmp

- it: should allow UI pod security context override
template: ui-deployment.yaml
set:
ui:
podSecurityContext:
runAsNonRoot: true
fsGroup: 5000
asserts:
- equal:
path: spec.template.spec.securityContext.runAsNonRoot
value: true
- equal:
path: spec.template.spec.securityContext.fsGroup
value: 5000

- it: should allow UI container security context override
template: ui-deployment.yaml
set:
ui:
securityContext:
readOnlyRootFilesystem: false
runAsUser: 2000
asserts:
- equal:
path: spec.template.spec.containers[0].securityContext.readOnlyRootFilesystem
value: false
- equal:
path: spec.template.spec.containers[0].securityContext.runAsUser
value: 2000

- it: should fallback to global pod security context for UI
template: ui-deployment.yaml
set:
ui:
podSecurityContext: {}
podSecurityContext:
runAsNonRoot: true
runAsUser: 3001
asserts:
- equal:
path: spec.template.spec.securityContext.runAsNonRoot
value: true
- equal:
path: spec.template.spec.securityContext.runAsUser
value: 3001

- it: should prefer UI security context over global
template: ui-deployment.yaml
set:
ui:
securityContext:
readOnlyRootFilesystem: false
securityContext:
readOnlyRootFilesystem: true
asserts:
- equal:
path: spec.template.spec.containers[0].securityContext.readOnlyRootFilesystem
value: false
42 changes: 31 additions & 11 deletions helm/kagent/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,18 @@ labels: {}
# environment: production
# team: platform

podSecurityContext: {}
# fsGroup: 2000

securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
# -- Security context for all pods
podSecurityContext:
runAsNonRoot: true
# fsGroup: 2000

# -- Security context for all containers
securityContext:
readOnlyRootFilesystem: true
# capabilities:
# drop:
# - ALL
# runAsUser: 1000

# ==============================================================================
# CORE KAGENT COMPONENTS
Expand Down Expand Up @@ -166,7 +168,25 @@ ui:
port: 8080
targetPort: 8080
env: {} # Additional configuration key-value pairs for the ui ConfigMap

# -- Pod-level security context for the UI pod. Overrides the global podSecurityContext.
# @default -- (uses global podSecurityContext)
podSecurityContext: {}
# fsGroup: 2000
# -- Container-level security context for the UI container. Overrides the global securityContext.
# @default -- (uses global securityContext)
securityContext: {}
# readOnlyRootFilesystem: true
# -- EmptyDir volume sizes for Next.js UI workload (typically used when enabling readOnlyRootFilesystem)
volumes:
# -- Size limit for Next.js build cache (.next/cache). Default 100Mi is sufficient for typical Next.js apps with moderate caching needs.
nextjsCache: 100Mi
# -- Size limit for temporary files (/tmp). Default 50Mi provides ample space for Next.js runtime temporary data.
tmp: 50Mi
# capabilities:
# drop:
# - ALL
# runAsNonRoot: true
# runAsUser: 1000
# -- Node taints which will be tolerated for `Pod` [scheduling](https://kubernetes.io/docs/concepts/scheduling-eviction/assign-pod-node/).
tolerations: []

Expand Down
4 changes: 3 additions & 1 deletion helm/tools/querydoc/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,10 @@ spec:
{{- end }}
containers:
- name: querydoc
{{- with .Values.securityContext }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
{{- toYaml . | nindent 12 }}
{{- end }}
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy | default "IfNotPresent" }}
resources:
Expand Down
8 changes: 5 additions & 3 deletions ui/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ RUN mkdir -p /app/ui/public /tmp/nginx/client_temp /tmp/nginx/proxy_temp /tmp/ng
WORKDIR /app
COPY conf/nginx.conf /etc/nginx/nginx.conf
COPY conf/supervisord.conf /etc/supervisor/conf.d/supervisord.conf
COPY scripts/init.sh /usr/local/bin/init.sh

WORKDIR /app/ui
COPY --from=builder /app/ui/next.config.ts ./
Expand All @@ -70,7 +71,8 @@ COPY --from=builder --chown=nextjs:nginx /app/ui/.next/static ./.next/static

# Ensure correct permissions
RUN chown -R nextjs:nginx /app/ui && \
chmod -R 755 /app
chmod -R 755 /app && \
chmod +x /usr/local/bin/init.sh

EXPOSE 8080
ARG VERSION
Expand All @@ -80,6 +82,6 @@ LABEL org.opencontainers.image.description="Kagent app is the UI and apiserver f
LABEL org.opencontainers.image.authors="Kagent Creators 🤖"
LABEL org.opencontainers.image.version="$VERSION"

USER nextjs
USER 1001

CMD ["/usr/bin/supervisord", "-c", "/etc/supervisor/conf.d/supervisord.conf"]
CMD ["/usr/local/bin/init.sh"]
15 changes: 15 additions & 0 deletions ui/scripts/init.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -e

# Create nginx temp directories
# These are required when running with readOnlyRootFilesystem: true
# The /tmp emptyDir volume is mounted empty at runtime, so we need to
# recreate the directory structure that was created during the Docker build
mkdir -p /tmp/nginx/client_temp \
/tmp/nginx/proxy_temp \
/tmp/nginx/fastcgi_temp \
/tmp/nginx/uwsgi_temp \
/tmp/nginx/scgi_temp

# Start supervisord
exec /usr/bin/supervisord -c /etc/supervisor/conf.d/supervisord.conf
Loading