Lab 07: Seguridad
Día: jueves · Branch de referencia: lab07-start → lab07-solution
Objetivo
Cerrar las capas de seguridad que quedaban pendientes: confirmar que
non-root/SCC siguen aplicándose correctamente, verificar que la imagen del
lab03 también pasa Pod Security Admission (el equivalente portable de la
SCC), revisar el manejo de Secrets, aplicar RBAC de mínimo privilegio para
la ServiceAccount del pipeline (lab04), y agregar NetworkPolicy de
segmentación real entre los componentes de TaskFlow.
Contexto
Tu namespace (<tu-usuario>) ya tiene, desde el aprovisionamiento inicial
del workshop, una NetworkPolicy base que niega todo el tráfico por
defecto. Hasta ahora la app funcionó igual porque esa política solo
bloquea tráfico entrante desde otros namespaces: el tráfico entre pods
de tu propio namespace y desde el router de OpenShift no estaba
restringido. Este lab agrega las reglas explícitas para que, aun con una
política de aislamiento estricta, solo pase el tráfico que TaskFlow
necesita, ni más, ni menos.
Pasos
|
Antes de empezar: confirma que ya hiciste |
-
Verificar SCC y non-root (repaso del lab03).
oc get pod -l app=taskflow-api \ -o jsonpath='{.items[0].metadata.annotations.openshift\.io/scc}'Debe imprimir
restricted-v2. Si en algún momento del workshop tu pod quedó conanyuidoprivileged, es señal de que algo en el Dockerfile o el manifiesto se resolvió mal en el lab03: corregirlo ahí, no acá. -
Confirmar Pod Security Admission (equivalente portable de la SCC).
oc label namespace $(oc project -q) pod-security.kubernetes.io/enforce=restricted --overwrite oc rollout restart deployment/taskflow-api oc get pods -wEl pod sigue arrancando sin problema: la imagen del lab03 ya cumple el perfil
restrictedde Pod Security Admission, no solo la SCCrestricted-v2. -
Revisar el manejo de Secrets. Confirmar que:
-
taskflow-db-credentialsnunca existió como archivo con un valor real en el repo:git log --all --format=%H -- 'labs/*/manifests/*.yaml' \ | xargs -I{} git show {} -- 'labs/*/manifests/*.yaml' 2>/dev/null \ | grep -i passwordSolo deberían aparecer nombres de clave/variable (
key: password,POSTGRESQL_PASSWORD,Db__Password), nunca un valor literal. -
Nadie en el equipo necesita leer el valor del Secret a mano para que la app funcione: llega a los pods vía
secretKeyRef, nunca como variable de entorno en texto plano en un manifiesto commiteado.
-
-
RBAC de mínimo privilegio para el pipeline. Completar
manifests/pipeline-role.yamlymanifests/pipeline-rolebinding.yaml: unRoleque le da a la ServiceAccountpipeline(usada en el lab04) solo los verbos que necesita:get/list/watch/patchsobredeployments(ellist+watchlos pideoc rollout status, no solooc set image), nada dedeleteni acceso asecrets. -
NetworkPolicy de segmentación. Completar
manifests/networkpolicy.yamlcon cuatro reglas:-
Permitir ingreso al pod de
taskflow-apisolo desde el router de OpenShift, identificado por la label estándarpolicy-group.network.openshift.io/ingress: ""en su namespace (no por nombre, es portable entre SDN y OVN-Kubernetes), en el puerto 8080. -
Permitir ingreso al pod de
taskflow-apitambién desde los namespaces de monitoreo (network.openshift.io/policy-group: monitoring), mismo puerto 8080: si no, elServiceMonitordel lab06 deja de scrapear en cuanto se aplica esta política. -
Permitir ingreso al pod de
taskflow-dbsolo desde pods con labelapp: taskflow-api, puerto 5432. -
Todo lo demás queda denegado por la política base ya existente.
-
-
Aplicar y validar:
oc apply -f labs/lab07-seguridad/manifests/ curl "https://$(oc get route taskflow-api -o jsonpath='{.spec.host}')/api/tasks"Si la Route sigue respondiendo pero un
oc execa un pod cualquiera de otro namespace ya no puede alcanzar directamente elServicedetaskflow-apipor su IP interna, la segmentación está bien aplicada.
Criterios de "hecho"
-
El pod sigue corriendo bajo
restricted-v2, sin SCC elevada. -
El namespace pasa a
enforce=restricted(Pod Security Admission) sin que el pod deje de arrancar. -
Ningún valor de Secret aparece en texto plano en el historial de Git.
-
La ServiceAccount
pipelinepuede hacerget/list/watch/patchsobredeploymentsen tu namespace, pero nodelete: verificar conoc auth can-i delete deployments --as=system:serviceaccount:<ns>:pipeline(debe responderno). -
La Route sigue funcionando después de aplicar las
NetworkPolicy. -
El tráfico directo pod-a-pod desde otro namespace queda bloqueado.
-
El
ServiceMonitordel lab06 sigue con el target enup(Observe → Targets) después de aplicar laNetworkPolicy.
Pistas
-
oc auth can-i --list --as=system:serviceaccount:<ns>:pipelinees la forma más rápida de auditar qué le quedó habilitado a la ServiceAccount. -
Si la Route deja de responder después de aplicar la
NetworkPolicy, el namespace del router casi siempre esopenshift-ingress: confirmarlo conoc get pods -n openshift-ingressantes de asumir el nombre. -
El valor de la label
policy-group.network.openshift.io/ingresses un string vacío (""), no un booleano ni "true". -
La label de los namespaces de monitoreo NO sigue el mismo formato que la del router: es
network.openshift.io/policy-group: monitoring(prefijo y valor distintos). -
Tu namespace ya trae, desde el aprovisionamiento inicial, una
NetworkPolicybase más permisiva (todo el tráfico intra-namespace + el router). Este lab la reemplaza por reglas más finas.