1. Introducción
Container Analysis proporciona análisis de vulnerabilidades y almacenamiento de metadatos para contenedores. El servicio de análisis realiza análisis de vulnerabilidades en imágenes de Artifact Registry y Container Registry. Luego, almacena los metadatos resultantes y los pone a disposición para su consumo a través de una API. El almacenamiento de metadatos te permite almacenar información de diferentes fuentes, incluidos el análisis de vulnerabilidades, los servicios de Google Cloud y los proveedores externos.
El análisis de vulnerabilidades puede realizarse automáticamente o on demand:
- Cuando el análisis automático está habilitado, el análisis se activa automáticamente cada vez que envías una imagen nueva a Artifact Registry o Container Registry. La información sobre vulnerabilidades se actualiza de forma continua cuando se descubren nuevas vulnerabilidades.
- Cuando el análisis on demand está habilitado, debes ejecutar un comando para analizar una imagen local o una imagen en Artifact Registry o Container Registry. El análisis a pedido te brinda flexibilidad en cuanto al momento en que analizas los contenedores. Por ejemplo, puedes analizar una imagen compilada de forma local y solucionar las vulnerabilidades antes de almacenarla en un registro. Los resultados del análisis están disponibles hasta 48 horas después de que se completa el análisis, y la información de vulnerabilidad no se actualiza después de este.
Con Container Analysis integrado en tu canalización de CI/CD, puedes tomar decisiones basadas en esos metadatos. Por ejemplo, puedes usar la Autorización binaria para crear políticas de implementación que solo permitan implementaciones de imágenes que cumplan con los requisitos de registros de confianza.
Qué aprenderás
- Cómo habilitar el análisis automático
- Cómo realizar un análisis On-Demand Scanning
- Cómo integrar el análisis en una canalización de compilación
- Cómo firmar imágenes aprobadas
- Cómo usar los controladores de admisión de GKE para bloquear imágenes
- Cómo configurar GKE para permitir solo imágenes aprobadas firmadas
2. Configuración y requisitos
Cómo configurar el entorno a tu propio ritmo
- Accede a Google Cloud Console y crea un proyecto nuevo o reutiliza uno existente. Si aún no tienes una cuenta de Gmail o de Google Workspace, debes crear una.
- El Nombre del proyecto es el nombre visible de los participantes de este proyecto. Es una cadena de caracteres que no se utiliza en las APIs de Google. Puedes actualizarla en cualquier momento.
- El ID del proyecto es único en todos los proyectos de Google Cloud y es inmutable (no se puede cambiar después de configurarlo). La consola de Cloud genera automáticamente una cadena única. Por lo general, no importa cuál sea. En la mayoría de los codelabs, deberás hacer referencia al ID del proyecto (suele identificarse como
PROJECT_ID
). Si no te gusta el ID que se generó, podrías generar otro aleatorio. También puedes probar uno propio y ver si está disponible. No se puede cambiar después de este paso y se mantendrá durante todo el proyecto. - Recuerda que hay un tercer valor, un número de proyecto, que usan algunas APIs. Obtén más información sobre estos tres valores en la documentación.
- A continuación, deberás habilitar la facturación en la consola de Cloud para usar las APIs o los recursos de Cloud. Ejecutar este codelab no debería costar mucho, tal vez nada. Para cerrar recursos y evitar que se generen cobros más allá de este instructivo, puedes borrar los recursos que creaste o borrar todo el proyecto. Los usuarios nuevos de Google Cloud son aptos para participar en el programa Prueba gratuita de USD 300.
Inicia el editor de Cloudshell
Este lab se diseñó y probó para usarse con el editor de Google Cloud Shell. Para acceder al editor, haz lo siguiente:
- Accede a tu proyecto de Google en https://console.cloud.google.com.
- En la esquina superior derecha, haz clic en el ícono del editor de Cloud Shell.
- Se abrirá un panel nuevo en la parte inferior de la ventana.
Configuración del entorno
En Cloud Shell, establece el ID y el número de tu proyecto. Guárdalos como variables PROJECT_ID
y PROJECT_ID
.
export PROJECT_ID=$(gcloud config get-value project)
export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID \
--format='value(projectNumber)')
Habilita los servicios
Habilita todos los servicios necesarios con el siguiente comando:
gcloud services enable \
cloudkms.googleapis.com \
cloudbuild.googleapis.com \
container.googleapis.com \
containerregistry.googleapis.com \
artifactregistry.googleapis.com \
containerscanning.googleapis.com \
ondemandscanning.googleapis.com \
binaryauthorization.googleapis.com
Crea un repositorio de Artifact Registry
En este lab, usarás Artifact Registry para almacenar y analizar tus imágenes. Crea el repositorio con el siguiente comando.
gcloud artifacts repositories create artifact-scanning-repo \
--repository-format=docker \
--location=us-central1 \
--description="Docker repository"
Configura Docker para que use tus credenciales de gcloud cuando accedas a Artifact Registry.
gcloud auth configure-docker us-central1-docker.pkg.dev
3. Análisis automatizado
El análisis de artefactos se activa automáticamente cada vez que envías una imagen nueva a Artifact Registry o Container Registry. La información sobre vulnerabilidades se actualiza de forma continua cuando se descubren nuevas vulnerabilidades. En esta sección, enviarás una imagen a Artifact Registry y explorarás los resultados.
Crea un directorio de trabajo y cámbialo
mkdir vuln-scan && cd vuln-scan
Define una imagen de muestra
Crea un archivo llamado Dockerfile con el siguiente contenido.
cat > ./Dockerfile << EOF
FROM gcr.io/google-appengine/debian9@sha256:ebffcf0df9aa33f342c4e1d4c8428b784fc571cdf6fbab0b31330347ca8af97a
# System
RUN apt update && apt install python3-pip -y
# App
WORKDIR /app
COPY . ./
RUN pip3 install Flask==1.1.4
RUN pip3 install gunicorn==20.1.0
CMD exec gunicorn --bind :$PORT --workers 1 --threads 8 --timeout 0 main:app
EOF
Crea un archivo llamado main.py con el siguiente contenido:
cat > ./main.py << EOF
import os
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello_world():
name = os.environ.get("NAME", "Worlds")
return "Hello {}!".format(name)
if __name__ == "__main__":
app.run(debug=True, host="0.0.0.0", port=int(os.environ.get("PORT", 8080)))
EOF
Compila y envía la imagen a AR
Usa Cloud Build para compilar y enviar automáticamente tu contenedor a Artifact Registry. Observa la etiqueta bad
en la imagen. Esto te ayudará a identificarlo para los pasos posteriores.
gcloud builds submit . -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:bad
Revisa los detalles de la imagen
Una vez que se complete el proceso de compilación, revisa la imagen y los resultados de vulnerabilidades en el panel de Artifact Registry.
- Abre Artifact Registry en la consola de Cloud.
- Haz clic en artifact-scanning-repo para ver el contenido.
- Haz clic en los detalles de la imagen.
- Haz clic en el resumen más reciente de tu imagen.
- Una vez que finalice el análisis, haz clic en la pestaña de vulnerabilidades de la imagen.
En la pestaña Vulnerabilidades, verás los resultados del análisis automático de la imagen que acabas de compilar.
La automatización del análisis está habilitada de forma predeterminada. Explora la configuración de Artifact Registry para ver cómo puedes activar o desactivar el análisis automático.
4. On-Demand Scanning
Existen varias situaciones en las que es posible que debas ejecutar un análisis antes de enviar la imagen a un repositorio. A modo de ejemplo, un desarrollador de contenedores puede analizar una imagen y corregir los problemas antes de enviar el código al control de código fuente. En el siguiente ejemplo, compilarás y analizarás la imagen de forma local antes de actuar en función de los resultados.
Compila una imagen
En este paso, usarás Docker local para compilar la imagen en tu caché local.
docker build -t us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image .
Escanea la imagen
Una vez que se haya compilado la imagen, solicita un análisis de la imagen. Los resultados del análisis se almacenan en un servidor de metadatos. La tarea se completa con una ubicación de los resultados en el servidor de metadatos.
gcloud artifacts docker images scan \
us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
--format="value(response.scan)" > scan_id.txt
Revisa el archivo de salida
Tómate un momento para revisar el resultado del paso anterior, que se almacenó en el archivo scan_id.txt. Observa la ubicación del informe de los resultados del análisis en el servidor de metadatos.
cat scan_id.txt
Revisa los resultados detallados del análisis
Para ver los resultados reales del análisis, usa el comando list-vulnerabilities
en la ubicación del informe que se indica en el archivo de salida.
gcloud artifacts docker images list-vulnerabilities $(cat scan_id.txt)
El resultado contiene una cantidad significativa de datos sobre todas las vulnerabilidades de la imagen.
Cómo marcar problemas críticos
Las personas rara vez usan directamente los datos almacenados en el informe. Por lo general, un proceso automatizado usa los resultados. Usa los siguientes comandos para leer los detalles del informe y registrar si se encontraron vulnerabilidades CRÍTICAS.
export SEVERITY=CRITICAL
gcloud artifacts docker images list-vulnerabilities $(cat scan_id.txt) --format="value(vulnerability.effectiveSeverity)" | if grep -Fxq ${SEVERITY}; then echo "Failed vulnerability check for ${SEVERITY} level"; else echo "No ${SEVERITY} Vulnerabilities found"; fi
El resultado de este comando será
Failed vulnerability check for CRITICAL level
5. Análisis de la canalización de compilación
En esta sección, crearás una canalización de compilación automatizada que compilará tu imagen de contenedor, la analizará y, luego, evaluará los resultados. Si no se encuentran vulnerabilidades CRÍTICAS, se enviará la imagen al repositorio. Si se encuentran vulnerabilidades CRÍTICAS, la compilación fallará y se finalizará.
Proporciona acceso a la cuenta de servicio de Cloud Build
Cloud Build necesitará derechos para acceder a la API de análisis a pedido. Proporciona acceso con los siguientes comandos.
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/iam.serviceAccountUser"
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/ondemandscanning.admin"
Crea la canalización de Cloud Build
El siguiente comando creará un archivo cloudbuild.yaml en tu directorio que se usará para el proceso automatizado. En este ejemplo, los pasos se limitan al proceso de compilación del contenedor. Sin embargo, en la práctica, incluirías instrucciones y pruebas específicas de la aplicación, además de los pasos del contenedor.
Crea el archivo con el siguiente comando:
cat > ./cloudbuild.yaml << EOF
steps:
# build
- id: "build"
name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', '.']
waitFor: ['-']
#Run a vulnerability scan at _SECURITY level
- id: scan
name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args:
- '-c'
- |
(gcloud artifacts docker images scan \
us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
--location us \
--format="value(response.scan)") > /workspace/scan_id.txt
#Analyze the result of the scan
- id: severity check
name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args:
- '-c'
- |
gcloud artifacts docker images list-vulnerabilities \$(cat /workspace/scan_id.txt) \
--format="value(vulnerability.effectiveSeverity)" | if grep -Fxq CRITICAL; \
then echo "Failed vulnerability check for CRITICAL level" && exit 1; else echo "No CRITICAL vulnerability found, congrats !" && exit 0; fi
#Retag
- id: "retag"
name: 'gcr.io/cloud-builders/docker'
args: ['tag', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']
#pushing to artifact registry
- id: "push"
name: 'gcr.io/cloud-builders/docker'
args: ['push', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']
images:
- us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
EOF
Ejecuta la canalización de CI
Envía la compilación para su procesamiento y verifica que se interrumpa cuando se encuentre una vulnerabilidad de gravedad CRITICAL.
gcloud builds submit
Revisa la compilación fallida
La compilación que acabas de enviar fallará porque la imagen contiene vulnerabilidades CRITÍCAS.
Revisa el error de compilación en la página Historial de Cloud Build.
Corrige la vulnerabilidad
Actualiza el Dockerfile para usar una imagen base que no contenga vulnerabilidades CRÍTICAS.
Reemplaza el Dockerfile para usar la imagen de Debian 10 con el siguiente comando:
cat > ./Dockerfile << EOF
from python:3.8-slim
# App
WORKDIR /app
COPY . ./
RUN pip3 install Flask==2.1.0
RUN pip3 install gunicorn==20.1.0
CMD exec gunicorn --bind :\$PORT --workers 1 --threads 8 main:app
EOF
Ejecuta el proceso de CI con la imagen correcta.
Envía la compilación para su procesamiento y verifica que se realice correctamente cuando no se encuentren vulnerabilidades de gravedad CRITICAL.
gcloud builds submit
Revisa el éxito de la compilación
La compilación que acabas de enviar se realizará correctamente porque la imagen actualizada no contiene vulnerabilidades CRÍTICAS.
Revisa el éxito de la compilación en la página Historial de Cloud Build.
Revisa los resultados del análisis
Revisa la imagen correcta en Artifact Registry
- Abre Artifact Registry en la consola de Cloud.
- Haz clic en artifact-scanning-repo para ver el contenido.
- Haz clic en los detalles de la imagen.
- Haz clic en el resumen más reciente de tu imagen.
- Haz clic en la pestaña de vulnerabilidades de la imagen.
6. Firma de imágenes
Crea una nota de certificador
Una nota de certificación es simplemente un pequeño dato que actúa como una etiqueta para el tipo de firma que se aplica. Por ejemplo, una nota puede indicar un análisis de vulnerabilidades, mientras que otra puede usarse para la firma de QA. Se hará referencia a la nota durante el proceso de firma.
Cómo crear una nota
cat > ./vulnz_note.json << EOM
{
"attestation": {
"hint": {
"human_readable_name": "Container Vulnerabilities attestation authority"
}
}
}
EOM
Almacena la nota
NOTE_ID=vulnz_note
curl -vvv -X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
--data-binary @./vulnz_note.json \
"https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/?noteId=${NOTE_ID}"
Verifica la nota
curl -vvv \
-H "Authorization: Bearer $(gcloud auth print-access-token)" \
"https://containeranalysis.googleapis.com/v1/projects/${PROJECT_ID}/notes/${NOTE_ID}"
Crea un certificador
Los certificadores se usan para realizar el proceso de firma de imágenes en sí y adjuntarán una ocurrencia de la nota a la imagen para su verificación posterior. Crea el certificador para usarlo más adelante.
Crear certificador
ATTESTOR_ID=vulnz-attestor
gcloud container binauthz attestors create $ATTESTOR_ID \
--attestation-authority-note=$NOTE_ID \
--attestation-authority-note-project=${PROJECT_ID}
Verifica el certificador
gcloud container binauthz attestors list
Ten en cuenta que la última línea indica que NUM_PUBLIC_KEYS: 0
proporcionarás claves en un paso posterior.
Ten en cuenta también que Cloud Build crea automáticamente el certificador built-by-cloud-build
en el proyecto cuando ejecutas una compilación que genera imágenes. Por lo tanto, el comando anterior muestra dos certificadores, vulnz-attestor
y built-by-cloud-build
. Una vez que las imágenes se compilan correctamente, Cloud Build firma y crea certificaciones de forma automática para ellas.
Agrega un rol de IAM
La cuenta de servicio de autorización binaria necesitará derechos para ver las notas de certificación. Proporciona el acceso con la siguiente llamada a la API
PROJECT_NUMBER=$(gcloud projects describe "${PROJECT_ID}" --format="value(projectNumber)")
BINAUTHZ_SA_EMAIL="service-${PROJECT_NUMBER}@gcp-sa-binaryauthorization.iam.gserviceaccount.com"
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
Usa el archivo para crear la política de IAM
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"
Agrega una clave de KMS
El certificador necesita claves criptográficas para adjuntar la nota y proporcionar firmas verificables. En este paso, crearás y almacenarás claves en KMS para que Cloud Build pueda acceder a ellas más adelante.
Primero, agrega algunas variables de entorno para describir la clave nueva.
KEY_LOCATION=global
KEYRING=binauthz-keys
KEY_NAME=codelab-key
KEY_VERSION=1
Crea un llavero para contener un conjunto de llaves
gcloud kms keyrings create "${KEYRING}" --location="${KEY_LOCATION}"
Crea un nuevo par de claves de firma asimétrica para el certificador
gcloud kms keys create "${KEY_NAME}" \
--keyring="${KEYRING}" --location="${KEY_LOCATION}" \
--purpose asymmetric-signing \
--default-algorithm="ec-sign-p256-sha256"
Deberías ver tu clave en la página de KMS de la consola de Google Cloud.
Ahora, asocia la clave con tu certificador 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 vuelves a imprimir la lista de autoridades, ahora deberías ver una clave registrada:
gcloud container binauthz attestors list
Cómo crear una certificación firmada
En este punto, tienes configuradas las funciones que te permiten firmar imágenes. Usa el certificador que creaste anteriormente para firmar la imagen de contenedor con la que trabajaste.
CONTAINER_PATH=us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
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 deseas usar para la firma y la imagen de contenedor específica que deseas 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á un caso nuevo y lo adjuntará a la nota de tu certificador. Para asegurarte de que todo funcione según lo esperado, puedes enumerar tus certificaciones
gcloud container binauthz attestations list \
--attestor=$ATTESTOR_ID --attestor-project=${PROJECT_ID}
7. Firma con Cloud Build
Habilitaste la firma de imágenes y usaste el certificador de forma manual para firmar tu imagen de ejemplo. En la práctica, querrás aplicar las certificaciones durante los procesos automatizados, como las canalizaciones de CI/CD.
En esta sección, configurarás Cloud Build para que certifique imágenes automáticamente.
Funciones
Agrega la función de visualizador de certificadores de autorización binaria a la cuenta de servicio de Cloud Build:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/binaryauthorization.attestorsViewer
Agrega la función de verificador y firmante de CryptoKey de Cloud KMS a la cuenta de servicio de Cloud Build (firma basada en KMS):
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/cloudkms.signerVerifier
Agrega la función de vinculador de notas de Container Analysis a la cuenta de servicio de Cloud Build:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
--role roles/containeranalysis.notes.attacher
Prepara el paso de compilación personalizada de Cloud Build
Usarás un paso de compilación personalizada en Cloud Build para simplificar el proceso de certificación. Google proporciona este paso de compilación personalizada, que contiene funciones auxiliares para optimizar el proceso. Antes de usarlo, el código para el paso de compilación personalizado se debe compilar en un contenedor y enviar a Cloud Build. Para ello, ejecuta los siguientes comandos:
git clone https://github.com/GoogleCloudPlatform/cloud-builders-community.git
cd cloud-builders-community/binauthz-attestation
gcloud builds submit . --config cloudbuild.yaml
cd ../..
rm -rf cloud-builders-community
Agrega un paso de firma a tu archivo cloudbuild.yaml
En este paso, agregarás el paso de certificación a la canalización de Cloud Build que compilaste antes.
- Revisa el nuevo paso que agregarás.
Solo revisión. No copiar
#Sign the image only if the previous severity check passes - id: 'create-attestation' name: 'gcr.io/${PROJECT_ID}/binauthz-attestation:latest' args: - '--artifact-url' - 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image' - '--attestor' - 'projects/${PROJECT_ID}/attestors/$ATTESTOR_ID' - '--keyversion' - 'projects/${PROJECT_ID}/locations/$KEY_LOCATION/keyRings/$KEYRING/cryptoKeys/$KEY_NAME/cryptoKeyVersions/$KEY_VERSION'
- Reemplaza el archivo cloudbuild.yaml por la canalización completa actualizada.
cat > ./cloudbuild.yaml << EOF
steps:
# build
- id: "build"
name: 'gcr.io/cloud-builders/docker'
args: ['build', '-t', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', '.']
waitFor: ['-']
#Run a vulnerability scan at _SECURITY level
- id: scan
name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args:
- '-c'
- |
(gcloud artifacts docker images scan \
us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image \
--location us \
--format="value(response.scan)") > /workspace/scan_id.txt
#Analyze the result of the scan
- id: severity check
name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args:
- '-c'
- |
gcloud artifacts docker images list-vulnerabilities \$(cat /workspace/scan_id.txt) \
--format="value(vulnerability.effectiveSeverity)" | if grep -Fxq CRITICAL; \
then echo "Failed vulnerability check for CRITICAL level" && exit 1; else echo "No CRITICAL vulnerability found, congrats !" && exit 0; fi
#Retag
- id: "retag"
name: 'gcr.io/cloud-builders/docker'
args: ['tag', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']
#pushing to artifact registry
- id: "push"
name: 'gcr.io/cloud-builders/docker'
args: ['push', 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good']
#Sign the image only if the previous severity check passes
- id: 'create-attestation'
name: 'gcr.io/${PROJECT_ID}/binauthz-attestation:latest'
args:
- '--artifact-url'
- 'us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good'
- '--attestor'
- 'projects/${PROJECT_ID}/attestors/$ATTESTOR_ID'
- '--keyversion'
- 'projects/${PROJECT_ID}/locations/$KEY_LOCATION/keyRings/$KEYRING/cryptoKeys/$KEY_NAME/cryptoKeyVersions/$KEY_VERSION'
images:
- us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image:good
EOF
Ejecuta la compilación
gcloud builds submit
Revisa la compilación en el historial de Cloud Build
Abre la consola de Cloud en la página Historial de Cloud Build y revisa la compilación más reciente y la ejecución correcta de los pasos de compilación.
8. Políticas de control de admisión
La autorización binaria es una función de GKE y Cloud Run que permite validar reglas antes de que se pueda ejecutar una imagen de contenedor. La validación se ejecuta en cualquier solicitud para ejecutar una imagen, ya sea desde una canalización de CI/CD de confianza o un usuario que intenta implementar una imagen de forma manual. Esta función te permite proteger tus entornos de tiempo de ejecución de manera más eficaz que solo con las verificaciones de canalización de CI/CD.
Para comprender esta función, modificarás la política predeterminada de GKE para aplicar una regla de autorización estricta.
Crea el clúster de GKE
Crea el clúster de GKE:
gcloud beta container clusters create binauthz \
--zone us-central1-a \
--binauthz-evaluation-mode=PROJECT_SINGLETON_POLICY_ENFORCE
Permite que Cloud Build realice la implementación en este clúster:
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com" \
--role="roles/container.developer"
Política de permitir todo
Primero, verifica el estado de la política predeterminada y tu capacidad para implementar cualquier imagen.
- Revisa la política existente
gcloud container binauthz policy export
- Ten en cuenta que la política de aplicación se establece en
ALWAYS_ALLOW
.
evaluationMode: ALWAYS_ALLOW
- Implementa una muestra para verificar que puedes implementar cualquier cosa
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
- Verifica que la implementación haya funcionado
kubectl get pods
Verás el siguiente resultado:
- Borrar implementación
kubectl delete pod hello-server
Política de denegación de todo
Ahora, actualiza la política para inhabilitar todas las imágenes.
- Exporta la política actual a un archivo editable
gcloud container binauthz policy export > policy.yaml
- Cambiar la política.
En un editor de texto, cambia evaluationMode de ALWAYS_ALLOW a ALWAYS_DENY.
edit policy.yaml
El archivo de políticas en formato YAML debe aparecer de la siguiente manera:
globalPolicyEvaluationMode: ENABLE defaultAdmissionRule: evaluationMode: ALWAYS_DENY enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG name: projects/PROJECT_ID/policy
- Abre Terminal, aplica la nueva política y espera unos segundos a que se propague el cambio.
gcloud container binauthz policy import policy.yaml
- Intenta implementar una carga de trabajo de muestra
kubectl run hello-server --image gcr.io/google-samples/hello-app:1.0 --port 8080
- La implementación falla con el siguiente mensaje
Error from server (VIOLATES_POLICY): admission webhook "imagepolicywebhook.image-policy.k8s.io" denied the request: Image gcr.io/google-samples/hello-app:1.0 denied by Binary Authorization default admission rule. Denied by always_deny admission rule
Revierte la política para permitir todo
Antes de pasar a la siguiente sección, asegúrate de revertir los cambios en la política.
- Cambiar la política.
En un editor de texto, cambia evaluationMode de ALWAYS_DENY a ALWAYS_ALLOW.
edit policy.yaml
El archivo de políticas en formato YAML debe aparecer de la siguiente manera:
globalPolicyEvaluationMode: ENABLE defaultAdmissionRule: evaluationMode: ALWAYS_ALLOW enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG name: projects/PROJECT_ID/policy
- Aplica la política revertida
gcloud container binauthz policy import policy.yaml
9. Bloquea vulnerabilidades en GKE
En esta sección, combinarás lo que aprendiste hasta ahora implementando una canalización de CI/CD con Cloud Build que analice las imágenes y, luego, verifique si hay vulnerabilidades antes de firmar la imagen y de intentar implementarla. GKE usará la autorización binaria para validar que la imagen tenga una firma del análisis de vulnerabilidades antes de permitir que se ejecute.
Actualiza la política de GKE para que requiera certificación
Agrega clusterAdmissionRules a tu política de BinAuth de GKE para exigir que tu certificador firme las imágenes.
Reemplaza la política con la configuración actualizada con el siguiente comando.
COMPUTE_ZONE=us-central1-a
cat > binauth_policy.yaml << EOM
defaultAdmissionRule:
enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
evaluationMode: ALWAYS_DENY
globalPolicyEvaluationMode: ENABLE
clusterAdmissionRules:
${COMPUTE_ZONE}.binauthz:
evaluationMode: REQUIRE_ATTESTATION
enforcementMode: ENFORCED_BLOCK_AND_AUDIT_LOG
requireAttestationsBy:
- projects/${PROJECT_ID}/attestors/vulnz-attestor
EOM
Aplica la política
gcloud beta container binauthz policy import binauth_policy.yaml
Intenta implementar la imagen sin firmar
Crea un descriptor de implementación para la aplicación que compilaste antes con el siguiente comando. La imagen que se usa aquí es la que compilaste antes, que contiene vulnerabilidades críticas y NO contiene la certificación firmada.
Los controladores de admisión de GKE deben conocer la imagen exacta que se implementará para validar la firma de forma coherente. Para ello, deberás usar el resumen de la imagen y una etiqueta simple.
Obtén el resumen de la imagen de mala calidad
CONTAINER_PATH=us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:bad \
--format='get(image_summary.digest)')
Usa el resumen en la configuración de Kubernetes
cat > deploy.yaml << EOM
apiVersion: v1
kind: Service
metadata:
name: deb-httpd
spec:
selector:
app: deb-httpd
ports:
- protocol: TCP
port: 80
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deb-httpd
spec:
replicas: 1
selector:
matchLabels:
app: deb-httpd
template:
metadata:
labels:
app: deb-httpd
spec:
containers:
- name: deb-httpd
image: ${CONTAINER_PATH}@${DIGEST}
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
EOM
Intenta implementar la app en GKE
kubectl apply -f deploy.yaml
Revisa la carga de trabajo en la consola y observa el error que indica que se rechazó la implementación:
No attestations found that were valid and signed by a key trusted by the attestor
Implementa una imagen firmada
Obtén el resumen de la imagen de mala calidad
CONTAINER_PATH=us-central1-docker.pkg.dev/${PROJECT_ID}/artifact-scanning-repo/sample-image
DIGEST=$(gcloud container images describe ${CONTAINER_PATH}:good \
--format='get(image_summary.digest)')
Usa el resumen en la configuración de Kubernetes
cat > deploy.yaml << EOM
apiVersion: v1
kind: Service
metadata:
name: deb-httpd
spec:
selector:
app: deb-httpd
ports:
- protocol: TCP
port: 80
targetPort: 8080
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: deb-httpd
spec:
replicas: 1
selector:
matchLabels:
app: deb-httpd
template:
metadata:
labels:
app: deb-httpd
spec:
containers:
- name: deb-httpd
image: ${CONTAINER_PATH}@${DIGEST}
ports:
- containerPort: 8080
env:
- name: PORT
value: "8080"
EOM
Implementar la app en GKE.
kubectl apply -f deploy.yaml
Revisa la carga de trabajo en la consola y observa que la imagen se implementó correctamente.
10. ¡Felicitaciones!
¡Felicitaciones! Completaste el codelab.
Temas abordados:
- Cómo habilitar el análisis automático
- Cómo realizar un análisis On-Demand Scanning
- Cómo integrar el análisis en una canalización de compilación
- Cómo firmar imágenes aprobadas
- Cómo usar los controladores de admisión de GKE para bloquear imágenes
- Cómo configurar GKE para permitir solo imágenes aprobadas firmadas
¿Qué sigue?
- Protege las implementaciones de imágenes en Cloud Run y Google Kubernetes Engine | Documentación de Cloud Build
- Guía de inicio rápido: Configura una política de autorización binaria con GKE | Google Cloud
Limpia
Para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos usados en este instructivo, borra el proyecto que contiene los recursos o conserva el proyecto y borra los recursos individuales.
Borra el proyecto
La manera más fácil de eliminar la facturación es borrar el proyecto que creaste para el instructivo.