Einführung
Die Sicherheit der Lieferkette (Supply Chain) beginnt, bevor eine Workload im Cluster ausgeführt wird. Wenn ein Image unnötige Tools, eine unklare Herkunft oder ein nicht genehmigtes Tag enthält, steigt das Risiko für die Laufzeitkontrollen, die Sie zuvor kennengelernt haben. Ein minimales, genehmigtes Image sollte einen kleinen Build-Kontext, ein klares Basis-Image, einen expliziten Anwendungs-Einstiegspunkt, nützliche Metadaten-Labels sowie den Nachweis enthalten, dass es im Ziel-Cluster ausgeführt werden kann.
In diesem Lab erstellen Sie einen kleinen lokalen Image-Build-Kontext, bauen das Image innerhalb des labex-v134 minikube-Profils, untersuchen die resultierenden Image-Metadaten, stellen es mit imagePullPolicy: Never bereit und verifizieren die Laufzeitinhalte über Kubernetes. Dieses Lab konzentriert sich auf die Praxis: Sie scannen noch keine Images und erzwingen noch keine Registry-Richtlinien. Sie erlernen die erste Gewohnheit der Lieferkettensicherheit: ein kleines, benanntes und überprüfbares Image zu erstellen und nachzuweisen, was darin enthalten ist.
Erstellen eines kleinen Image-Build-Kontexts
In diesem Schritt erstellen Sie die Dateien, aus denen das Image besteht. Ein Build-Kontext ist das Verzeichnis, das an den Image-Builder gesendet wird. Es ist wichtig, den Build-Kontext klein zu halten, da jede zusätzliche Datei die Gefahr birgt, später unnötige Dinge in ein Image zu kopieren.
Beginnen Sie im Lab-Arbeitsbereich:
cd /home/labex/project/minimal-approved-image
Lesen Sie die Lab-Notizen:
sed -n '1,160p' IMAGE_BUILD_NOTES.md
Bestätigen Sie den CKS-Kontext und den Namespace:
kubectl config current-context | tee context-check.txt
kubectl get namespace cks-prep-image | tee namespace-check.txt
Erstellen Sie das Anwendungsskript. Dieses Skript gibt eine Bereitschaftsmeldung aus, zeigt die Laufzeit-UID an und wartet dann, damit Kubernetes den Container zur Überprüfung aktiv halten kann.
cat > app.sh <<'EOF'
#!/bin/sh
set -eu
echo "minimal approved image ready"
echo "runtime uid: $(id -u)"
sleep 300
EOF
chmod 0755 app.sh
Erstellen Sie das Dockerfile. busybox:1.36 ist das kleine Basis-Image für dieses Lab. Die OCI-Labels dokumentieren, warum dieses Image im Lab genehmigt wurde, und USER 65534:65534 sorgt dafür, dass das Image standardmäßig als numerischer Nicht-Root-Benutzer ausgeführt wird.
cat > Dockerfile <<'EOF'
FROM busybox:1.36
LABEL org.opencontainers.image.title="minimal-approved-app"
LABEL org.opencontainers.image.source="local-cks-prep"
LABEL security.labex.io.approved="true"
WORKDIR /app
COPY app.sh /app/app.sh
RUN chmod 0555 /app/app.sh
USER 65534:65534
ENTRYPOINT ["/app/app.sh"]
EOF
Speichern Sie das Inventar des Build-Kontexts und eine Prüfsumme des Anwendungsskripts:
find . -maxdepth 1 -type f -printf '%f\n' | sort | tee build-context-files.txt
sha256sum app.sh | tee app-sha256.txt
sed -n '1,120p' Dockerfile | tee dockerfile-review.txt
Ihr Verzeichnis enthält nun das Dockerfile, app.sh, die Notizen und die von Ihnen gespeicherten Nachweisdateien. Die wichtige Grenze des Images ist die COPY-Zeile im Dockerfile: Nur app.sh wird in /app/app.sh innerhalb des Images kopiert.
Erstellen des Images innerhalb des Minikube-Profils
In diesem Schritt erstellen Sie das Image im labex-v134 minikube-Profil. Dies ist wichtig, da Kubernetes Container aus der minikube-Node-Laufzeitumgebung ausführt. Wenn Sie ein Image nur auf dem Docker-Daemon der äußeren VM erstellen, kann die minikube-Node es möglicherweise nicht sehen.
Erstellen Sie das Image mit einem klaren lokalen Tag:
minikube -p labex-v134 image build -t labex/minimal-approved:1.0 .
Untersuchen Sie das Image innerhalb des minikube-Profils. Der erste Befehl bestätigt, dass das Image in der Node-Laufzeitumgebung vorhanden ist. Der zweite Befehl speichert wichtige Metadaten, einschließlich des konfigurierten Benutzers, des Einstiegspunkts und der Labels.
minikube -p labex-v134 ssh -- 'docker image ls labex/minimal-approved:1.0' | tee built-image-list.txt
minikube -p labex-v134 ssh -- 'docker image inspect labex/minimal-approved:1.0' | tee built-image-inspect.json
Verwenden Sie jq, um die für den Genehmigungsnachweis relevanten Felder zu extrahieren:
jq '.[0].Config | {User, Entrypoint, Labels}' built-image-inspect.json | tee built-image-approval.json
Sie sollten das Image-Tag in built-image-list.txt sehen, User auf 65534:65534 gesetzt, Entrypoint auf /app/app.sh und das Genehmigungs-Label auf true.
Ausführen des genehmigten Images in Kubernetes
In diesem Schritt führen Sie das lokale Image in Kubernetes aus. Der Pod verwendet imagePullPolicy: Never, da das Image innerhalb des minikube-Profils erstellt wurde und nicht in eine Registry gepusht wurde. Diese Einstellung weist Kubernetes an, das lokale Node-Image zu verwenden und einen Fehler auszugeben, falls es nicht vorhanden ist.
Erstellen Sie das Pod-Manifest:
cat > approved-image-pod.yaml <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: approved-image-app
namespace: cks-prep-image
labels:
app: approved-image-app
supply-chain.labex.io/approved: "true"
spec:
restartPolicy: Never
securityContext:
runAsNonRoot: true
runAsUser: 65534
runAsGroup: 65534
containers:
- name: app
image: labex/minimal-approved:1.0
imagePullPolicy: Never
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
EOF
Wenden Sie das Pod-Manifest an und warten Sie auf die Bereitstellung:
kubectl apply -f approved-image-pod.yaml
kubectl wait --for=condition=Ready pod/approved-image-app -n cks-prep-image --timeout=120s
Speichern Sie die Pod-Logs und das aktuelle Pod-YAML:
kubectl logs approved-image-app -n cks-prep-image | tee approved-image-logs.txt
kubectl get pod approved-image-app -n cks-prep-image -o yaml | tee approved-image-pod.current.yaml
Die Logs sollten minimal approved image ready und runtime uid: 65534 anzeigen. Dies beweist, dass Kubernetes den Image-Einstiegspunkt als der vorgesehene Nicht-Root-Benutzer ausführt.
Überprüfen der Laufzeitinhalte
In diesem Schritt untersuchen Sie den laufenden Container von Kubernetes aus. Die Image-Genehmigung sollte nicht beim Tag-Namen enden. Sie benötigen den Nachweis, dass die Laufzeitumgebung den erwarteten Anwendungspfad enthält und keine offensichtlichen zusätzlichen Dateien enthält, die nie Teil des Images sein sollten.
Untersuchen Sie das Anwendungsverzeichnis:
kubectl exec -n cks-prep-image approved-image-app -- sh -c 'ls -la /app; test -f /app/app.sh; echo APP_PATH_OK' | tee runtime-app-path.txt
Überprüfen Sie den Laufzeitbenutzer und führen Sie eine kleine negative Prüfung auf eine unnötige Debug-Datei durch:
kubectl exec -n cks-prep-image approved-image-app -- sh -c 'id -u; test ! -e /app/debug-tool && echo NO_DEBUG_TOOL' | tee runtime-content-check.txt
Speichern Sie einen kompakten finalen Genehmigungsdatensatz, der den Kubernetes-Status mit den Image-Metadaten kombiniert:
kubectl get pod approved-image-app -n cks-prep-image -o json | jq '{image: .spec.containers[0].image, imagePullPolicy: .spec.containers[0].imagePullPolicy, podSecurityContext: .spec.securityContext, containerSecurityContext: .spec.containers[0].securityContext}' | tee final-pod-approval.json
jq '.[0].Config | {User, Entrypoint, Labels}' built-image-inspect.json | tee final-image-approval.json
Der finale Nachweis sollte das lokale genehmigte Image-Tag, imagePullPolicy: Never, die Nicht-Root-Laufzeiteinstellungen, den /app/app.sh-Einstiegspunkt und das Genehmigungs-Label zeigen.
Zusammenfassung
Sie haben den ersten Workflow der Lieferkettensicherheit in diesem CKS-Vorbereitungskurs geübt: das Erstellen und Nachweisen eines minimalen, genehmigten Images. Sie haben einen kleinen Build-Kontext erstellt, labex/minimal-approved:1.0 innerhalb des labex-v134 minikube-Profils gebaut, Image-Metadaten und Labels untersucht, das lokale Image mit imagePullPolicy: Never bereitgestellt und den Laufzeitbenutzer sowie die Anwendungsinhalte über Kubernetes verifiziert. Zukünftige Labs zur Lieferkette werden auf diesem Fundament aufbauen, unter anderem mit Manifest-Scans, der Überprüfung von Helm-Outputs, SBOM- und Prüfsummen-Nachweisen, Kontrollen für vertrauenswürdige Registries und der Bereinigung von Build-Secrets.



