Refuerza la seguridad de tu aplicación con Cloud Service Mesh, Config Sync y Policy Controller


En este tutorial se explica cómo mejorar la postura de seguridad de tu clúster y tu aplicación. Supongamos que eres un administrador de una plataforma cuya organización gestiona las aplicaciones de su tienda online con Cloud Service Mesh, un conjunto de herramientas que te ayuda a monitorizar y gestionar una malla de servicios fiable. Es tu responsabilidad asegurarte de que tu red de malla y tus aplicaciones sean seguras.

Puedes evitar errores de configuración y validar automáticamente tus políticas de Cloud Service Mesh con Policy Controller y Config Sync. Policy Controller permite aplicar políticas totalmente programables en tus clústeres. Policy Controller también incluye una biblioteca predeterminada de plantillas de restricciones que puedes usar con el paquete de seguridad de Cloud Service Mesh para auditar el cumplimiento de las vulnerabilidades de seguridad y las prácticas recomendadas de tu malla. Config Sync reconcilia continuamente el estado de los clústeres con un conjunto central de archivos de configuración declarativos de Kubernetes. Si usas Policy Controller y Config Sync juntos, podrás aplicar restricciones de forma continua a las configuraciones de políticas de tu malla de servicios de Cloud.

En el siguiente diagrama se muestra cómo funcionan conjuntamente Cloud Service Mesh, Policy Controller y Config Sync en este tutorial para gestionar y proteger una puerta de enlace de entrada y las aplicaciones de ejemplo Online Boutique que se usan en este tutorial:

Un diagrama que muestra la arquitectura que crearás en este tutorial

Objetivos

  • Crea un clúster de Google Kubernetes Engine (GKE) y regístralo en una flota.
  • Instala Policy Controller, Config Sync y Cloud Service Mesh en un clúster.
  • Configurar Config Sync para sincronizar varios repositorios
  • Aplica las prácticas recomendadas para desplegar configuraciones, aplicaciones y recursos de Istio con Config Sync.
  • Despliega configuraciones de clúster, las aplicaciones de ejemplo Online Boutique y una pasarela de entrada con Config Sync.
  • Aprovecha el paquete de políticas de Cloud Service Mesh de Policy Controller para aplicar las siguientes prácticas recomendadas de seguridad:
    • Asegúrate de que todas las cargas de trabajo de la malla tengan la inyección automática de sidecar.
    • Cifra todo el tráfico de la malla.
    • Garantizar que todas las cargas de trabajo de la malla tengan un control de acceso granular.

Costes

En este documento, se utilizan los siguientes componentes facturables de Google Cloud:

  • GKE.
  • GKE Enterprise. The billing for GKE Enterprise includes billing for the Cloud Service Mesh, Config Sync, and Policy Controller.

Para generar una estimación de costes basada en el uso previsto, utiliza la calculadora de precios.

Los usuarios nuevos Google Cloud pueden disfrutar de una prueba gratuita.

Cuando termines las tareas que se describen en este documento, puedes evitar que se te siga facturando eliminando los recursos que has creado. Para obtener más información, consulta la sección Limpiar.

Antes de empezar

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    Go to project selector

  2. Verify that billing is enabled for your Google Cloud project.

Prepara tu entorno

En esta sección, se prepara el entorno para poder instalar Cloud Service Mesh, Policy Controller y Config Sync:

  1. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

  2. Actualiza a la versión más reciente de Google Cloud CLI:

    gcloud components update
    
  3. Para almacenar los archivos que crees en este tutorial, crea un directorio:

    mkdir ~/asm-acm-tutorial-dir
    
  4. Para simplificar el resto del tutorial, crea las siguientes variables de entorno:

    PROJECT_ID=PROJECT_ID
    gcloud config set project $PROJECT_ID
    CLUSTER=asm-acm-tutorial
    CLUSTER_ZONE=us-east4-a
    MEMBERSHIP=asm-acm-tutorial
    PROJECT_NUMBER=$(gcloud projects describe ${PROJECT_ID} --format='get(projectNumber)')
    

    Sustituye PROJECT_ID por el ID del proyecto que quieras usar en este tutorial.

    Si se te pide que autorices Cloud Shell, haz clic en Autorizar para completar la operación.

  5. Habilita las APIs que necesitas para este tutorial:

    gcloud

    gcloud services enable \
        mesh.googleapis.com \
        anthos.googleapis.com
    

    Config Connector

    Este tutorial incluye recursos de Config Connector. Puedes usar estos recursos para completar las mismas tareas que realizas en la pestaña gcloud. Para utilizar estos recursos, instala Config Connector y aplica los recursos de la forma que mejor se adapte a tu entorno.

    Usa el siguiente Services manifiesto:

    apiVersion: serviceusage.cnrm.cloud.google.com/v1beta1
    kind: Service
    metadata:
      annotations:
        cnrm.cloud.google.com/deletion-policy: "abandon"
        cnrm.cloud.google.com/disable-dependent-services: "false"
      name: mesh.googleapis.com
    spec:
      resourceID: mesh.googleapis.com
      projectRef:
        external: PROJECT_ID
    ---
    apiVersion: serviceusage.cnrm.cloud.google.com/v1beta1
    kind: Service
    metadata:
      annotations:
        cnrm.cloud.google.com/deletion-policy: "abandon"
        cnrm.cloud.google.com/disable-dependent-services: "false"
      name: anthos.googleapis.com
    spec:
      resourceID: anthos.googleapis.com
      projectRef:
        external: PROJECT_ID
    

    Esta operación puede tardar más de un minuto.

  6. Configurar un clúster de GKE

    En esta sección, creará un clúster de GKE y, a continuación, lo registrará en una flota. Las flotas son unGoogle Cloud concepto para organizar de forma lógica clústeres y otros recursos, lo que te permite usar y gestionar funciones de varios clústeres, así como aplicar políticas coherentes en tus sistemas.

    El clúster que crees en esta sección es el clúster en el que instalarás Cloud Service Mesh, Policy Controller y Config Sync. También es el clúster en el que se implementan las aplicaciones de ejemplo de Online Boutique.

    Para configurar el clúster, sigue estos pasos:

    1. Crea un clúster de GKE:

      gcloud

      gcloud container clusters create ${CLUSTER} \
          --zone ${CLUSTER_ZONE} \
          --machine-type=e2-standard-4 \
          --num-nodes 4 \
          --workload-pool ${PROJECT_ID}.svc.id.goog \
          --labels mesh_id=proj-${PROJECT_NUMBER}
      

      Config Connector

      Usa los siguientes manifiestos ContainerCluster y ContainerNodePool:

      apiVersion: container.cnrm.cloud.google.com/v1beta1
      kind: ContainerNodePool
      metadata:
        annotations:
          cnrm.cloud.google.com/project-id: PROJECT_ID
        name: asm-acm-tutorial
      spec:
        clusterRef:
          name: asm-acm-tutorial
        location: us-east4-a
        nodeConfig:
          machineType: e2-standard-4
        nodeCount: 4
      ---
      apiVersion: container.cnrm.cloud.google.com/v1beta1
      kind: ContainerCluster
      metadata:
        annotations:
          cnrm.cloud.google.com/project-id: PROJECT_ID
          cnrm.cloud.google.com/remove-default-node-pool: "true"
        labels:
          mesh_id: proj-PROJECT_NUMBER
        name: asm-acm-tutorial
      spec:
        location: us-east4-a
        initialNodeCount: 1
        workloadIdentityConfig:
          workloadPool: PROJECT_ID.svc.id.goog
      

      Sustituye PROJECT_NUMBER por el valor de la variable de entorno PROJECT_NUMBER que has obtenido antes.

      Esta operación puede tardar más de cinco minutos en completarse.

    2. Para asegurarte de que el clúster de GKE se ha creado correctamente, describe su estado:

      gcloud container clusters list \
          --zone ${CLUSTER_ZONE} \
          --project ${PROJECT_ID}
      

      El resultado debería ser similar al siguiente:

      NAME                LOCATION      MASTER_VERSION   MASTER_IP      MACHINE_TYPE   NODE_VERSION     NUM_NODES  STATUS
      asm-acm-tutorial    us-east4-a    1.23.12-gke.100  35.186.179.30  e2-standard-4  1.23.12-gke.100  3          RUNNING
      
    3. Conéctate al clúster de GKE:

      gcloud container clusters get-credentials ${CLUSTER} \
          --zone ${CLUSTER_ZONE} \
          --project ${PROJECT_ID}
      
    4. Registra tu clúster en una flota:

      gcloud

      gcloud container fleet memberships register ${MEMBERSHIP} \
          --project ${PROJECT_ID} \
          --gke-cluster ${CLUSTER_ZONE}/${CLUSTER} \
          --enable-workload-identity
      

      El resultado debería ser similar al siguiente:

      kubeconfig entry generated for asm-acm-tutorial.
      Waiting for membership to be created...done.
      Created a new membership [projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial] for the cluster [asm-acm-tutorial]
      Generating the Connect Agent manifest...
      Deploying the Connect Agent on cluster [asm-acm-tutorial] in namespace [gke-connect]...
      Deployed the Connect Agent on cluster [asm-acm-tutorial] in namespace [gke-connect].
      Finished registering the cluster [asm-acm-tutorial] with the Fleet.
      

      Config Connector

      Usa el siguiente GKEHubMembership manifiesto:

      apiVersion: gkehub.cnrm.cloud.google.com/v1beta1
      kind: GKEHubMembership
      metadata:
        annotations:
          cnrm.cloud.google.com/project-id: PROJECT_ID
        name: asm-acm-tutorial
      spec:
        location: global
        authority:
          issuer: https://container.googleapis.com/v1/projects/PROJECT_ID/locations/us-east4-a/clusters/asm-acm-tutorial
        endpoint:
          gkeCluster:
            resourceRef:
              name: asm-acm-tutorial
      
    5. Para asegurarte de que el clúster de GKE se ha registrado correctamente, describe su estado:

      gcloud container fleet memberships list
      

      El resultado debería ser similar al siguiente:

      NAME              EXTERNAL_ID                           LOCATION
      asm-acm-tutorial  0e12258c-8831-4d81-b5c0-5e7099a468cc  global
      

    Explorar los repositorios

    En la siguiente sección de instalación, se aplica un archivo acm-config.yaml de manifiesto. Este manifiesto configura tu clúster para que se sincronice desde la carpeta asm-acm-tutorial del repositorio de ejemplo. Esta carpeta contiene todos los archivos de configuración que necesitas para completar el resto del tutorial.

    Para simplificar este tutorial, usarás comandos de sed para actualizar el acm-config.yaml. Con el archivo acm-config.yaml, Config Sync implementa los manifiestos necesarios para cada paso de este tutorial. Actualizar un solo archivo te ayuda a centrarte en los conceptos y el flujo de protección de tus clústeres, malla y aplicaciones sin tener que manipular los archivos ni ejecutar los comandos git repetidamente.

    Para aprovechar la capacidad de Config Sync de sincronizar varios repositorios, utiliza los siguientes recursos:

    • root-sync, como repositorio de RootSync, contiene todas las configuraciones de tu clúster, incluidas RepoSyncs, Constraints, ClusterRole, RoleBindings y los recursos incluidos en algunos espacios de nombres del sistema, como istio-system.
    • ingress-gateway, como primer RepoSync, contiene todos los recursos necesarios para implementar una puerta de enlace de entrada y protegerla progresivamente a lo largo de este tutorial.
    • online-boutique, como segundo RepoSync, contiene todos los recursos necesarios para implementar las aplicaciones de Online Boutique y protegerlas progresivamente a lo largo de este tutorial.

    Instalar Policy Controller, Config Sync y Cloud Service Mesh gestionado

    Ahora que has creado y registrado tu clúster, puedes instalar Config Sync, Policy Controller y Cloud Service Mesh en él, así como configurarlo para que se sincronice con las configuraciones del RootSync predeterminado:

    1. Habilita el operador ConfigManagement, que gestiona Config Sync y Policy Controller:

      gcloud

      gcloud beta container fleet config-management enable
      

      Config Connector

      Usa el siguiente GKEHubFeature manifiesto:

      apiVersion: gkehub.cnrm.cloud.google.com/v1beta1
      kind: GKEHubFeature
      metadata:
        name: configmanagement
      spec:
        projectRef:
          external: PROJECT_ID
        location: global
        resourceID: configmanagement
      
    2. Habilita Cloud Service Mesh en tu flota.

      gcloud

      gcloud container fleet mesh enable
      

      Config Connector

      Usa el siguiente GKEHubFeature manifiesto:

      apiVersion: gkehub.cnrm.cloud.google.com/v1beta1
      kind: GKEHubFeature
      metadata:
        name: servicemesh
      spec:
        projectRef:
          external: PROJECT_ID
        location: global
        resourceID: servicemesh
      
    3. Habilita la gestión automática de Cloud Service Mesh para que Google aplique la configuración recomendada de Cloud Service Mesh gestionado:

      gcloud

      gcloud container fleet mesh update \
          --management automatic \
          --memberships ${MEMBERSHIP}
      

      Config Connector

      Usa el siguiente GKEHubFeatureMembership manifiesto:

      apiVersion: gkehub.cnrm.cloud.google.com/v1beta1
      kind: GKEHubFeatureMembership
      metadata:
        name: servicemesh-membership
      spec:
        projectRef:
          external: PROJECT_ID
        location: global
        membershipRef:
          name: asm-acm-tutorial
        featureRef:
          name: servicemesh
        mesh:
          management: MANAGEMENT_AUTOMATIC
      
    4. Habilita Config Sync y Policy Controller:

      gcloud

      Guarda el siguiente archivo de manifiesto como acm-config.yaml en el directorio ~/asm-acm-tutorial-dir:

      applySpecVersion: 1
      spec:
        configSync:
          enabled: true
          policyDir: asm-acm-tutorial/root-sync/init
          secretType: none
          sourceFormat: unstructured
          syncRepo: https://github.com/GoogleCloudPlatform/anthos-config-management-samples
          syncBranch: main
        policyController:
          enabled: true
          referentialRulesEnabled: true
          templateLibraryInstalled: true
      

      Para obtener más información sobre los campos de configuración de la CLI de Google Cloud, consulta Campos de especificación de aplicación de gcloud.

      Aplica el archivo:

      gcloud beta container fleet config-management apply \
          --membership ${MEMBERSHIP} \
          --config ~/asm-acm-tutorial-dir/acm-config.yaml
      

      Config Connector

      Usa el siguiente GKEHubFeatureMembership manifiesto:

      apiVersion: gkehub.cnrm.cloud.google.com/v1beta1
      kind: GKEHubFeatureMembership
      metadata:
        name: configmanagement-membership
      spec:
        projectRef:
          external: PROJECT_ID
        location: global
        membershipRef:
          name: asm-acm-tutorial
        featureRef:
          name: configmanagement
        configmanagement:
          configSync:
            sourceFormat: unstructured
            git:
              policyDir: asm-acm-tutorial/root-sync/init
              secretType: none
              syncBranch: main
              syncRepo: https://github.com/GoogleCloudPlatform/anthos-config-management-samples
          policyController:
            enabled: true
            referentialRulesEnabled: true
            templateLibraryInstalled: true
      

      Policy Controller y Config Sync están instalados en tu clúster. A continuación, Config Sync empezará a sincronizar todas las configuraciones del RootSync predeterminado con tu clúster. Estas configuraciones instalan y configuran los siguientes componentes clave:

      • Los objetos RepoSync que configuran las aplicaciones de Online Boutique y la puerta de enlace de entrada se sincronizan:

        apiVersion: configsync.gke.io/v1beta1
        kind: RepoSync
        metadata:
          name: repo-sync
        spec:
          override:
            enableShellInRendering: true
          sourceFormat: unstructured
          git:
            repo: https://github.com/GoogleCloudPlatform/anthos-config-management-samples
            revision: HEAD
            branch: main
            dir: asm-acm-tutorial/online-boutique/init
            auth: none
        apiVersion: configsync.gke.io/v1beta1
        kind: RepoSync
        metadata:
          name: repo-sync
        spec:
          override:
            enableShellInRendering: true
          sourceFormat: unstructured
          git:
            repo: https://github.com/GoogleCloudPlatform/anthos-config-management-samples
            revision: HEAD
            branch: main
            dir: asm-acm-tutorial/ingress-gateway/init
            auth: none
      • Como los reconciliadores de RepoSync necesitan permisos adicionales para crear recursos de Istio, también se aplican a tu clúster un objeto ClusterRole y dos objetos RoleBinding para conceder estos permisos:

        apiVersion: rbac.authorization.k8s.io/v1
        kind: ClusterRole
        metadata:
          labels:
            rbac.authorization.k8s.io/aggregate-to-edit: "true"
          name: custom:aggregate-to-edit:istio
        rules:
        - apiGroups:
          - "networking.istio.io"
          - "security.istio.io"
          resources:
          - "virtualservices"
          - "authorizationpolicies"
          - "gateways"
          verbs:
          - "*"
        apiVersion: rbac.authorization.k8s.io/v1
        kind: RoleBinding
        metadata:
          name: repo-sync
        subjects:
        - kind: ServiceAccount
          name: ns-reconciler-onlineboutique
          namespace: config-management-system
        roleRef:
          kind: ClusterRole
          name: edit
          apiGroup: rbac.authorization.k8s.io
        apiVersion: rbac.authorization.k8s.io/v1
        kind: RoleBinding
        metadata:
          name: repo-sync
        subjects:
        - kind: ServiceAccount
          name: ns-reconciler-asm-ingress
          namespace: config-management-system
        roleRef:
          kind: ClusterRole
          name: edit
          apiGroup: rbac.authorization.k8s.io
    5. Para asegurarte de que Policy Controller y Config Sync se han instalado correctamente, comprueba el estado:

      gcloud beta container fleet config-management status
      

      El resultado debería ser similar al siguiente:

      Name: asm-acm-tutorial
      Status: SYNCED
      Last_Synced_Token: 4b3384d
      Sync_Branch: main
      Last_Synced_Time: 2022-05-04T21:32:58Z
      Policy_Controller: INSTALLED
      

      Si ves PENDING o NOT_INSTALLED en las filas Status o Policy_Controller, espera unos minutos y vuelve a ejecutar gcloud beta container fleet config-management status.

    6. Para asegurarte de que Cloud Service Mesh se ha instalado correctamente, describe su estado:

      gcloud container fleet mesh describe
      

      El resultado debería ser similar al siguiente:

      createTime: '2022-09-13T23:12:56.477042921Z'
      membershipSpecs:
        projects/PROJECT_NUMBER/locations/global/memberships/asm-acm-tutorial:
          mesh:
            management: MANAGEMENT_AUTOMATIC
      membershipStates:
        projects/PROJECT_NUMBER/locations/global/memberships/asm-acm-tutorial:
          servicemesh:
            controlPlaneManagement:
              details:
              - code: REVISION_READY
                details: 'Ready: asm-managed'
              state: ACTIVE
            dataPlaneManagement:
              details:
              - code: OK
                details: Service is running.
              state: ACTIVE
          state:
            code: OK
            description: |-
              Revision(s) ready for use: asm-managed.
              All Canonical Services have been reconciled successfully.
            updateTime: '2022-09-14T00:19:10.571552206Z'
      name: projects/PROJECT_ID/locations/global/features/servicemesh
      resourceState:
        state: ACTIVE
      spec: {}
      state:
        state: {}
      updateTime: '2022-09-14T00:19:14.135113118Z'
      

      Si ves state.code: ERROR en lugar de state.code: OK, espera unos minutos y vuelve a ejecutar gcloud container fleet mesh describe. Antes de continuar con el tutorial, debes asegurarte de que el campo servicemesh.controlPlaneManagement.details.code tenga el valor REVISION_READY.

    Desplegar una pasarela de entrada y una aplicación de ejemplo

    En esta sección, desplegarás la aplicación de ejemplo Online Boutique y una puerta de enlace de entrada para gestionar el tráfico de entrada.

    1. Despliega la aplicación de ejemplo Online Boutique y la puerta de enlace de entrada.

      El siguiente comando usa sed para actualizar el manifiesto acm-config.yaml y conseguir que Config Sync implemente los recursos que necesitas para implementar la pasarela de entrada y la aplicación de ejemplo.

      sed -i "s,root-sync/init,root-sync/deployments,g" ~/asm-acm-tutorial-dir/acm-config.yaml
      gcloud beta container fleet config-management apply \
          --membership ${MEMBERSHIP} \
          --config ~/asm-acm-tutorial-dir/acm-config.yaml
      

      Ten en cuenta que este paso puede tardar unos minutos en completarse.

    2. Consulta el estado de Config Sync de RootSync y de los dos RepoSyncs:

      gcloud alpha anthos config sync repo describe
      

      La salida es similar a la siguiente:

      getting 3 RepoSync and RootSync from projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial
      [
        {
          "clusters": [
            "projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial"
          ],
          "commit": "95a30c052566357afb9db3d7f6153d9c0f219c03",
          "errors": [],
          "source": "https://github.com/GoogleCloudPlatform/anthos-config-management-samples//asm-acm-tutorial/root-sync/deployments@main",
          "status": "SYNCED"
        },
        {
          "clusters": [
            "projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial"
          ],
          "commit": "95a30c052566357afb9db3d7f6153d9c0f219c03",
          "errors": [],
          "source": "https://github.com/GoogleCloudPlatform/anthos-config-management-samples//asm-acm-tutorial/ingress-gateway/deployments@main",
          "status": "SYNCED"
        },
        {
          "clusters": [
            "projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial"
          ],
          "commit": "95a30c052566357afb9db3d7f6153d9c0f219c03",
          "errors": [],
          "source": "https://github.com/GoogleCloudPlatform/anthos-config-management-samples//asm-acm-tutorial/online-boutique/deployments@main",
          "status": "SYNCED"
        }
      ]
      

      Si ves status: RECONCILING en lugar de status: SYNCED, espera unos minutos y vuelve a ejecutar gcloud alpha anthos config sync repo describe.

      Para ver solo la información de un repositorio, puedes usar las marcas --sync-name y --sync-namespace. Para ver los recursos gestionados en detalle, añade la marca --managed-resources. Para obtener más información, consulta Ver el estado de Config Sync en varios clústeres.

    3. Espera a que se aprovisione la dirección IP pública de la pasarela de entrada:

      until kubectl -n asm-ingress get svc asm-ingressgateway -o jsonpath='{.status.loadBalancer}' | grep "ingress"; do : ; done
      
    4. Obtén la dirección IP pública de la pasarela de entrada:

      EXTERNAL_IP=$(kubectl get svc asm-ingressgateway -n asm-ingress -o jsonpath="{.status.loadBalancer.ingress[*].ip}")
      
    5. Visita la dirección IP desde tu navegador para verificar que la aplicación Online Boutique se ha implementado correctamente:

      echo http://${EXTERNAL_IP}
      

    Aplicar políticas para proteger tu malla

    En las siguientes secciones, utilizarás Policy Controller para aplicar políticas del paquete de políticas de Cloud Service Mesh creando restricciones.

    Implementar la inserción de proxies de sidecar

    En esta sección, aplicará políticas para asegurarse de que todas las cargas de trabajo de la malla tengan habilitada la inyección automática de sidecar.

    1. Para aplicar la inyección de proxies de sidecar, aplica restricciones.

      El siguiente comando usa sed para actualizar el manifiesto acm-config.yaml y conseguir que Config Sync implemente los recursos asociados.

      sed -i "s,root-sync/deployments,root-sync/enforce-sidecar-injection,g" ~/asm-acm-tutorial-dir/acm-config.yaml
      gcloud beta container fleet config-management apply \
          --membership ${MEMBERSHIP} \
          --config ~/asm-acm-tutorial-dir/acm-config.yaml
      

      El comando anterior implementa los siguientes recursos:

      • Un K8sRequiredLabels Constraint que requiere que cualquier Namespace de la malla contenga la etiqueta de inyección de proxy sidecar de Cloud Service Mesh específica:

        apiVersion: constraints.gatekeeper.sh/v1beta1
        kind: K8sRequiredLabels
        metadata:
          name: namespace-sidecar-injection-label
        spec:
          enforcementAction: deny
          match:
            kinds:
            - apiGroups:
              - ""
              kinds:
              - Namespace
            excludedNamespaces:
            - config-management-monitoring
            - config-management-system
            - default
            - gatekeeper-system
            - gke-connect
            - istio-system
            - kube-node-lease
            - kube-public
            - kube-system
            - resource-group-system
          parameters:
            labels:
            - allowedRegex: enabled
              key: istio-injection
      • Un AsmSidecarInjection Constraint que prohíbe que cualquier Pod de la malla omita la inyección de sidecar de proxy de Istio:

        apiVersion: constraints.gatekeeper.sh/v1beta1
        kind: AsmSidecarInjection
        metadata:
          name: pod-sidecar-injection-annotation
        spec:
          enforcementAction: deny
          match:
            kinds:
            - apiGroups:
              - ""
              kinds:
              - Pod
            excludedNamespaces:
            - kube-system
          parameters:
            strictnessLevel: High
    2. Consulta el estado de Config Sync de RootSync:

      gcloud alpha anthos config sync repo describe \
          --sync-name root-sync \
          --sync-namespace config-management-system
      

      La salida es similar a la siguiente:

      getting 1 RepoSync and RootSync from projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial
      [
        {
          "clusters": [
            "projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial"
          ],
          "commit": "7d15d49af13c44aa531a4565b2277ddcf8b81884",
          "errors": [],
          "source": "https://github.com/GoogleCloudPlatform/anthos-config-management-samples//asm-acm-tutorial/root-sync/enforce-sidecar-injection@main",
          "status": "SYNCED"
        }
      ]
      

      Si ves status: RECONCILING en lugar de status: SYNCED, espera unos minutos y vuelve a ejecutar gcloud alpha anthos config sync repo describe.

    3. Verifica que se hayan creado los Constraints:

      kubectl get constraints
      

      Policy Controller puede tardar unos minutos en evaluar estas restricciones. Si no ve ningún valor en la columna TOTAL-VIOLATIONS, espere y vuelva a ejecutar kubectl get constraints.

      La salida es similar a la siguiente:

      NAME                                                                                       ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
      podsidecarinjectionannotation.constraints.gatekeeper.sh/pod-sidecar-injection-annotation   deny                 0
      
      NAME                                                                            ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
      k8srequiredlabels.constraints.gatekeeper.sh/namespace-sidecar-injection-label   deny                 0
      

      Como hemos configurado correctamente Namespaces y Pods, hay 0 TOTAL-VIOLATIONS para estos Constraints.

    4. Para ver estos Constraints en funcionamiento, intenta crear un Namespace en tu clúster sin label ni annotation:

      kubectl create namespace test
      

      La salida es similar al siguiente error:

      Error from server (Forbidden): admission webhook "validation.gatekeeper.sh" denied the request: [namespace-sidecar-injection-label] you must provide labels: {"istio-injection"}
      

    Forzar el cifrado del tráfico

    En esta sección, aplicará políticas para asegurarse de que todo el tráfico de la malla esté cifrado.

    1. Para aplicar el cifrado del tráfico, aplica restricciones.

      El siguiente comando usa sed para actualizar el manifiesto acm-config.yaml y conseguir que Config Sync implemente los recursos asociados.

      sed -i "s,root-sync/enforce-sidecar-injection,root-sync/enforce-strict-mtls,g" ~/asm-acm-tutorial-dir/acm-config.yaml
      gcloud beta container fleet config-management apply \
          --membership ${MEMBERSHIP} \
          --config ~/asm-acm-tutorial-dir/acm-config.yaml
      

      El comando anterior implementa los siguientes recursos:

      • Un AsmPeerAuthnMeshStrictMtls Constraint que aplica el mTLS a nivel de malla PeerAuthentication en el espacio de nombres istio-system:

        apiVersion: constraints.gatekeeper.sh/v1beta1
        kind: AsmPeerAuthnMeshStrictMtls
        metadata:
          name: mesh-level-strict-mtls
        spec:
          enforcementAction: deny
          parameters:
            rootNamespace: istio-system
            strictnessLevel: High
      • Una restricción referencial Config en el espacio de nombres gatekeeper-system. Esta restricción referencial permite que AsmPeerAuthnMeshStrictMtls Constraint haga referencia a otro objeto en su definición (por ejemplo, buscar cualquier PeerAuthentication en istio-system Namespace):

        apiVersion: config.gatekeeper.sh/v1alpha1
        kind: Config
        metadata:
          name: config
        spec:
          sync:
            syncOnly:
              - group: ""
                version: "v1"
                kind: "Namespace"
              - group: "security.istio.io"
                version: "v1beta1"
                kind: "PeerAuthentication"
              - group: "security.istio.io"
                version: "v1beta1"
                kind: "AuthorizationPolicy"
      • Un DestinationRuleTLSEnabled Constraint que prohíbe inhabilitar TLS para todos los hosts y subconjuntos de hosts en Istio DestinationRules:

        apiVersion: constraints.gatekeeper.sh/v1beta1
        kind: DestinationRuleTLSEnabled
        metadata:
          name: destination-rule-tls-enabled
        spec:
          enforcementAction: deny
          match:
            kinds:
            - apiGroups:
              - networking.istio.io
              kinds:
              - DestinationRule
      • Un AsmPeerAuthnStrictMtls Constraint que obliga a que todos los PeerAuthentications no puedan sobrescribir STRICT mTLS:

        apiVersion: constraints.gatekeeper.sh/v1beta1
        kind: AsmPeerAuthnStrictMtls
        metadata:
          name: peerauthentication-strict-mtls
        spec:
          enforcementAction: deny
          match:
            kinds:
            - apiGroups:
              - security.istio.io
              kinds:
              - PeerAuthentication
          parameters:
            strictnessLevel: High
    2. Consulta el estado de Config Sync de RootSync:

      gcloud alpha anthos config sync repo describe \
          --sync-name root-sync \
          --sync-namespace config-management-system
      

      La salida es similar a la siguiente:

      getting 1 RepoSync and RootSync from projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial
      [
        {
          "clusters": [
            "projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial"
          ],
          "commit": "7d15d49af13c44aa531a4565b2277ddcf8b81884",
          "errors": [],
          "source": "https://github.com/GoogleCloudPlatform/anthos-config-management-samples//asm-acm-tutorial/root-sync/enforce-strict-mtls@main",
          "status": "SYNCED"
        }
      ]
      

      Si ves status: RECONCILING en lugar de status: SYNCED, espera unos minutos y vuelve a ejecutar gcloud alpha anthos config sync repo describe.

    3. Ejecuta el siguiente comando para obtener más información sobre la infracción PeerAuthentication:

      kubectl get asmpeerauthnmeshstrictmtls.constraints.gatekeeper.sh/mesh-level-strict-mtls -ojsonpath='{.status.violations}'  | jq
      

      La salida es similar a la siguiente:

      [
        {
          "enforcementAction": "deny",
          "group": "constraints.gatekeeper.sh",
          "kind": "AsmPeerAuthnMeshStrictMtls",
          "message": "Root namespace <istio-system> does not have a strict mTLS PeerAuthentication",
          "name": "mesh-level-strict-mtls",
          "version": "v1beta1"
        }
      ]
      
    4. Para solucionar el problema, implementa un PeerAuthentication en el istio-system. Para evitar que todos tus servicios de la malla acepten tráfico sin cifrar, define una política PeerAuthentication en toda la malla con el modo mTLS definido como STRICT. Cuando implementas la política, el plano de control aprovisiona automáticamente certificados TLS para que las cargas de trabajo puedan autenticarse entre sí.

      El siguiente comando usa sed para actualizar el manifiesto acm-config.yaml y conseguir que Config Sync implemente los recursos asociados.

      sed -i "s,root-sync/enforce-strict-mtls,root-sync/fix-strict-mtls,g" ~/asm-acm-tutorial-dir/acm-config.yaml
      gcloud beta container fleet config-management apply \
          --membership ${MEMBERSHIP} \
          --config ~/asm-acm-tutorial-dir/acm-config.yaml
      

      El comando anterior implementa el siguiente STRICT mTLS PeerAuthentication en el espacio de nombres istio-system. Esto aplica mTLS STRICT a toda la malla:

      apiVersion: security.istio.io/v1beta1
      kind: PeerAuthentication
      metadata:
        name: default
      spec:
        mtls:
          mode: STRICT
    5. Consulta el estado de Config Sync de RootSync:

      gcloud alpha anthos config sync repo describe \
          --sync-name root-sync \
          --sync-namespace config-management-system
      

      La salida es similar a la siguiente:

      getting 1 RepoSync and RootSync from projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial
      [
        {
          "clusters": [
            "projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial"
          ],
          "commit": "7d15d49af13c44aa531a4565b2277ddcf8b81884",
          "errors": [],
          "source": "https://github.com/GoogleCloudPlatform/anthos-config-management-samples//asm-acm-tutorial/root-sync/fix-strict-mtls@main",
          "status": "SYNCED"
        }
      ]
      

      Si ves status: RECONCILING en lugar de status: SYNCED, espera unos minutos y vuelve a ejecutar gcloud alpha anthos config sync repo describe.

    6. Verifica que se hayan creado los Constraints:

      kubectl get constraints
      

      Ten en cuenta que Policy Controller puede tardar unos minutos en evaluar estos Constraints. Espera y vuelve a ejecutar este comando kubectl get constraints hasta que obtengas valores en la columna TOTAL-VIOLATIONS de cada línea.

      La salida es similar a la siguiente:

      NAME                                                                            ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
      k8srequiredlabels.constraints.gatekeeper.sh/namespace-sidecar-injection-label   deny                 0
      NAME                                                                          ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
      asmpeerauthnmeshstrictmtls.constraints.gatekeeper.sh/mesh-level-strict-mtls   deny                 0
      NAME                                                                               ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
      destinationruletlsenabled.constraints.gatekeeper.sh/destination-rule-tls-enabled   deny                 0
      NAME                                                                              ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
      asmpeerauthnstrictmtls.constraints.gatekeeper.sh/peerauthentication-strict-mtls   deny                 0
      NAME                                                                             ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
      asmsidecarinjection.constraints.gatekeeper.sh/pod-sidecar-injection-annotation   deny                 0
      

    Aplica controles de acceso pormenorizados

    En esta sección, aplicará políticas para asegurarse de que todas las cargas de trabajo de la malla tengan un control de acceso granular.

    1. Para aplicar un control de acceso pormenorizado, aplica restricciones.

      El siguiente comando usa sed para actualizar el manifiesto acm-config.yaml y conseguir que Config Sync implemente los recursos asociados.

      sed -i "s,root-sync/fix-strict-mtls,root-sync/enforce-authorization-policies,g" ~/asm-acm-tutorial-dir/acm-config.yaml
      gcloud beta container fleet config-management apply \
          --membership ${MEMBERSHIP} \
          --config ~/asm-acm-tutorial-dir/acm-config.yaml
      

      El comando anterior implementa los siguientes recursos:

      • Un AsmAuthzPolicyDefaultDeny Constraint que aplica la denegación predeterminada a nivel de malla AuthorizationPolicy en el espacio de nombres istio-system:

        apiVersion: constraints.gatekeeper.sh/v1beta1
        kind: AsmAuthzPolicyDefaultDeny
        metadata:
          name: default-deny-authorization-policies
        spec:
          enforcementAction: deny
          parameters:
            rootNamespace: istio-system
            strictnessLevel: High
      • Un AsmAuthzPolicyEnforceSourcePrincipals Constraint que obliga a que cualquier AuthorizationPolicies defina principales de origen granulares (que no sean "*"). La única excepción a esta regla es la pasarela de entrada del espacio de nombres asm-ingress, que puede recibir el tráfico de los usuarios finales y redirigirlo a la aplicación frontend de Online Boutique.

        apiVersion: constraints.gatekeeper.sh/v1beta1
        kind: AsmAuthzPolicyEnforceSourcePrincipals
        metadata:
          name: authz-source-principals-not-all
        spec:
          enforcementAction: deny
          match:
            kinds:
            - apiGroups:
              - security.istio.io
              kinds:
              - AuthorizationPolicy
            excludedNamespaces:
              - asm-ingress
    2. Consulta el estado de Config Sync de RootSync:

      gcloud alpha anthos config sync repo describe \
          --sync-name root-sync \
          --sync-namespace config-management-system
      

      La salida es similar a la siguiente:

      getting 1 RepoSync and RootSync from projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial
      [
        {
          "clusters": [
            "projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial"
          ],
          "commit": "7d15d49af13c44aa531a4565b2277ddcf8b81884",
          "errors": [],
          "source": "https://github.com/GoogleCloudPlatform/anthos-config-management-samples//asm-acm-tutorial/root-sync/enforce-authorization-policies@main",
          "status": "SYNCED"
        }
      ]
      

      Si ves status: RECONCILING en lugar de status: SYNCED, espera unos minutos y vuelve a ejecutar gcloud alpha anthos config sync repo describe.

    3. Ejecuta el siguiente comando para obtener más información sobre la infracción asociada:

      kubectl get asmauthzpolicydefaultdeny.constraints.gatekeeper.sh/default-deny-authorization-policies -ojsonpath='{.status.violations}'  | jq
      

      La salida es similar a la siguiente:

      [
        {
          "enforcementAction": "deny",
          "group": "constraints.gatekeeper.sh",
          "kind": "AsmAuthzPolicyDefaultDeny",
          "message": "Root namespace <istio-system> does not have a default deny AuthorizationPolicy",
          "name": "default-deny-authorization-policies",
          "version": "v1beta1"
        }
      ]
      
    4. Soluciona el problema implementando el AuthorizationPolicy en el espacio de nombres istio-system.

      El siguiente comando usa sed para actualizar el manifiesto acm-config.yaml y conseguir que Config Sync implemente los recursos asociados.

      sed -i "s,root-sync/enforce-authorization-policies,root-sync/fix-default-deny-authorization-policy,g" ~/asm-acm-tutorial-dir/acm-config.yaml
      gcloud beta container fleet config-management apply \
          --membership ${MEMBERSHIP} \
          --config ~/asm-acm-tutorial-dir/acm-config.yaml
      

      El comando anterior implementa el siguiente AuthorizationPolicy de denegación total en el espacio de nombres istio-system:

      apiVersion: security.istio.io/v1beta1
      kind: AuthorizationPolicy
      metadata:
        name: deny-all
      spec:
        {}
    5. Consulta el estado de Config Sync de RootSync:

      gcloud alpha anthos config sync repo describe \
          --sync-name root-sync \
          --sync-namespace config-management-system
      

      La salida es similar a la siguiente:

      getting 1 RepoSync and RootSync from projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial
      [
        {
          "clusters": [
            "projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial"
          ],
          "commit": "7d15d49af13c44aa531a4565b2277ddcf8b81884",
          "errors": [],
          "source": "https://github.com/GoogleCloudPlatform/anthos-config-management-samples//asm-acm-tutorial/root-sync/fix-default-deny-authorization-policy@main",
          "status": "SYNCED"
        }
      ]
      

      Si ves status: RECONCILING en lugar de status: SYNCED, espera unos minutos y vuelve a ejecutar gcloud alpha anthos config sync repo describe.

    6. Verifica que se hayan creado los Constraints:

      kubectl get constraints
      

      Ten en cuenta que Policy Controller puede tardar unos minutos en evaluar estos Constraints. Espera y vuelve a ejecutar este comando kubectl get constraints hasta que obtengas valores en la columna TOTAL-VIOLATIONS de cada línea.

      La salida es similar a la siguiente:

      NAME                                                                             ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
      asmsidecarinjection.constraints.gatekeeper.sh/pod-sidecar-injection-annotation   deny                 0
      NAME                                                                            ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
      k8srequiredlabels.constraints.gatekeeper.sh/namespace-sidecar-injection-label   deny                 0
      NAME                                                                                      ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
      asmauthzpolicydefaultdeny.constraints.gatekeeper.sh/default-deny-authorization-policies   deny                 0
      NAME                                                                          ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
      asmpeerauthnmeshstrictmtls.constraints.gatekeeper.sh/mesh-level-strict-mtls   deny                 0
      NAME                                                                               ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
      destinationruletlsenabled.constraints.gatekeeper.sh/destination-rule-tls-enabled   deny                 0
      NAME                                                                              ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
      asmpeerauthnstrictmtls.constraints.gatekeeper.sh/peerauthentication-strict-mtls   deny                 0
      NAME                                                                                              ENFORCEMENT-ACTION   TOTAL-VIOLATIONS
      asmauthzpolicyenforcesourceprincipals.constraints.gatekeeper.sh/authz-source-principals-not-all   deny                 0
      
    7. Visita la aplicación Online Boutique desde tu navegador:

      echo http://${EXTERNAL_IP}
      

      Deberías recibir el error RBAC: access denied, que confirma que el valor predeterminado de denegación AuthorizationPolicy se aplica a toda la malla.

    8. Para solucionar este problema, implementa AuthorizationPolicies más granulares en los espacios de nombres asm-ingress y onlineboutique.

      El siguiente comando usa sed para actualizar el manifiesto acm-config.yaml y conseguir que Config Sync implemente los recursos asociados.

      sed -i "s,root-sync/fix-default-deny-authorization-policy,root-sync/deploy-authorization-policies,g" ~/asm-acm-tutorial-dir/acm-config.yaml
      gcloud beta container fleet config-management apply \
          --membership ${MEMBERSHIP} \
          --config ~/asm-acm-tutorial-dir/acm-config.yaml
      

      El comando anterior implementa los siguientes recursos:

      • Un AuthorizationPolicy en el espacio de nombres asm-ingress

        apiVersion: security.istio.io/v1beta1
        kind: AuthorizationPolicy
        metadata:
          name: asm-ingressgateway
        spec:
          selector:
            matchLabels:
              asm: ingressgateway
          rules:
          - to:
            - operation:
                ports:
                - "8080"
      • Un AuthorizationPolicy por aplicación en el espacio de nombres onlineboutique. A continuación se muestra un ejemplo de la aplicación cartservice:

        apiVersion: security.istio.io/v1beta1
        kind: AuthorizationPolicy
        metadata:
          name: cartservice
        spec:
          selector:
            matchLabels:
              app: cartservice
          rules:
          - from:
            - source:
                principals:
                - cluster.local/ns/onlineboutique/sa/frontend
                - cluster.local/ns/onlineboutique/sa/checkoutservice
            to:
            - operation:
                paths:
                - /hipstershop.CartService/AddItem
                - /hipstershop.CartService/GetCart
                - /hipstershop.CartService/EmptyCart
                methods:
                - POST
                ports:
                - "7070"
      • Un ServiceAccount por aplicación en los espacios de nombres asm-ingress y onlineboutique para tener una identidad única por aplicación evaluada como principal en AuthorizationPolicies. Aquí tienes un ejemplo de la aplicación cartservice:

        apiVersion: v1
        kind: ServiceAccount
        metadata:
          name: cartservice
    9. Consulta el estado de Config Sync de RootSync y de los dos RepoSyncs:

      gcloud alpha anthos config sync repo describe
      

      La salida es similar a la siguiente:

      getting 3 RepoSync and RootSync from projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial
      [
        {
          "clusters": [
            "projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial"
          ],
          "commit": "7d15d49af13c44aa531a4565b2277ddcf8b81884",
          "errors": [],
          "source": "https://github.com/GoogleCloudPlatform/anthos-config-management-samples//asm-acm-tutorial/root-sync/deploy-authorization-policies@main",
          "status": "SYNCED"
        },
        {
          "clusters": [
            "projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial"
          ],
          "commit": "7d15d49af13c44aa531a4565b2277ddcf8b81884",
          "errors": [],
          "source": "https://github.com/GoogleCloudPlatform/anthos-config-management-samples//asm-acm-tutorial/ingress-gateway/authorization-policies@main",
          "status": "SYNCED"
        },
        {
          "clusters": [
            "projects/PROJECT_ID/locations/global/memberships/asm-acm-tutorial"
          ],
          "commit": "7d15d49af13c44aa531a4565b2277ddcf8b81884",
          "errors": [],
          "source": "https://github.com/GoogleCloudPlatform/anthos-config-management-samples//asm-acm-tutorial/online-boutique/authorization-policies@main",
          "status": "SYNCED"
        }
      ]
      

      Si ves status: RECONCILING en lugar de status: SYNCED, espera unos minutos y vuelve a ejecutar gcloud alpha anthos config sync repo describe.

      Para ver solo la información de un repositorio, puedes usar las marcas --sync-name y --sync-namespace. Para ver los recursos gestionados en detalle, puedes añadir la marca --managed-resources. Para obtener más información, consulta Ver el estado de Config Sync en varios clústeres.

    10. Vuelve a visitar la aplicación Online Boutique desde tu navegador:

      echo http://${EXTERNAL_IP}
      

      Si esperas unos minutos, el sitio web debería volver a funcionar correctamente.

    Ver el estado de las funciones de seguridad de GKE Enterprise

    Puedes consultar el estado de las funciones de seguridad de GKE Enterprise, incluidas las políticas de autenticación y autorización, en la Google Cloud consola.

    1. En la Google Cloud consola, ve a la página Seguridad de GKE Enterprise.

      Ir a Seguridad de GKE Enterprise

      En Resumen de políticas se muestra el estado de la seguridad de las aplicaciones, incluido el control de acceso a servicios (AuthorizationPolicies) y mTLS.

    2. Haz clic en Auditoría de políticas para ver los estados de las políticas de cargas de trabajo del clúster y de ambos espacios de nombres (asm-ingress y onlineboutique).

      Las tarjetas Control de acceso a los servicios y Estado de mTLS ofrecen una descripción general.

      Resumen general del control de acceso a servicios y del estado de mTLS

      La lista Cargas de trabajo muestra el control de acceso al servicio y el estado de mTLS de cada carga de trabajo.

      Lista detallada de cada carga de trabajo y su control de acceso al servicio y estado de mTLS

    Ahora has protegido tu clúster y tu malla con Policy Controller y Config Sync.

Limpieza

Para evitar que los recursos utilizados en este tutorial se cobren en tu cuenta de Google Cloud, elimina el proyecto que contiene los recursos o conserva el proyecto y elimina los recursos.

Eliminar el proyecto

    Delete a Google Cloud project:

    gcloud projects delete PROJECT_ID

Eliminar recursos concretos

Para eliminar los recursos concretos, sigue estos pasos:

  1. Da de baja el clúster de la flota:

    gcloud

    gcloud container fleet memberships unregister ${CLUSTER} \
        --project=${PROJECT_ID} \
        --gke-cluster=${CLUSTER_ZONE}/${CLUSTER}
    

    El resultado debería ser similar al siguiente:

    kubeconfig entry generated for asm-acm-tutorial.
    Waiting for membership to be deleted...done.
    Deleting membership CR in the cluster...done.
    Deleting namespace [gke-connect] in the cluster...done.
    

    Config Connector

    kubectl delete -f ~/asm-acm-tutorial-dir/fleet-membership.yaml
    
  2. Elimina el clúster:

    gcloud

    gcloud container clusters delete ${CLUSTER} \
        --zone ${CLUSTER_ZONE}
    

    Pulsa y cuando se te pida. Este comando puede tardar más de cinco minutos en completarse.

    El resultado debería ser similar al siguiente:

    Deleting cluster asm-acm-tutorial...done.
    Deleted [https://container.googleapis.com/v1/projects/PROJECT_ID/zones/us-east4-a/clusters/asm-acm-tutorial].
    

    Config Connector

    kubectl delete -f ~/asm-acm-tutorial-dir/container-cluster.yaml
    
  3. Elimina los archivos que has creado:

    rm -r ~/asm-acm-tutorial-dir
    

Siguientes pasos