Asegurar sus implementaciones de GKE con autorización binaria

Google Kubernetes Engine y su modelo de contenedor subyacente proporcionan una mayor escalabilidad y capacidad de administración para las aplicaciones alojadas en la nube. Es más fácil que nunca iniciar aplicaciones de software flexibles de acuerdo con las necesidades de tiempo de ejecución de su sistema.

Sin embargo, esta flexibilidad puede conllevar nuevos desafíos. En tales entornos, puede resultar difícil garantizar que todos los componentes se construyan, prueben y publiquen de acuerdo con sus mejores prácticas y estándares, y que solo se implemente software autorizado en su entorno de producción.

La autorización binaria (BinAuthz) es un servicio que tiene como objetivo reducir algunas de estas preocupaciones al agregar la aplicación de políticas de tiempo de implementación a su clúster de Kubernetes Engine. Las políticas se pueden escribir para requerir que una o más partes de confianza (llamadas "certificadores") aprueben una imagen antes de que se pueda implementar. Para una canalización de implementación de múltiples etapas donde las imágenes progresan desde el desarrollo hasta las pruebas y los clústeres de producción, se pueden usar los certificadores para garantizar que todos los procesos requeridos se hayan completado antes de que el software pase a la siguiente etapa.

La identidad de los atestiguadores se establece y verifica mediante claves públicas criptográficas, y las atestaciones se firman digitalmente utilizando las claves privadas correspondientes. Esto asegura que solo las partes confiables puedan autorizar la implementación de software en su entorno.

En el momento de la implementación, la autorización binaria aplica la política que definió al verificar que la imagen del contenedor haya superado todas las restricciones requeridas, incluido que todos los certificadores requeridos hayan verificado que la imagen está lista para la implementación. Si la imagen pasa, el servicio permite su implementación. De lo contrario, la implementación se bloquea y la imagen no se puede implementar hasta que sea compatible.

866ef6a5bf86cf5.png

Qué vas a construir

Este laboratorio de código describe cómo proteger un clúster de GKE mediante la autorización binaria. Para hacer esto, creará una política que todas las implementaciones deben cumplir y la aplicará al clúster. Como parte de la creación de la política, creará un certificador que pueda verificar las imágenes del contenedor y usarlo para firmar y ejecutar una imagen personalizada.

El propósito de este laboratorio de código es brindar una breve descripción general de cómo funciona la firma de contenedores con la autorización binaria. Con este conocimiento, debe sentirse cómodo construyendo una canalización CI / CD segura, asegurada por certificadores confiables.

Qué vas a aprender

  • Cómo habilitar la autorización binaria en un clúster de GKE
  • Cómo definir una política de autorización binaria
  • Cómo crear un certificador y asociarlo a la política
  • Cómo firmar una imagen como certificador

Lo que necesitarás

Debido a que la autorización binaria se refiere a la seguridad de su infraestructura, normalmente varias personas con diferentes responsabilidades interactuarán con ella. En este codelab, actuará como todos ellos. Antes de comenzar, es importante explicar los diferentes roles que asumirá:

4426da76922fea23.png Implementador :

  • Esta persona / proceso es responsable de ejecutar el código en el clúster.
  • No les preocupa especialmente cómo se hacen cumplir las garantías de seguridad, ese es el trabajo de otra persona.
  • Puede ser un ingeniero de software o una canalización automatizada.

5b1748abb8d8b699.png Creador de políticas:

  • Esta persona es responsable de las políticas de seguridad generales de la organización.
  • Su trabajo es hacer una lista de verificación de las reglas que deben pasarse antes de que se pueda ejecutar un contenedor.
  • Están a cargo de la cadena de confianza, incluido quién debe firmar una imagen antes de que pueda considerarse segura.
  • No están necesariamente preocupados por los detalles técnicos de cómo cumplir con las reglas. Es posible que ni siquiera sepan qué hace el software en un contenedor. Simplemente saben lo que hay que hacer antes de que se pueda establecer la confianza.

dca98cc118cd9139.png Atestiguador

  • Esta persona / proceso es responsable de un eslabón en la cadena de confianza del sistema.
  • Tienen una clave criptográfica y firman una imagen si pasa su proceso de aprobación.
  • Mientras que el Creador de la política determina la política de una manera abstracta de alto nivel, el certificador es responsable de hacer cumplir de manera concreta algún aspecto de la política.
  • Puede ser una persona real, como un evaluador de control de calidad o un administrador, o puede ser un bot en un sistema de CI.
  • La seguridad del sistema depende de su confiabilidad, por lo que es importante que sus claves privadas se mantengan seguras.

Cada uno de estos roles puede representar a una persona individual o un equipo de personas en su organización. En un entorno de producción, es probable que estos roles sean administrados por proyectos separados de Google Cloud Platform (GCP), y el acceso a los recursos se compartiría entre ellos de manera limitada mediante Cloud IAM .

a37eb2ed54b9c2eb.png

Como implementador:

Configurar el entorno

Este laboratorio de código se puede completar a través de su navegador web utilizando Google Cloud Shell. Haga clic en el siguiente enlace para abrir una nueva sesión:

Abra Google Cloud Shell

Configuración de su proyecto

Nuestro primer paso es configurar elproyecto de GCP en el que desea ejecutar el laboratorio de código. Puede encontrar una lista de los proyectos en su cuenta con el siguiente comando:

gcloud projects list

Cuando sepa qué proyecto desea usar, configúrelo en una variable de entorno para que pueda usarlo para el resto del laboratorio de código:

PROJECT_ID=<YOUR_CHOSEN_PROJECT_ID>
gcloud config set project $PROJECT_ID

Crear un directorio de trabajo

A lo largo de este codelab, creará algunos archivos de configuración. Es posible que desee crear un nuevo directorio para trabajar con:

mkdir binauthz-codelab ; cd binauthz-codelab

Habilitando las API

Antes de usar la autorización binaria, debes habilitar las API relevantes en tu proyecto de GCP:

//enable GKE to create and manage your cluster
gcloud services enable container.googleapis.com
//enable BinAuthz to manage a policy on the cluster
gcloud services enable binaryauthorization.googleapis.com
//enable KMS to manage cryptographic signing keys
gcloud services enable cloudkms.googleapis.com

Alternativamente, puede habilitar las API para su proyecto a través de la biblioteca de API de Google Cloud Platform .

Configurar un clúster

A continuación, configure un clúster de Kubernetes para suproyecto a través de Kubernetes Engine. El siguiente comando creará un nuevo clúster llamado "binauthz-codelab" en la zona us-central1-a con la autorización binaria habilitada:

gcloud beta container clusters create \
    --enable-binauthz \
    --zone us-central1-a \
    binauthz-codelab

Una vez que se haya creado su clúster, agréguelo a su entorno local para que pueda interactuar con él localmente usando kubectl :

gcloud container clusters get-credentials binauthz-codelab --zone us-central1-a

Ejecutando un Pod

Ahora, agreguemos un contenedor al nuevo clúster. El siguiente comando creará un Dockerfile simple que puede usar:

cat << EOF > Dockerfile
   FROM alpine
   CMD tail -f /dev/null
EOF

Este contenedor no hará nada más que ejecutar el comando "tail -f / dev / null", lo que hará que espere para siempre. No es un contenedor particularmente útil, pero le permitirá probar la seguridad de su clúster.

Cree el contenedor y envíelo a Google Container Registry (GCR) :

#set the GCR path you will use to host the container image
CONTAINER_PATH=us.gcr.io/${PROJECT_ID}/hello-world

#build container
docker build -t $CONTAINER_PATH ./

#push to GCR
gcloud auth configure-docker --quiet
docker push $CONTAINER_PATH

Ahora debería poder ver el contenedor recién creado en la interfaz web de Container Registry .

8d95f439df5fedb2.png

Ahora, ejecute el contenedor en su clúster:

kubectl create deployment hello-world --image=$CONTAINER_PATH

Si todo funcionó bien, su contenedor debería estar funcionando silenciosamente.

Puede verificar esto enumerando los pods en ejecución:

kubectl get pods

a1724f9d39373710.png

Como creador de políticas:

Agregar una política

Ahora tiene un clúster configurado y ejecutando su código. Ahora, asegure el clúster con una política.

El primer paso es crear un archivo de política:

cat > ./policy.yaml << EOM
    globalPolicyEvaluationMode: ENABLE
    defaultAdmissionRule:
      evaluationMode: ALWAYS_DENY
      enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
EOM

Esta política es relativamente simple. La línea globalPolicyEvaluationMode declara que esta política amplía la política global definida por Google. Esto permite que todos los contenedores oficiales de GKE se ejecuten de forma predeterminada. Además, la política declara una regla de admisión predeterminada que establece que todos los demás pods serán rechazados . La regla de admisión incluye una líneaforcementMode , que establece que todos los pods que no cumplan con esta regla deben bloquearse para que no se ejecuten en el clúster.

Para obtener instrucciones sobre cómo crear políticas más complejas, consulte la documentación de Autorización binaria .

ce424657bce1501f.png

Ahora, puede aplicar la política a su proyecto:

gcloud container binauthz policy import policy.yaml

Alternativamente, la política también se puede configurar a través de la interfaz de usuario de Google Cloud Console .

Como implementador:

Prueba de la política

Su nueva política debería evitar que se implementen imágenes de contenedor personalizadas en el clúster. Puede verificar esto eliminando su pod e intentando ejecutarlo nuevamente:

kubectl delete deployment --all
kubectl delete event --all
kubectl create deployment hello-world --image=$CONTAINER_PATH

Si comprueba si hay pods en el clúster, debería notar que esta vez no se están ejecutando pods:

kubectl get pods

Es posible que deba ejecutar el comando por segunda vez para ver desaparecer los pods. kubectl verificó el pod con la política, descubrió que no se ajustaba a las reglas y lo rechazó.

Puede ver el rechazo enumerado como un evento de kubectl :

kubectl get event --template \
  '{{range.items}}{{"\033[0;36m"}}{{.reason}}:{{"\033[0m"}}{{.message}}{{"\n"}}{{end}}'

d57096ad40933ded.png

Los certificadores en la autorización binaria se implementan sobre la API de análisis de contenedores en la nube , por lo que es importante describir cómo funciona eso antes de seguir adelante. La API de Container Analysis se diseñó para permitirle asociar metadatos con imágenes de contenedores específicas.

Como ejemplo, se podría crear una nota para rastrear la vulnerabilidad Heartbleed . Los proveedores de seguridad luego crearían escáneres para probar las imágenes del contenedor en busca de la vulnerabilidad y crearían una ocurrencia asociada con cada contenedor comprometido.

208aa5ebc53ff2b3.png

Junto con el seguimiento de vulnerabilidades, Container Analysis fue diseñado para ser una API de metadatos genérica. La autorización binaria utiliza el análisis de contenedores para asociar firmas con las imágenes del contenedor que están verificando **. ** Una nota de análisis de contenedores se usa para representar un solo certificador, y las ocurrencias se crean y asocian con cada contenedor que el certificador ha aprobado.

La API de autorización binaria utiliza los conceptos de "certificadores" y "atestaciones", pero estos se implementan mediante las notas y las incidencias correspondientes en la API de análisis de contenedores.

63a701bd0057ea17.png

Actualmente, el clúster realizará un rechazo general en todas las imágenes que no se encuentren en un repositorio oficial. Su siguiente paso es crear un certificador, para que pueda permitir selectivamente contenedores confiables.

Como certificador:

Creación de una nota de análisis de contenedores

36f8f5ade32507f7.png

Comience creando un archivo JSON que contenga los datos necesarios para su Nota. Este comando creará un archivo JSON que contiene su nota localmente:

cat > ./create_note_request.json << EOM
{
  "attestation": {
    "hint": {
      "human_readable_name": "This note represents an attestation authority"
    }
  }
}
EOM

Ahora, envíe la nota a su proyecto utilizando la API de Container Analysis:

NOTE_ID=my-attestor-note

curl -vvv -X POST \
    -H "Content-Type: application/json"  \
    -H "Authorization: Bearer $(gcloud auth print-access-token)"  \
    --data-binary @./create_note_request.json  \
    "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/?noteId=${NOTE_ID}"

Puede verificar que la nota se guardó recuperándola:

curl -vvv  \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}"

Creación de un certificador en autorización binaria

af0267ab7f7757f9.png

Su nota ahora está guardada dentro de la API de Container Analysis. Para hacer uso de su certificador, también debe registrar la nota con Autorización binaria:

ATTESTOR_ID=my-binauthz-attestor

gcloud container binauthz attestors create $ATTESTOR_ID \
    --attestation-authority-note=$NOTE_ID \
    --attestation-authority-note-project=${PROJECT_ID}

Para verificar que todo funciona como se esperaba, imprima la lista de autoridades registradas:

gcloud container binauthz attestors list

9ef5aba66d1b06d3.png

También debería poder ver a su nuevo certificador a través de la interfaz de usuario de Google Cloud Console .

Agregar rol de IAM

Antes de poder utilizar este certificador, debe otorgar a la Autorización binaria los permisos adecuados para ver la Nota de análisis de contenedor que creó. Esto permitirá que Binary Authorization consulte la API de Container Analysis para asegurarse de que cada pod se haya firmado y aprobado para su ejecución.

Los permisos en la autorización binaria se manejan a través de una cuenta de servicio generada automáticamente.

Primero, busque la dirección de correo electrónico de la cuenta de servicio:

PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}"  --format="value(projectNumber)")
BINAUTHZ_SA_EMAIL="service-${PROJECT_NUMBER}@gcp-sa-binaryauthorization.iam.gserviceaccount.com"

Ahora, utilícelo para crear una solicitud JSON de IAM de Container Analysis:

cat > ./iam_request.json << EOM
{
  'resource': 'projects/${PROJECT_ID}/notes/${NOTE_ID}',
  'policy': {
    'bindings': [
      {
        'role': 'roles/containeranalysis.notes.occurrences.viewer',
        'members': [
          'serviceAccount:${BINAUTHZ_SA_EMAIL}'
        ]
      }
    ]
  }
}
EOM

Realice una solicitud curl para otorgar la función de IAM necesaria:

curl -X POST  \
    -H "Content-Type: application/json" \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    --data-binary @./iam_request.json \
    "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}:setIamPolicy"

Agregar una clave KMS

1e3af7c177f7a311.png

Antes de que pueda utilizar este certificador, su autoridad debe crear un par de claves criptográficas que se pueda utilizar para firmar imágenes de contenedor. Esto se puede hacer a través del Servicio de administración de claves de Google Cloud (KMS) .

Primero, agregue algunas variables de entorno para describir la nueva clave

KEY_LOCATION=global
KEYRING=binauthz-keys
KEY_NAME=codelab-key
KEY_VERSION=1

Crea un llavero para guardar un juego de llaves

gcloud kms keyrings create "${KEYRING}" --location="${KEY_LOCATION}"

Cree un nuevo par de claves de firma asimétricas para el certificador

gcloud kms keys create "${KEY_NAME}" \
    --keyring="${KEYRING}" --location="${KEY_LOCATION}" \
    --purpose asymmetric-signing  --default-algorithm="ec-sign-p256-sha256"

Debería ver su clave aparecer en la página KMS de Google Cloud Console. Ahora, asocie la clave con su autoridad a través del comando gcloud binauthz :

gcloud beta container binauthz attestors public-keys add  \
    --attestor="${ATTESTOR_ID}"  \
    --keyversion-project="${PROJECT_ID}"  \
    --keyversion-location="${KEY_LOCATION}" \
    --keyversion-keyring="${KEYRING}" \
    --keyversion-key="${KEY_NAME}" \
    --keyversion="${KEY_VERSION}"

Si vuelve a imprimir la lista de autoridades, ahora debería ver una clave registrada:

gcloud container binauthz attestors list

c5ad61fbf14f1885.png

Tenga en cuenta que se pueden registrar varias claves para cada autoridad. Esto puede resultar útil si la autoridad representa a un equipo de personas. Por ejemplo, cualquier miembro del equipo de control de calidad podría actuar como certificador de control de calidad y firmar con su propia clave privada individual.

Como certificador:

Ahora que tiene su autoridad configurada y lista para usar, puede usarla para firmar la imagen del contenedor que creó anteriormente.

Creación de una atestación firmada

858d7e6feeb6f159.png

Una atestación debe incluir una firma criptográfica para indicar que una imagen de contenedor en particular ha sido verificada por el certificador y es segura de ejecutar en su clúster. Para especificar qué imagen de contenedor certificar, debe determinar su resumen. Puede encontrar el resumen de una etiqueta de contenedor en particular alojada en Container Registry ejecutando:

DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:latest \
    --format='get(image_summary.digest)')

Ahora, puedes usar gcloud para crear tu certificación. El comando simplemente toma los detalles de la clave que desea usar para firmar y la imagen de contenedor específica que desea aprobar.

gcloud beta container binauthz attestations sign-and-create  \
    --artifact-url="${CONTAINER_PATH}@${DIGEST}" \
    --attestor="${ATTESTOR_ID}" \
    --attestor-project="${PROJECT_ID}" \
    --keyversion-project="${PROJECT_ID}" \
    --keyversion-location="${KEY_LOCATION}" \
    --keyversion-keyring="${KEYRING}" \
    --keyversion-key="${KEY_NAME}" \
    --keyversion="${KEY_VERSION}"

En términos de Container Analysis , esto creará una nueva ocurrencia y la adjuntará a la nota de su certificador. Para asegurarse de que todo funcionó como se esperaba, puede enumerar sus certificaciones

gcloud container binauthz attestations list \
   --attestor=$ATTESTOR_ID --attestor-project=${PROJECT_ID}

Ahora, cuando intente ejecutar esa imagen de contenedor, la autorización binaria podrá determinar que fue firmada y verificada por el certificador y que es seguro ejecutarla.

Ahora que un certificador ha verificado su imagen de forma segura, hagámosla funcionar en el clúster.

Como creador de políticas:

Actualización de la política

Actualmente, su clúster ejecuta una política con una regla: permitir contenedores de repositorios oficiales y rechazar todos los demás.

Cámbielo para permitir las imágenes verificadas por el certificador:

cat << EOF > updated_policy.yaml
    globalPolicyEvaluationMode: ENABLE
    defaultAdmissionRule:
      evaluationMode: REQUIRE_ATTESTATION
      enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
      requireAttestationsBy:
      - projects/${PROJECT_ID}/attestors/${ATTESTOR_ID}
EOF

Ahora debería tener un nuevo archivo en el disco, llamado updated_policy.yaml. Ahora, en lugar de que la regla predeterminada rechace todas las imágenes, primero verifica a su certificador en busca de verificaciones.

822240fc0b02408e.png

Sube la nueva política a la autorización binaria:

gcloud container binauthz policy import updated_policy.yaml

Como implementador:

Ejecución de la imagen verificada

A continuación, ejecutará la imagen firmada y verificará que el pod se esté ejecutando con el siguiente comando:

kubectl create deployment hello-world-signed --image="${CONTAINER_PATH}@${DIGEST}"

Ahora verifique si su pod se está ejecutando:

kubectl get pods

Debería ver que su pod ha aprobado la política y se está ejecutando en el clúster.

¡Felicidades! Ahora puede hacer garantías de seguridad específicas para su clúster agregando reglas más complejas a la política.

Eliminar el clúster:

gcloud container clusters delete binauthz-codelab --zone us-central1-a

Eliminar la imagen del contenedor:

gcloud container images delete $CONTAINER_PATH@$DIGEST --force-delete-tags

Eliminar el certificador:

gcloud container binauthz attestors delete my-binauthz-attestor

Elimina los recursos de Container Analysis:

curl -vvv -X DELETE  \
    -H "Authorization: Bearer $(gcloud auth print-access-token)" \
    "https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}"