{"id":3312,"date":"2026-10-11T20:43:39","date_gmt":"2026-10-11T18:43:39","guid":{"rendered":"https:\/\/djimn.com\/?p=3312"},"modified":"2026-10-11T20:51:20","modified_gmt":"2026-10-11T18:51:20","slug":"pod-security-standards-la-checklist-que-paso-antes-de-aprobar-cualquier-despliegue","status":"publish","type":"post","link":"https:\/\/djimn.com\/index.php\/2026\/10\/11\/pod-security-standards-la-checklist-que-paso-antes-de-aprobar-cualquier-despliegue\/","title":{"rendered":"Pod Security Standards: la checklist que paso antes de aprobar cualquier despliegue"},"content":{"rendered":"<p dir=\"ltr\">Desde que Kubernetes elimin\u00f3 las PodSecurityPolicies en la versi\u00f3n 1.25, el control nativo de qu\u00e9 puede hacer un pod se llama Pod Security Admission. Funciona con tres niveles (Pod Security Standards) que se aplican por namespace con una simple etiqueta. Es de lo m\u00e1s rentable que se puede activar en un cluster. Aun as\u00ed, en muchos clusters que reviso sigue sin configurar o est\u00e1 en modo \u201csolo avisar\u201d desde hace a\u00f1os.<\/p>\n<p dir=\"ltr\"><strong>Los tres niveles, en una frase cada uno:<\/strong><\/p>\n<ul dir=\"ltr\">\n<li><strong>privileged<\/strong>: sin restricciones. Solo para componentes de sistema que realmente lo necesitan.<\/li>\n<li><strong>baseline<\/strong>: bloquea las escaladas de privilegios conocidas (contenedores privilegiados, hostNetwork, hostPID, hostPath\u2026). Es el m\u00ednimo razonable para cualquier namespace.<\/li>\n<li><strong>restricted<\/strong>: aplica las buenas pr\u00e1cticas de endurecimiento completas. Es el objetivo para las aplicaciones.<\/li>\n<\/ul>\n<p dir=\"ltr\"><strong>Y tres modos para aplicarlos:<\/strong><\/p>\n<ul dir=\"ltr\">\n<li><strong>enforce<\/strong> rechaza el pod.<\/li>\n<li><strong>audit<\/strong> lo deja pasar, pero lo registra en el audit log.<\/li>\n<li><strong>warn<\/strong> lo deja pasar, pero devuelve un aviso a quien despliega.<\/li>\n<\/ul>\n<p dir=\"ltr\">El truco est\u00e1 en combinarlos. As\u00ed es como lo activo en un namespace existente sin romper nada:<\/p>\n<div>\n<div dir=\"ltr\" tabindex=\"0\" role=\"group\" aria-label=\"C\u00f3digo en yaml\">\n<div>\n<div><\/div>\n<\/div>\n<div>yaml<\/div>\n<div>\n<pre><code class=\"language-yaml\">apiVersion: v1\r\nkind: Namespace\r\nmetadata:\r\n  name: mi-app\r\n  labels:\r\n    pod-security.kubernetes.io\/enforce: baseline\r\n    pod-security.kubernetes.io\/warn: restricted\r\n    pod-security.kubernetes.io\/audit: restricted<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<p dir=\"ltr\">Con esto, hoy ya no entra nada peligroso (baseline en enforce), y cada despliegue te avisa de lo que le falta para llegar a restricted. Cuando dejan de salir avisos, subes el enforce a restricted.<\/p>\n<p dir=\"ltr\"><strong>La checklist que reviso en cada manifiesto antes de aprobarlo:<\/strong><\/p>\n<ul dir=\"ltr\">\n<li>\u00bf<code dir=\"ltr\">runAsNonRoot: true<\/code> y un <code dir=\"ltr\">runAsUser<\/code> distinto de 0?<\/li>\n<li>\u00bf<code dir=\"ltr\">allowPrivilegeEscalation: false<\/code>?<\/li>\n<li>\u00bf<code dir=\"ltr\">capabilities.drop: [\"ALL\"]<\/code>, a\u00f1adiendo solo las que haga falta y justific\u00e1ndolas?<\/li>\n<li>\u00bf<code dir=\"ltr\">seccompProfile.type: RuntimeDefault<\/code>?<\/li>\n<li>\u00bfNada de <code dir=\"ltr\">privileged<\/code>, <code dir=\"ltr\">hostNetwork<\/code>, <code dir=\"ltr\">hostPID<\/code>, <code dir=\"ltr\">hostIPC<\/code> ni vol\u00famenes <code dir=\"ltr\">hostPath<\/code>?<\/li>\n<li>\u00bfSistema de ficheros ra\u00edz de solo lectura (<code dir=\"ltr\">readOnlyRootFilesystem: true<\/code>) cuando la aplicaci\u00f3n lo permite?<\/li>\n<\/ul>\n<p dir=\"ltr\">Si el equipo responde \u201cs\u00ed\u201d a todo, el pod pasa restricted sin problemas. Si alguna respuesta es \u201cno, porque\u2026\u201d, ese \u201cporque\u201d tiene que quedar documentado.<\/p>\n<p dir=\"ltr\"><strong>Si usas OpenShift<\/strong>, hay un matiz. OpenShift tiene sus propias Security Context Constraints (SCC), que son anteriores y m\u00e1s granulares, y conviven con Pod Security Admission. OpenShift sincroniza autom\u00e1ticamente las etiquetas de PSA seg\u00fan las SCC que tienen disponibles las service accounts del namespace. Por eso los avisos que ves no siempre coinciden con lo que esperar\u00edas de Kubernetes \u201cpuro\u201d. Antes de concluir que algo est\u00e1 mal, revisa qu\u00e9 SCC se le est\u00e1 asignando al pod (la anotaci\u00f3n <code dir=\"ltr\">openshift.io\/scc<\/code>).<\/p>\n<p dir=\"ltr\">Activar Pod Security Admission cuesta tres etiquetas por namespace. No tenerlo activado significa que cualquiera con permiso para crear pods puede montar el sistema de ficheros del nodo.<\/p>\n<p dir=\"ltr\">\u00bfEn qu\u00e9 nivel ten\u00e9is vuestros namespaces de aplicaci\u00f3n: baseline, restricted, o todav\u00eda ninguno?<\/p>\n<hr \/>\n<p dir=\"ltr\"><em>Pod Security, SCC y el resto de controles de admisi\u00f3n los trato a fondo, con manifiestos listos para adaptar, en mi manual \u201cSeguridad y monitorizaci\u00f3n en Kubernetes\u201d (950 p\u00e1ginas, en espa\u00f1ol). [Descarga la muestra gratuita]([URL de la muestra]) \u00b7 <a href=\"https:\/\/4016705366609.gumroad.com\/l\/seguridad-kubernetes?wanted=true\">Consigue el manual completo<\/a><\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Desde que Kubernetes elimin\u00f3 las PodSecurityPolicies en la versi\u00f3n 1.25, el control nativo de qu\u00e9 puede hacer un pod se llama Pod Security Admission. Funciona con tres niveles (Pod Security Standards) que se aplican por namespace con una simple etiqueta. Es de lo m\u00e1s rentable que se puede activar en un cluster. Aun as\u00ed, en [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3318,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_post_was_ever_published":false},"categories":[5],"tags":[60],"class_list":["post-3312","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-tech","tag-arquitecturadesoftware-cloudcomputing-devops-sre-monitorizacion-seguridad-aws-azure-gcp-finops"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/i0.wp.com\/djimn.com\/wp-content\/uploads\/2026\/10\/pod-security-standards_1.png?fit=1200%2C630&ssl=1","_links":{"self":[{"href":"https:\/\/djimn.com\/index.php\/wp-json\/wp\/v2\/posts\/3312","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/djimn.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/djimn.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/djimn.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/djimn.com\/index.php\/wp-json\/wp\/v2\/comments?post=3312"}],"version-history":[{"count":1,"href":"https:\/\/djimn.com\/index.php\/wp-json\/wp\/v2\/posts\/3312\/revisions"}],"predecessor-version":[{"id":3314,"href":"https:\/\/djimn.com\/index.php\/wp-json\/wp\/v2\/posts\/3312\/revisions\/3314"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/djimn.com\/index.php\/wp-json\/wp\/v2\/media\/3318"}],"wp:attachment":[{"href":"https:\/\/djimn.com\/index.php\/wp-json\/wp\/v2\/media?parent=3312"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/djimn.com\/index.php\/wp-json\/wp\/v2\/categories?post=3312"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/djimn.com\/index.php\/wp-json\/wp\/v2\/tags?post=3312"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}