Skip to content

Commit cd9da84

Browse files
fix: align tests and deployment templates with core v0.3.0 (#7)
Restore the build and Kubernetes conformance after the core v0.3.0 upgrade: - Pass the RuntimeContext argument now required by network.GenerateNetworkMappings in the create-to-run test. - Harden the deployment template to satisfy the KUBERNETES_OUTPUT_PROFILE_EPHEMERAL_LOCAL_APPLY_V1 and restricted conformance profiles: pod/container securityContext, resource bounds, liveness/readiness/startup probes, terminationGracePeriodSeconds and automountServiceAccountToken, digest-pinned image, and secretKeyRef-based secret injection under restricted profiles. - Pin the workload to numeric UID 1000 (deployment runAsUser + Dockerfile adduser). Kubernetes' runAsNonRoot admission check rejects a container whose image user is a non-numeric name, so runAsNonRoot alone would leave every deployed pod stuck in CreateContainerConfigError. - Give the read-only container writable scratch: mount a bounded emptyDir (sizeLimit 1Gi) at /tmp and set HOME=/tmp so ~/.cache writes land there instead of failing against readOnlyRootFilesystem. - Label the owned Namespace with app.kubernetes.io/managed-by: codefly and elide the inline Secret under restricted profiles. - Assert the rendered deployment pins runAsUser, mounts and bounds /tmp, and redirects HOME, so these runtime requirements can't regress silently past static conformance. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent b7e4c82 commit cd9da84

7 files changed

Lines changed: 96 additions & 10 deletions

File tree

‎deployment_test.go‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,31 @@
11
package main
22

33
import (
4+
"os"
5+
"path/filepath"
46
"testing"
57

68
agenttesting "github.com/codefly-dev/core/agents/testing"
9+
"github.com/stretchr/testify/require"
710
)
811

912
func TestDeploymentTemplates(t *testing.T) {
10-
agenttesting.AssertKustomizeTemplates(t, deploymentFS, Parameters{})
13+
destination := agenttesting.AssertKustomizeTemplates(t, deploymentFS, Parameters{})
14+
15+
rendered, err := os.ReadFile(filepath.Join(destination, "base", "deployment.yaml"))
16+
require.NoError(t, err)
17+
manifest := string(rendered)
18+
19+
// Kubernetes rejects runAsNonRoot when the image user is non-numeric, so the
20+
// workload must pin a numeric UID matching the Dockerfile's appuser (1000).
21+
require.Contains(t, manifest, "runAsUser: 1000")
22+
// readOnlyRootFilesystem leaves the container without writable storage, so a
23+
// scratch mount at /tmp is required for the app to run.
24+
require.Contains(t, manifest, "mountPath: /tmp")
25+
// The scratch volume is bounded so a runaway writer evicts only this pod
26+
// rather than filling node ephemeral storage.
27+
require.Contains(t, manifest, "sizeLimit: 1Gi")
28+
// $HOME must point at the writable mount so ~/.cache writes don't hit the
29+
// read-only root filesystem.
30+
require.Contains(t, manifest, "value: /tmp")
1131
}

‎main_test.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ func testCreateToRun(t *testing.T, runtimeContext *basev0.RuntimeContext) {
9494

9595
require.Equal(t, 1, len(runtime.Endpoints))
9696

97-
networkMappings, err := networkManager.GenerateNetworkMappings(ctx, env, workspace, runtime.Identity, runtime.Endpoints)
97+
networkMappings, err := networkManager.GenerateNetworkMappings(ctx, env, workspace, runtime.Identity, runtime.Endpoints, runtimeContext)
9898
require.NoError(t, err)
9999
require.Equal(t, 1, len(networkMappings))
100100

‎templates/builder/Dockerfile.tmpl‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ FROM {{.Builder}} as runtime
1717

1818
WORKDIR /app
1919

20-
RUN adduser -D appuser
20+
# UID pinned to match runAsUser in the kustomize Deployment: Kubernetes'
21+
# runAsNonRoot check rejects a container whose image user is non-numeric.
22+
RUN adduser -D -u 1000 appuser
2123
USER appuser
2224

2325
ENV VIRTUAL_ENV=/app/.venv \

‎templates/deployment/kustomize/base/deployment.yaml.tmpl‎

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,75 @@ spec:
1414
app: {{ .Service.Name.DNSCase }}
1515
sha: {{ .Sha }}
1616
spec:
17+
automountServiceAccountToken: false
18+
terminationGracePeriodSeconds: 30
19+
securityContext:
20+
runAsNonRoot: true
21+
runAsUser: 1000
22+
runAsGroup: 1000
23+
seccompProfile:
24+
type: RuntimeDefault
1725
containers:
1826
- name: {{ .Service.Name.DNSCase }}
19-
image: image:tag
27+
image: {{ .Image.FullName }}
28+
ports:
29+
- containerPort: 8080
30+
securityContext:
31+
allowPrivilegeEscalation: false
32+
runAsNonRoot: true
33+
readOnlyRootFilesystem: true
34+
seccompProfile:
35+
type: RuntimeDefault
36+
capabilities:
37+
drop:
38+
- ALL
39+
resources:
40+
requests:
41+
cpu: 10m
42+
memory: 64Mi
43+
limits:
44+
cpu: 500m
45+
memory: 256Mi
46+
startupProbe:
47+
httpGet:
48+
path: /version
49+
port: 8080
50+
failureThreshold: 30
51+
periodSeconds: 2
52+
readinessProbe:
53+
httpGet:
54+
path: /version
55+
port: 8080
56+
livenessProbe:
57+
httpGet:
58+
path: /version
59+
port: 8080
60+
volumeMounts:
61+
- name: tmp
62+
mountPath: /tmp
2063
envFrom:
2164
- configMapRef:
2265
name: config-{{ .Service.Name.DNSCase }}
66+
{{- if not .Restricted }}
2367
- secretRef:
2468
name: secret-{{ .Service.Name.DNSCase }}
69+
{{- end }}
70+
env:
71+
# readOnlyRootFilesystem makes $HOME unwritable; point caches at the
72+
# writable scratch mount so libraries that use ~/.cache still work.
73+
- name: HOME
74+
value: /tmp
75+
{{- if .Restricted }}
76+
{{- range $environmentVariable, $reference := .SecretReferences }}
77+
- name: {{ $environmentVariable }}
78+
valueFrom:
79+
secretKeyRef:
80+
name: {{ $reference.Name }}
81+
key: {{ $reference.Key }}
82+
optional: {{ $reference.Optional }}
83+
{{- end }}
84+
{{- end }}
85+
volumes:
86+
- name: tmp
87+
emptyDir:
88+
sizeLimit: 1Gi

‎templates/deployment/kustomize/base/namespace.yaml.tmpl‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ kind: Namespace
33
metadata:
44
name: "{{ .Namespace }}"
55
labels:
6+
app.kubernetes.io/managed-by: codefly
67
istio-injection: "enabled"
Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
resources:
22
- ../../base
33
- configmap.yaml
4+
{{- if not .Restricted }}
45
- secret.yaml
5-
6-
images:
7-
- name: image:tag
8-
newName: {{.Image.Name}}
9-
newTag: {{.Image.Tag}}
6+
{{- end }}
Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{{- if not .Restricted }}
12
apiVersion: v1
23
kind: Secret
34
metadata:
@@ -6,4 +7,5 @@ metadata:
67
data:
78
{{- range $key, $value := .Deployment.SecretMap }}
89
{{ $key }}: "{{ $value }}"
9-
{{- end }}
10+
{{- end }}
11+
{{- end }}

0 commit comments

Comments
 (0)