Configurar la seguridad de los servicios con gRPC sin proxy
En esta guía se explica cómo configurar un servicio de seguridad para una malla de servicios gRPC sin proxy.
Requisitos
Antes de configurar la seguridad del servicio para la malla de servicios gRPC sin proxy, asegúrate de que cumples los siguientes requisitos.
- Tu implementación cumple los requisitos que se indican en el artículo Prepararse para configurar las APIs de enrutamiento en el servicio con Envoy y cargas de trabajo sin proxy.
- Debes usar xDS v3.
- Tienes acceso a la versión de xDS y a la funcionalidad del proveedor de certificados que necesitas con uno de los siguientes lenguajes:
- gRPC Java
- gRPC C++
- gRPC Python
- gRPC Go Puedes encontrar las versiones de idioma necesarias en GitHub.
- Tienes acceso al generador de bootstrap, versión 0.16.0. La imagen del generador de bootstrap se encuentra en el Google Cloud repositorio de contenedores.
- Cumples todos los requisitos previos para el balanceo de carga de la malla de servicios sin proxy de gRPC.
- Tienes permisos suficientes para crear o actualizar los recursos de Cloud Service Mesh y de malla de servicios para usar la seguridad de PSM.Google Cloud Para obtener información completa sobre los permisos necesarios, consulta Prepararse para configurar Cloud Service Mesh con servicios de gRPC sin proxy.
- Tienes los permisos necesarios para usar el Servicio de Autoridades de Certificación, que se describen en el artículo Crear autoridades de certificación para emitir certificados.
Configurar la gestión de identidades y accesos
Debes tener los permisos necesarios para usar Google Kubernetes Engine. Como mínimo, debes tener los siguientes roles:
roles/container.clusterAdmin
rol de GKE- Rol de
roles/compute.instanceAdmin
Compute Engine - Rol de
roles/iam.serviceAccountUser
Para crear los recursos necesarios para la configuración, debe tener el rol compute.NetworkAdmin
. Este rol contiene todos los permisos necesarios para crear, actualizar, eliminar, enumerar y usar (es decir, hacer referencia a este en otros recursos) los recursos necesarios. Si eres el propietario y editor de tu proyecto, tienes este rol automáticamente.
Ten en cuenta que networksecurity.googleapis.com.clientTlsPolicies.use
y networksecurity.googleapis.com.serverTlsPolicies.use
no se aplican cuando haces referencia a estos recursos en el recurso de servicio de backend.
Si se aplica en el futuro y usas el rol compute.NetworkAdmin
, no notarás ningún problema cuando se aplique esta comprobación.
Si usas roles personalizados y esta comprobación se aplica en el futuro, debes incluir el permiso .use
correspondiente. De lo contrario, en el futuro, es posible que tu rol personalizado no tenga los permisos necesarios para hacer referencia a clientTlsPolicy
o serverTlsPolicy
desde el servicio backend.
Prepararse para la configuración
La seguridad de la malla de servicios sin proxy (PSM) añade seguridad a una malla de servicios configurada para el balanceo de carga según la documentación de los servicios gRPC sin proxy. En una malla de servicios sin proxy, un cliente gRPC usa el esquema xds:
en el URI para acceder al servicio, lo que habilita las funciones de balanceo de carga y descubrimiento de endpoints de PSM.
Actualizar los clientes y servidores gRPC a la versión correcta
Crea o vuelve a crear tus aplicaciones con la versión mínima admitida de gRPC para tu lenguaje.
Actualizar el archivo de arranque
Las aplicaciones gRPC usan un único archivo de arranque, que debe tener todos los campos que requiere el código del lado del cliente y del servidor de gRPC. Un generador de bootstrap genera automáticamente el archivo de bootstrap para incluir las marcas y los valores que necesita la seguridad de PSM. Para obtener más información, consulta la sección Archivo de arranque, que incluye un archivo de arranque de ejemplo.
Descripción general de la configuración
Este proceso de configuración es una extensión de la configuración de Cloud Service Mesh con GKE y servicios de gRPC sin proxy. Los pasos de ese procedimiento de configuración que no se hayan modificado se mencionan en los casos en los que se apliquen.
Estas son las principales mejoras de la configuración de Cloud Service Mesh con GKE:
- Configurar el servicio de AC, en el que creas grupos de AC privadas y las autoridades de certificación necesarias.
- Crear un clúster de GKE con las funciones de Workload Identity Federation for GKE y de certificados de malla, así como con la integración de CA Service.
- Configurar la emisión de certificados de malla en el clúster.
- Crear las cuentas de servicio de cliente y de servidor.
- Configurar el servidor de ejemplo que usa las APIs xDS y las credenciales del servidor xDS para obtener la configuración de seguridad de Cloud Service Mesh.
- Configurar el cliente de ejemplo que usa credenciales de xDS.
- Actualizar la configuración de la malla de servicios de Cloud para incluir la configuración de seguridad.
Puedes ver ejemplos de código para usar las credenciales de xDS en las siguientes ubicaciones:
Actualizar Google Cloud CLI
Para actualizar la CLI de Google Cloud, ejecuta el siguiente comando:
gcloud components update
Configurar variables de entorno
En esta guía, se usan comandos de Cloud Shell y la información repetida en los comandos se representa mediante varias variables de entorno. Asigna tus valores específicos a las siguientes variables de entorno en el entorno de shell antes de ejecutar los comandos. Cada línea de comentario indica el significado de la variable de entorno asociada.
# Your project ID PROJECT_ID=PROJECT_ID # GKE cluster name and zone for this example. CLUSTER_NAME=CLUSTER_NAME ZONE=ZONE gcloud config set compute/zone $ZONE # GKE cluster URL derived from the above GKE_CLUSTER_URL="https://container.googleapis.com/v1/projects/${PROJECT_ID}/locations/${ZONE}/clusters/${CLUSTER_NAME}" # Workload pool to be used with the GKE cluster WORKLOAD_POOL="${PROJECT_ID}.svc.id.goog" # Kubernetes namespace to run client and server demo. K8S_NAMESPACE='default' DEMO_BACKEND_SERVICE_NAME='grpc-gke-helloworld-service' # Compute other values # Project number for your project PROJNUM=$(gcloud projects describe ${PROJECT_ID} --format="value(projectNumber)") # VERSION is the GKE cluster version. Install and use the most recent version # from the rapid release channel and substitute its version for # CLUSTER_VERSION, for example: # VERSION=latest available version # Note that the minimum required cluster version is 1.21.4-gke.1801. VERSION="CLUSTER_VERSION" SA_GKE=service-${PROJNUM}@container-engine-robot.iam.gserviceaccount.com
Habilitar el acceso a las APIs necesarias
En esta sección se explica cómo habilitar el acceso a las APIs necesarias.
Ejecuta el siguiente comando para habilitar Cloud Service Mesh y otras APIs necesarias para la seguridad de la malla de servicios gRPC sin proxy.
gcloud services enable \ container.googleapis.com \ cloudresourcemanager.googleapis.com \ compute.googleapis.com \ trafficdirector.googleapis.com \ networkservices.googleapis.com \ networksecurity.googleapis.com \ privateca.googleapis.com \ gkehub.googleapis.com
Ejecuta el siguiente comando para permitir que la cuenta de servicio predeterminada acceda a la API de seguridad de Cloud Service Mesh.
GSA_EMAIL=$(gcloud iam service-accounts list --format='value(email)' \ --filter='displayName:Compute Engine default service account') gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member serviceAccount:${GSA_EMAIL} \ --role roles/trafficdirector.client
Crear o actualizar un clúster de GKE
La seguridad de los servicios de Cloud Service Mesh depende de la integración del servicio de CA con GKE. El clúster de GKE debe cumplir los siguientes requisitos, además de los requisitos de configuración:
- Usa una versión de clúster mínima de 1.21.4-gke.1801. Si necesitas funciones que estén en una versión posterior, puedes obtenerla del canal de lanzamiento rápido.
- El clúster de GKE debe estar habilitado y configurado con certificados de malla, tal como se describe en el artículo Crear autoridades de certificación para emitir certificados.
Crea un clúster que use Workload Identity Federation para GKE. Si vas a actualizar un clúster, ve al siguiente paso. El valor que proporciones para
--tags
debe coincidir con el nombre que se haya pasado a la marca--target-tags
del comandofirewall-rules create
en la sección Configurar Cloud Service Mesh con componentes de Cloud Load Balancing.# Create a GKE cluster with GKE managed mesh certificates. gcloud container clusters create CLUSTER_NAME \ --release-channel=rapid \ --scopes=cloud-platform \ --image-type=cos_containerd \ --machine-type=e2-standard-2 \ --zone=ZONE \ --workload-pool=PROJECT_ID.svc.id.goog \ --enable-mesh-certificates \ --cluster-version=CLUSTER_VERSION \ --enable-ip-alias \ --tags=allow-health-checks \ --workload-metadata=GKE_METADATA
La creación del clúster puede tardar varios minutos en completarse.
Si utilizas un clúster, activa Workload Identity Federation para GKE y los certificados de malla de GKE. Asegúrate de que el clúster se haya creado con la marca
--enable-ip-alias
, que no se puede usar con el comandoupdate
.gcloud container clusters update CLUSTER_NAME \ --enable-mesh-certificates
Ejecuta el siguiente comando para cambiar al nuevo clúster como clúster predeterminado para tus comandos
kubectl
:gcloud container clusters get-credentials CLUSTER_NAME \ --zone ZONE
Registrar clústeres en una flota
Registra el clúster que has creado o actualizado en Crear un clúster de GKE con una flota. Si registras el clúster, te resultará más fácil configurar clústeres en varios proyectos.
Ten en cuenta que cada uno de estos pasos puede tardar hasta diez minutos en completarse.
Registra tu clúster en la flota:
gcloud container fleet memberships register CLUSTER_NAME \ --gke-cluster=ZONE/CLUSTER_NAME \ --enable-workload-identity --install-connect-agent \ --manifest-output-file=MANIFEST-FILE_NAME
Sustituye las variables de la siguiente manera:
- CLUSTER_NAME: el nombre del clúster.
- ZONE: la zona de tu clúster.
- MANIFEST-FILE_NAME: la ruta en la que estos comandos generan el archivo de manifiesto para el registro.
Si el proceso de registro se completa correctamente, verás un mensaje como el siguiente:
Finished registering the cluster CLUSTER_NAME with the fleet.
Aplica el archivo de manifiesto generado a tu clúster:
kubectl apply -f MANIFEST-FILE_NAME
Si el proceso de solicitud se completa correctamente, verás mensajes como los siguientes:
namespace/gke-connect created serviceaccount/connect-agent-sa created podsecuritypolicy.policy/gkeconnect-psp created role.rbac.authorization.k8s.io/gkeconnect-psp:role created rolebinding.rbac.authorization.k8s.io/gkeconnect-psp:rolebinding created role.rbac.authorization.k8s.io/agent-updater created rolebinding.rbac.authorization.k8s.io/agent-updater created role.rbac.authorization.k8s.io/gke-connect-agent-20210416-01-00 created clusterrole.rbac.authorization.k8s.io/gke-connect-impersonation-20210416-01-00 created clusterrolebinding.rbac.authorization.k8s.io/gke-connect-impersonation-20210416-01-00 created clusterrolebinding.rbac.authorization.k8s.io/gke-connect-feature-authorizer-20210416-01-00 created rolebinding.rbac.authorization.k8s.io/gke-connect-agent-20210416-01-00 created role.rbac.authorization.k8s.io/gke-connect-namespace-getter created rolebinding.rbac.authorization.k8s.io/gke-connect-namespace-getter created secret/http-proxy created deployment.apps/gke-connect-agent-20210416-01-00 created service/gke-connect-monitoring created secret/creds-gcp create
Obtén el recurso de pertenencia del clúster:
kubectl get memberships membership -o yaml
El resultado debe incluir el grupo de identidades de carga de trabajo asignado por la flota, donde PROJECT_ID es el ID de tu proyecto:
workload_identity_pool: PROJECT_ID.svc.id.goog
Esto significa que el clúster se ha registrado correctamente.
Crear autoridades de certificación para emitir certificados
Para emitir certificados a tus pods, crea un grupo de Servicio de Autoridades de Certificación y las siguientes autoridades de certificación (ACs):
- CA raíz. Es la raíz de confianza de todos los certificados de malla emitidos. Puedes usar una CA raíz que ya tengas. Crea la AC raíz en el nivel
enterprise
, que está pensado para la emisión de certificados de larga duración y bajo volumen. - Autoridad de certificación subordinada. Esta CA emite certificados para cargas de trabajo. Crea la CA subordinada en la región en la que se haya desplegado tu clúster. Crea la AC subordinada en el nivel
devops
, que está diseñado para la emisión de certificados de gran volumen y de corta duración.
Crear una AC subordinada es opcional, pero te recomendamos que lo hagas en lugar de usar tu AC raíz para emitir certificados de malla de GKE. Si decides usar la AC raíz para emitir certificados de malla, asegúrate de que el modo de emisión basado en la configuración predeterminado siga permitido.
La CA subordinada puede estar en una región diferente a la de tu clúster, pero te recomendamos que la crees en la misma región que tu clúster para optimizar el rendimiento. Sin embargo, puedes crear las autoridades de certificación raíz y subordinadas en diferentes regiones sin que esto afecte al rendimiento ni a la disponibilidad.
Estas regiones se admiten en el servicio de autoridades de certificación:
Nombre de la región | Descripción de la región |
---|---|
asia-east1 |
Taiwán |
asia-east2 |
Hong Kong |
asia-northeast1 |
Tokio |
asia-northeast2 |
Osaka |
asia-northeast3 |
Seúl |
asia-south1 |
Bombay |
asia-south2 |
Deli |
asia-southeast1 |
Singapur |
asia-southeast2 |
Yakarta |
australia-southeast1 |
Sídney |
australia-southeast2 |
Melbourne |
europe-central2 |
Varsovia |
europe-north1 |
Finlandia |
europe-southwest1 |
Madrid |
europe-west1 |
Bélgica |
europe-west2 |
Londres |
europe-west3 |
Fráncfort |
europe-west4 |
Países Bajos |
europe-west6 |
Zúrich |
europe-west8 |
Milán |
europe-west9 |
París |
europe-west10 |
Berlín |
europe-west12 |
Turín |
me-central1 |
Doha |
me-central2 |
Dammam |
me-west1 |
Tel Aviv |
northamerica-northeast1 |
Montreal |
northamerica-northeast2 |
Toronto |
southamerica-east1 |
São Paulo |
southamerica-west1 |
Santiago |
us-central1 |
Iowa |
us-east1 |
Carolina del Sur |
us-east4 |
Norte de Virginia |
us-east5 |
Columbus |
us-south1 |
Dallas |
us-west1 |
Oregón |
us-west2 |
Los Ángeles |
us-west3 |
Salt Lake City |
us-west4 |
Las Vegas |
También puedes consultar la lista de ubicaciones admitidas ejecutando el siguiente comando:
gcloud privateca locations list
Concede el permiso
roles/privateca.caManager
de IAM a las personas que creen un grupo de AC y una AC. Ten en cuenta que, en el caso de MEMBER, el formato correcto esuser:userid@example.com
. Si esa persona es el usuario actual, puedes obtener su ID con el comando de shell$(gcloud auth list --filter=status:ACTIVE --format="value(account)")
.gcloud projects add-iam-policy-binding PROJECT_ID \ --member=MEMBER \ --role=roles/privateca.caManager
Asigna el rol
role/privateca.admin
al servicio de CA a las personas que necesiten modificar las políticas de gestión de identidades y accesos, dondeMEMBER
es una persona que necesita este acceso, en concreto, cualquier persona que realice los pasos que se indican a continuación para asignar los rolesprivateca.auditor
yprivateca.certificateManager
:gcloud projects add-iam-policy-binding PROJECT_ID \ --member=MEMBER \ --role=roles/privateca.admin
Crea el grupo de servicios de la CA raíz.
gcloud privateca pools create ROOT_CA_POOL_NAME \ --location ROOT_CA_POOL_LOCATION \ --tier enterprise
Crea una CA raíz.
gcloud privateca roots create ROOT_CA_NAME --pool ROOT_CA_POOL_NAME \ --subject "CN=ROOT_CA_NAME, O=ROOT_CA_ORGANIZATION" \ --key-algorithm="ec-p256-sha256" \ --max-chain-length=1 \ --location ROOT_CA_POOL_LOCATION
Para esta configuración de demostración, utilice los siguientes valores para las variables:
- ROOT_CA_POOL_NAME=td_sec_pool
- ROOT_CA_NAME=pkcs2-ca
- ROOT_CA_POOL_LOCATION=us-east1
- ROOT_CA_ORGANIZATION="TestCorpLLC"
Crea el grupo subordinado y la AC subordinada. Asegúrate de que el modo de emisión basado en la configuración predeterminado siga permitido.
gcloud privateca pools create SUBORDINATE_CA_POOL_NAME \ --location SUBORDINATE_CA_POOL_LOCATION \ --tier devops
gcloud privateca subordinates create SUBORDINATE_CA_NAME \ --pool SUBORDINATE_CA_POOL_NAME \ --location SUBORDINATE_CA_POOL_LOCATION \ --issuer-pool ROOT_CA_POOL_NAME \ --issuer-location ROOT_CA_POOL_LOCATION \ --subject "CN=SUBORDINATE_CA_NAME, O=SUBORDINATE_CA_ORGANIZATION" \ --key-algorithm "ec-p256-sha256" \ --use-preset-profile subordinate_mtls_pathlen_0
Para esta configuración de demostración, utilice los siguientes valores para las variables:
- SUBORDINATE_CA_POOL_NAME="td-ca-pool"
- SUBORDINATE_CA_POOL_LOCATION=us-east1
- SUBORDINATE_CA_NAME="td-ca"
- SUBORDINATE_CA_ORGANIZATION="TestCorpLLC"
- ROOT_CA_POOL_NAME=td_sec_pool
- ROOT_CA_POOL_LOCATION=us-east1
Asigna el rol
privateca.auditor
de gestión de identidades y accesos al grupo de AC raíz para permitir el acceso desde la cuenta de servicio de GKE:gcloud privateca pools add-iam-policy-binding ROOT_CA_POOL_NAME \ --location ROOT_CA_POOL_LOCATION \ --role roles/privateca.auditor \ --member="serviceAccount:service-PROJNUM@container-engine-robot.iam.gserviceaccount.com"
Concede el rol de gestión de identidades y accesos
privateca.certificateManager
al grupo de CAs subordinadas para permitir el acceso desde la cuenta de servicio de GKE:gcloud privateca pools add-iam-policy-binding SUBORDINATE_CA_POOL_NAME \ --location SUBORDINATE_CA_POOL_LOCATION \ --role roles/privateca.certificateManager \ --member="serviceAccount:service-PROJNUM@container-engine-robot.iam.gserviceaccount.com"
Guarda la siguiente configuración
WorkloadCertificateConfig
YAML para indicar a tu clúster cómo emitir certificados de malla:apiVersion: security.cloud.google.com/v1 kind: WorkloadCertificateConfig metadata: name: default spec: # Required. The CA service that issues your certificates. certificateAuthorityConfig: certificateAuthorityServiceConfig: endpointURI: ISSUING_CA_POOL_URI # Required. The key algorithm to use. Choice of RSA or ECDSA. # # To maximize compatibility with various TLS stacks, your workloads # should use keys of the same family as your root and subordinate CAs. # # To use RSA, specify configuration such as: # keyAlgorithm: # rsa: # modulusSize: 4096 # # Currently, the only supported ECDSA curves are "P256" and "P384", and the only # supported RSA modulus sizes are 2048, 3072 and 4096. keyAlgorithm: rsa: modulusSize: 4096 # Optional. Validity duration of issued certificates, in seconds. # # Defaults to 86400 (1 day) if not specified. validityDurationSeconds: 86400 # Optional. Try to start rotating the certificate once this # percentage of validityDurationSeconds is remaining. # # Defaults to 50 if not specified. rotationWindowPercentage: 50
Haz los cambios siguientes:
- El ID del proyecto en el que se ejecuta el clúster:
PROJECT_ID
- El URI completo de la AC que emite los certificados de tu malla (ISSUING_CA_POOL_URI).
Puede ser tu AC subordinada (opción recomendada) o tu AC raíz. El formato es el siguiente:
//privateca.googleapis.com/projects/PROJECT_ID/locations/SUBORDINATE_CA_POOL_LOCATION/caPools/SUBORDINATE_CA_POOL_NAME
- El ID del proyecto en el que se ejecuta el clúster:
Guarda la siguiente configuración
TrustConfig
YAML para indicar a tu clúster cómo confiar en los certificados emitidos:apiVersion: security.cloud.google.com/v1 kind: TrustConfig metadata: name: default spec: # You must include a trustStores entry for the trust domain that # your cluster is enrolled in. trustStores: - trustDomain: PROJECT_ID.svc.id.goog # Trust identities in this trustDomain if they appear in a certificate # that chains up to this root CA. trustAnchors: - certificateAuthorityServiceURI: ROOT_CA_POOL_URI
Haz los cambios siguientes:
- El ID del proyecto en el que se ejecuta el clúster:
PROJECT_ID
- El URI completo del grupo de AC raíz (ROOT_CA_POOL_URI).
El formato es el siguiente:
//privateca.googleapis.com/projects/PROJECT_ID/locations/ROOT_CA_POOL_LOCATION/caPools/ROOT_CA_POOL_NAME
- El ID del proyecto en el que se ejecuta el clúster:
Aplica las configuraciones a tu clúster:
kubectl apply -f WorkloadCertificateConfig.yaml kubectl apply -f TrustConfig.yaml
Crear un servicio gRPC sin proxy con NEGs
Para la seguridad de PSM, necesitas un servidor gRPC sin proxy que pueda usar xDS para obtener la configuración de seguridad de Cloud Service Mesh. Este paso es similar a Configurar servicios de GKE con NEGs en la guía de configuración del balanceo de carga de PSM, pero se usa el servidor helloworld
habilitado para xDS en el ejemplo de xDS del repositorio grpc-java
en lugar de la imagen java-example-hostname
.
Compila y ejecuta este servidor en un contenedor creado a partir de una imagen de openjdk:8-jdk
.
También puedes usar la función de NEG con nombre, que te permite especificar un nombre para el NEG. De esta forma, se simplifican los pasos posteriores, ya que tu despliegue conoce el nombre del NEG sin tener que buscarlo.
A continuación, se muestra un ejemplo completo de la especificación de Kubernetes del servidor gRPC. Ten en cuenta lo siguiente:
- La especificación crea una cuenta de servicio de Kubernetes
example-grpc-server
que utiliza el pod del servidor gRPC. - La especificación usa el campo
name
en la anotacióncloud.google.com/neg
del servicio para especificar el nombre del NEGexample-grpc-server
. - La variable
${PROJNUM}
representa el número de proyecto de tu proyecto. - La especificación usa la sección
initContainers
para ejecutar un generador de bootstrap que rellene el archivo de bootstrap que necesita la biblioteca gRPC sin proxy. Este archivo de arranque se encuentra en/tmp/grpc-xds/td-grpc-bootstrap.json
en el contenedor del servidor gRPC llamadoexample-grpc-server
.
Añade la siguiente anotación a tu especificación de Pod:
annotations: security.cloud.google.com/use-workload-certificates: ""
Puedes ver la colocación correcta en las especificaciones completas que se indican a continuación.
Al crearse, cada Pod obtiene un volumen en /var/run/secrets/workload-spiffe-credentials
.
Este volumen contiene lo siguiente:
private_key.pem
es una clave privada generada automáticamente.certificates.pem
es un paquete de certificados con formato PEM que se puede presentar a otro pod como cadena de certificados de cliente o usar como cadena de certificados de servidor.ca_certificates.pem
es un paquete de certificados con formato PEM que se usa como ancla de confianza al validar la cadena de certificados de cliente presentada por otro pod o la cadena de certificados de servidor recibida al conectarse a otro pod.
Ten en cuenta que ca_certificates.pem
contiene certificados del dominio de confianza local de las cargas de trabajo, que es el grupo de cargas de trabajo del clúster.
El certificado de hoja de certificates.pem
contiene la siguiente
afirmación de identidad SPIFFE en texto sin formato:
spiffe://WORKLOAD_POOL/ns/NAMESPACE/sa/KUBERNETES_SERVICE_ACCOUNT
En esta aserción:
- WORKLOAD_POOL es el nombre del grupo de cargas de trabajo del clúster.
- NAMESPACE es el espacio de nombres de tu cuenta de servicio de Kubernetes.
- KUBERNETES_SERVICE_ACCOUNT es el nombre de tu cuenta de servicio de Kubernetes.
Las siguientes instrucciones para tu idioma crean la especificación que se usará en este ejemplo.
Java
Ejecuta el siguiente comando para asegurarte de que el número de proyecto se ha definido correctamente:
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
Crea la especificación:
cat << EOF > example-grpc-server.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-server namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: v1 kind: Service metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server annotations: cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}' spec: ports: - name: helloworld port: 8080 protocol: TCP targetPort: 50051 selector: k8s-app: example-grpc-server type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-server strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-server spec: containers: - image: openjdk:8-jdk imagePullPolicy: IfNotPresent name: example-grpc-server command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" ports: - protocol: TCP containerPort: 50051 resources: limits: cpu: 800m memory: 512Mi requests: cpu: 100m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" - --node-metadata=app=helloworld resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-server volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
C++
Ejecuta el siguiente comando para asegurarte de que el número de proyecto se ha definido correctamente:
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
Crea la especificación:
cat << EOF > example-grpc-server.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-server namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: v1 kind: Service metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server annotations: cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}' spec: ports: - name: helloworld port: 8080 protocol: TCP targetPort: 50051 selector: k8s-app: example-grpc-server type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-server strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-server spec: containers: - image: phusion/baseimage:18.04-1.0.0 imagePullPolicy: IfNotPresent name: example-grpc-server command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" ports: - protocol: TCP containerPort: 50051 resources: limits: cpu: 8 memory: 8Gi requests: cpu: 300m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" - --node-metadata=app=helloworld resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-server volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
Python
Ejecuta el siguiente comando para asegurarte de que el número de proyecto se ha definido correctamente:
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
Crea la especificación:
cat << EOF > example-grpc-server.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-server namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: v1 kind: Service metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server annotations: cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}' spec: ports: - name: helloworld port: 8080 protocol: TCP targetPort: 50051 selector: k8s-app: example-grpc-server type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-server strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-server spec: containers: - image: phusion/baseimage:18.04-1.0.0 imagePullPolicy: IfNotPresent name: example-grpc-server command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" ports: - protocol: TCP containerPort: 50051 resources: limits: cpu: 8 memory: 8Gi requests: cpu: 300m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" - --node-metadata=app=helloworld resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-server volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
Go
Ejecuta el siguiente comando para asegurarte de que el número de proyecto se ha definido correctamente:
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
Crea la especificación:
cat << EOF > example-grpc-server.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-server namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: v1 kind: Service metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server annotations: cloud.google.com/neg: '{"exposed_ports":{"8080":{"name": "example-grpc-server"}}}' spec: ports: - name: helloworld port: 8080 protocol: TCP targetPort: 50051 selector: k8s-app: example-grpc-server type: ClusterIP --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-server namespace: default labels: k8s-app: example-grpc-server spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-server strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-server spec: containers: - image: golang:1.16-alpine imagePullPolicy: IfNotPresent name: example-grpc-server command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" ports: - protocol: TCP containerPort: 50051 resources: limits: cpu: 8 memory: 8Gi requests: cpu: 300m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" - --node-metadata=app=helloworld resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-server volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
Completa el proceso de la siguiente manera.
Aplica la especificación:
kubectl apply -f example-grpc-server.yaml
Asigna los roles necesarios a la cuenta de servicio:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-server]" \ ${PROJNUM}-compute@developer.gserviceaccount.com gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-server]" \ --role roles/trafficdirector.client
Ejecuta estos comandos para comprobar que el servicio y el pod se han creado correctamente:
kubectl get deploy/example-grpc-server kubectl get svc/example-grpc-server
Verifica que el nombre del NEG sea correcto:
gcloud compute network-endpoint-groups list \ --filter "name=example-grpc-server" --format "value(name)"
El comando debe devolver el nombre del NEG
example-grpc-server
.
Configurar Cloud Service Mesh con componentes de Google Cloud balanceo de carga
Los pasos de esta sección son similares a los de Configurar Cloud Service Mesh con componentes de balanceo de carga, pero hay algunos cambios, como se describe en las siguientes secciones.
Crear la comprobación del estado, la regla de cortafuegos y el servicio de backend
Cuando el servidor gRPC está configurado para usar mTLS, las comprobaciones de estado de gRPC no funcionan porque el cliente de comprobación de estado no puede presentar un certificado de cliente válido a los servidores. Puedes hacerlo de dos formas:
En el primer enfoque, el servidor crea un puerto de servicio adicional que se designa como puerto de comprobación del estado. Se adjunta a un servicio de comprobación del estado especial, como texto sin formato o TLS a ese puerto.
El servidor de ejemplo de xDS helloworld
usa PORT_NUMBER
+ 1 como puerto de comprobación del estado de texto sin formato. En el ejemplo se usa el puerto 50052 para la comprobación del estado porque 50051 es el puerto del servidor de aplicaciones gRPC.
En el segundo enfoque, se configura la comprobación del estado para que solo compruebe la conectividad TCP al puerto de servicio de la aplicación. Esta opción solo comprueba la conectividad y también genera tráfico innecesario al servidor cuando no se completan las negociaciones TLS. Por este motivo, te recomendamos que uses el primer método.
Crea la comprobación del estado. Ten en cuenta que la comprobación del estado no se inicia hasta que crees e inicies el servidor.
Si vas a crear un puerto de servicio designado para las comprobaciones del estado (que es el método que recomendamos), usa este comando:
gcloud compute health-checks create grpc grpc-gke-helloworld-hc \ --enable-logging --port 50052
Si vas a crear una comprobación del estado TCP, lo cual no te recomendamos, usa este comando:
gcloud compute health-checks create tcp grpc-gke-helloworld-hc \ --use-serving-port
Crea el cortafuegos. Asegúrate de que el valor de
--target-tags
coincida con el valor que has proporcionado para--tags
en la sección Crear o actualizar un clúster de GKE.gcloud compute firewall-rules create grpc-gke-allow-health-checks \ --network default --action allow --direction INGRESS \ --source-ranges 35.191.0.0/16,130.211.0.0/22 \ --target-tags allow-health-checks \ --rules tcp:50051-50052
Crea el servicio de backend:
gcloud compute backend-services create grpc-gke-helloworld-service \ --global \ --load-balancing-scheme=INTERNAL_SELF_MANAGED \ --protocol=GRPC \ --health-checks grpc-gke-helloworld-hc
Asocia el NEG al servicio de backend:
gcloud compute backend-services add-backend grpc-gke-helloworld-service \ --global \ --network-endpoint-group example-grpc-server \ --network-endpoint-group-zone ${ZONE} \ --balancing-mode RATE \ --max-rate-per-endpoint 5
Crea los recursos Mesh
y GRPCRoute
.
Es similar a la forma en que se configuran los recursos Mesh
y GRPCRoute
en Configurar servicios gRPC sin proxy.
Crea la especificación
Mesh
y guárdala en un archivo llamadomesh.yaml
.name: grpc-mesh
Importa el recurso
Mesh
de la especificación.gcloud network-services meshes import grpc-mesh \ --source=mesh.yaml \ --location=global
Crea la especificación
GRPCRoute
y guárdala en un archivo llamadogrpc_route.yaml
.name: helloworld-grpc-route hostnames: - helloworld-gke:8000 meshes: - projects/PROJECT_NUMBER/locations/global/meshes/grpc-mesh rules: - action: destinations: - serviceName: projects/PROJECT_NUMBER/locations/global/backendServices/grpc-gke-helloworld-service
Importa el recurso
GRPCRoute
de la especificacióngrpc_route.yaml
.gcloud network-services grpc-routes import helloworld-grpc-route \ --source=grpc_route.yaml \ --location=global
Configurar Cloud Service Mesh con seguridad de gRPC sin proxy
En este ejemplo se muestra cómo configurar mTLS en el cliente y en el servidor.
Formato de las referencias de la política
Ten en cuenta el siguiente formato obligatorio para hacer referencia a las políticas de TLS de servidor y de TLS de cliente:
projects/PROJECT_ID/locations/global/[serverTlsPolicies|clientTlsPolicies]/[server-tls-policy|client-mtls-policy]
Por ejemplo:
projects/PROJECT_ID/locations/global/serverTlsPolicies/server-tls-policy
projects/PROJECT_ID/locations/global/clientTlsPolicies/client-mtls-policy
Configurar mTLS en el lado del servidor
Primero, crea una política de TLS de servidor. La política pide al lado del servidor de gRPC que use la configuración del complemento certificateProvicerInstance
identificada por el nombre google_cloud_private_spiffe
para el certificado de identidad, que forma parte de serverCertificate
. La sección mtlsPolicy
indica la seguridad de mTLS y usa el mismo google_cloud_private_spiffe
que la configuración del complemento para clientValidationCa
, que es la especificación del certificado raíz (de validación).
A continuación, crea una política de endpoint. Esto especifica que un backend, por ejemplo, un servidor gRPC que usa el puerto 50051
con ninguna o cualquier etiqueta de metadatos, recibe la política de TLS de servidor adjunta llamada server-mtls-policy
. Para especificar etiquetas de metadatos, usa MATCH_ALL
o un valor admitido. Las etiquetas de metadatos admitidas se pueden encontrar en el campo endpointMatcher.metadataLabelMatcher.metadataLabelMatchCriteria
del documento NetworkServicesEndpointPolicy. Crea la política de endpoint con un archivo temporal
ep-mtls-psms.yaml
que contenga los valores del recurso de política de endpoint
con la política que ya has definido.
Crea un archivo temporal
server-mtls-policy.yaml
en el directorio actual con los valores del recurso de política TLS del servidor:name: "projects/PROJECT_ID/locations/global/serverTlsPolicies/server-mtls-policy" serverCertificate: certificateProviderInstance: pluginInstance: google_cloud_private_spiffe mtlsPolicy: clientValidationCa: - certificateProviderInstance: pluginInstance: google_cloud_private_spiffe
Crea un recurso de política de TLS de servidor llamado
server-mtls-policy
importando el archivo temporalserver-mtls-policy.yaml
:gcloud network-security server-tls-policies import server-mtls-policy \ --source=server-mtls-policy.yaml --location=global
Crea la política de endpoint creando el archivo temporal
ep-mtls-psms.yaml
:name: "ep-mtls-psms" type: "GRPC_SERVER" serverTlsPolicy: "projects/PROJECT_ID/locations/global/serverTlsPolicies/server-mtls-policy" trafficPortSelector: ports: - "50051" endpointMatcher: metadataLabelMatcher: metadataLabelMatchCriteria: "MATCH_ALL" metadataLabels: - labelName: app labelValue: helloworld
Crea el recurso de política de endpoint importando el archivo
ep-mtls-psms.yaml
:gcloud beta network-services endpoint-policies import ep-mtls-psms \ --source=ep-mtls-psms.yaml --location=global
Configurar mTLS en el lado del cliente
La política de seguridad del lado del cliente se adjunta al servicio de backend. Cuando un cliente accede a un backend (el servidor gRPC) a través del servicio de backend, la política de seguridad del lado del cliente adjunta se envía al cliente.
Crea el contenido del recurso de la política de TLS de cliente en un archivo temporal llamado
client-mtls-policy.yaml
en el directorio actual:name: "client-mtls-policy" clientCertificate: certificateProviderInstance: pluginInstance: google_cloud_private_spiffe serverValidationCa: - certificateProviderInstance: pluginInstance: google_cloud_private_spiffe
Crea el recurso de política de TLS de cliente llamado
client-mtls-policy
importando el archivo temporalclient-mtls-policy.yaml
:gcloud network-security client-tls-policies import client-mtls-policy \ --source=client-mtls-policy.yaml --location=global
Crea un fragmento en un archivo temporal para hacer referencia a esta política y añade detalles sobre
subjectAltNames
en el mensajeSecuritySettings
, como en el ejemplo siguiente. Sustituye${PROJECT_ID}
por el valor del ID de tu proyecto, que es el valor de la variable de entorno${PROJECT_ID}
que se ha descrito anteriormente. Ten en cuenta queexample-grpc-server
ensubjectAltNames
es el nombre de la cuenta de servicio de Kubernetes que se usa para el pod del servidor gRPC en la especificación de la implementación.if [ -z "$PROJECT_ID" ] ; then echo Please make sure PROJECT_ID is set. ; fi cat << EOF > client-security-settings.yaml securitySettings: clientTlsPolicy: projects/${PROJECT_ID}/locations/global/clientTlsPolicies/client-mtls-policy subjectAltNames: - "spiffe://${PROJECT_ID}.svc.id.goog/ns/default/sa/example-grpc-server" EOF
Añade el mensaje
securitySettings
al servicio backend que ya has creado. Con estos pasos se exporta el contenido del servicio de backend actual, se añade el mensaje del clientesecuritySetting
y se vuelve a importar el nuevo contenido para actualizar el servicio de backend.gcloud compute backend-services export grpc-gke-helloworld-service --global \ --destination=/tmp/grpc-gke-helloworld-service.yaml cat /tmp/grpc-gke-helloworld-service.yaml client-security-settings.yaml \ >/tmp/grpc-gke-helloworld-service1.yaml gcloud compute backend-services import grpc-gke-helloworld-service --global \ --source=/tmp/grpc-gke-helloworld-service1.yaml -q
Verificar la configuración
La configuración de Cloud Service Mesh ya está completa, incluida la seguridad del lado del servidor y del cliente. A continuación, prepara y ejecuta las cargas de trabajo del servidor y del cliente. Con esto se completa el ejemplo.
Crear un cliente gRPC sin proxy
Este paso es similar al anterior, Crear un servicio gRPC sin proxy.
Utilizas el cliente helloworld
habilitado para xDS del directorio de ejemplo de xDS
en el repositorio grpc-java
. Compila y ejecuta el cliente en un contenedor creado a partir de una imagen de openjdk:8-jdk
. La especificación de Kubernetes del cliente de gRPC hace lo siguiente.
- Crea una cuenta de servicio de Kubernetes
example-grpc-client
que usa el pod del cliente gRPC. ${PROJNUM}
representa el número de proyecto de tu proyecto y debe sustituirse por el número real.
Añade la siguiente anotación a tu especificación de Pod:
annotations: security.cloud.google.com/use-workload-certificates: ""
Al crearse, cada Pod obtiene un volumen en /var/run/secrets/workload-spiffe-credentials
.
Este volumen contiene lo siguiente:
private_key.pem
es una clave privada generada automáticamente.certificates.pem
es un paquete de certificados con formato PEM que se puede presentar a otro pod como cadena de certificados de cliente o usar como cadena de certificados de servidor.ca_certificates.pem
es un paquete de certificados con formato PEM que se usa como ancla de confianza al validar la cadena de certificados de cliente presentada por otro pod o la cadena de certificados de servidor recibida al conectarse a otro pod.
Ten en cuenta que ca_certificates.pem
contiene los certificados raíz del dominio de confianza local de las cargas de trabajo, que es el grupo de cargas de trabajo del clúster.
El certificado de hoja de certificates.pem
contiene la siguiente
afirmación de identidad SPIFFE en texto sin formato:
spiffe://WORKLOAD_POOL/ns/NAMESPACE/sa/KUBERNETES_SERVICE_ACCOUNT
En esta aserción:
- WORKLOAD_POOL es el nombre del grupo de cargas de trabajo del clúster.
- NAMESPACE es el nombre de tu cuenta de servicio de Kubernetes.
- KUBERNETES_SERVICE_ACCOUNT es el espacio de nombres de tu cuenta de servicio de Kubernetes.
Las siguientes instrucciones para tu idioma crean la especificación que se usará en este ejemplo.
Java
Ejecuta el siguiente comando para asegurarte de que el número de proyecto se ha definido correctamente:
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
Crea la siguiente especificación:
cat << EOF > example-grpc-client.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-client namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-client namespace: default labels: k8s-app: example-grpc-client spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-client strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-client spec: containers: - image: openjdk:8-jdk imagePullPolicy: IfNotPresent name: example-grpc-client command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" resources: limits: cpu: 800m memory: 512Mi requests: cpu: 100m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-client volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
C++
Ejecuta el siguiente comando para asegurarte de que el número de proyecto se ha definido correctamente:
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
Crea la siguiente especificación:
cat << EOF > example-grpc-client.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-client namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-client namespace: default labels: k8s-app: example-grpc-client spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-client strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-client spec: containers: - image: phusion/baseimage:18.04-1.0.0 imagePullPolicy: IfNotPresent name: example-grpc-client command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" resources: limits: cpu: 8 memory: 8Gi requests: cpu: 300m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-client volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
Python
Ejecuta el siguiente comando para asegurarte de que el número de proyecto se ha definido correctamente:
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
Crea la siguiente especificación:
cat << EOF > example-grpc-client.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-client namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-client namespace: default labels: k8s-app: example-grpc-client spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-client strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-client spec: containers: - image: phusion/baseimage:18.04-1.0.0 imagePullPolicy: IfNotPresent name: example-grpc-client command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" resources: limits: cpu: 8 memory: 8Gi requests: cpu: 300m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-client volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
Go
Ejecuta el siguiente comando para asegurarte de que el número de proyecto se ha definido correctamente:
if [ -z "$PROJNUM" ] ; then export PROJNUM=$(gcloud projects describe $(gcloud info --format='value(config.project)') --format="value(projectNumber)") ; fi ; echo $PROJNUM
Crea la siguiente especificación:
cat << EOF > example-grpc-client.yaml apiVersion: v1 kind: ServiceAccount metadata: name: example-grpc-client namespace: default annotations: iam.gke.io/gcp-service-account: ${PROJNUM}-compute@developer.gserviceaccount.com --- apiVersion: apps/v1 kind: Deployment metadata: name: example-grpc-client namespace: default labels: k8s-app: example-grpc-client spec: replicas: 1 selector: matchLabels: k8s-app: example-grpc-client strategy: {} template: metadata: annotations: security.cloud.google.com/use-workload-certificates: "" labels: k8s-app: example-grpc-client spec: containers: - image: golang:1.16-alpine imagePullPolicy: IfNotPresent name: example-grpc-client command: - /bin/sleep - inf env: - name: GRPC_XDS_BOOTSTRAP value: "/tmp/grpc-xds/td-grpc-bootstrap.json" resources: limits: cpu: 8 memory: 8Gi requests: cpu: 300m memory: 512Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/grpc-xds/ initContainers: - name: grpc-td-init image: gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0 imagePullPolicy: Always args: - --config-mesh-experimental - "grpc-mesh" - --output - "/tmp/bootstrap/td-grpc-bootstrap.json" resources: limits: cpu: 100m memory: 100Mi requests: cpu: 10m memory: 100Mi volumeMounts: - name: grpc-td-conf mountPath: /tmp/bootstrap/ serviceAccountName: example-grpc-client volumes: - name: grpc-td-conf emptyDir: medium: Memory EOF
Completa el proceso de la siguiente manera.
Aplica la especificación:
kubectl apply -f example-grpc-client.yaml
Asigna los roles necesarios a la cuenta de servicio:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-client]" \ ${PROJNUM}-compute@developer.gserviceaccount.com gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member "serviceAccount:${PROJECT_ID}.svc.id.goog[default/example-grpc-client]" \ --role roles/trafficdirector.client
Comprueba que el pod del cliente se está ejecutando:
kubectl get pods
El comando devuelve un texto similar al siguiente:
NAMESPACE NAME READY STATUS RESTARTS AGE default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 104s [..skip..]
Ejecutar el servidor
Compila y ejecuta el servidor helloworld
habilitado para xDS en el pod de servidor que has creado anteriormente.
Java
Obtén el nombre del pod creado para el servicio
example-grpc-server
:kubectl get pods | grep example-grpc-server
Recibes comentarios como los siguientes:
default example-grpc-server-77548868d-l9hmf 1/1 Running 0 105s
Abre un shell en el pod del servidor:
kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
En el shell, comprueba que el archivo de arranque de
/tmp/grpc-xds/td-grpc-bootstrap.json
coincida con el esquema descrito en la sección Archivo de arranque.Descarga la versión 1.42.1 de gRPC Java y crea la aplicación de servidor
xds-hello-world
.curl -L https://github.com/grpc/grpc-java/archive/v1.42.1.tar.gz | tar -xz cd grpc-java-1.42.1/examples/example-xds ../gradlew --no-daemon installDist
Ejecuta el servidor con la marca
--xds-creds
para indicar la seguridad habilitada para xDS, usa50051
como puerto de escucha yxds-server
como nombre de identificación del servidor:./build/install/example-xds/bin/xds-hello-world-server --xds-creds 50051 xds-server
Una vez que el servidor obtiene la configuración necesaria de Cloud Service Mesh, verás el siguiente resultado:
Listening on port 50051 plain text health service listening on port 50052
C++
Obtén el nombre del pod creado para el servicio
example-grpc-server
:kubectl get pods | grep example-grpc-server
Recibes comentarios como los siguientes:
default example-grpc-server-77548868d-l9hmf 1/1 Running 0 105s
Abre un shell en el pod del servidor:
kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
En el shell, comprueba que el archivo de arranque de
/tmp/grpc-xds/td-grpc-bootstrap.json
coincida con el esquema descrito en la sección Archivo de arranque.Descarga gRPC C++ y crea la aplicación de servidor
xds-hello-world
.apt-get update -y && \ apt-get install -y \ build-essential \ clang \ python3 \ python3-dev curl -L https://github.com/grpc/grpc/archive/master.tar.gz | tar -xz cd grpc-master tools/bazel build examples/cpp/helloworld:xds_greeter_server
Ejecuta el servidor con
50051
como puerto de escucha yxds_greeter_server
como nombre de identificación del servidor:bazel-bin/examples/cpp/helloworld/xds_greeter_server --port=50051 --maintenance_port=50052 --secure
Para ejecutar el servidor sin credenciales, puedes especificar lo siguiente:
bazel-bin/examples/cpp/helloworld/xds_greeter_server --nosecure
Una vez que el servidor obtiene la configuración necesaria de Cloud Service Mesh, verás el siguiente resultado:
Listening on port 50051 plain text health service listening on port 50052
Python
Obtén el nombre del pod creado para el servicio
example-grpc-server
:kubectl get pods | grep example-grpc-server
Recibes comentarios como los siguientes:
default example-grpc-server-77548868d-l9hmf 1/1 Running 0 105s
Abre un shell en el pod del servidor:
kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
En el shell, comprueba que el archivo de arranque de
/tmp/grpc-xds/td-grpc-bootstrap.json
coincida con el esquema descrito en la sección Archivo de arranque.Descarga gRPC Python versión 1.41.0 y crea la aplicación de ejemplo.
apt-get update -y
apt-get install -y python3 python3-pip
curl -L https://github.com/grpc/grpc/archive/v1.41.x.tar.gz | tar -xz
cd grpc-1.41.x/examples/python/xds/
python3 -m virtualenv venv
source venv/bin/activate
python3 -m pip install -r requirements.txt
Ejecuta el servidor con la marca
--xds-creds
para indicar que la seguridad está habilitada para xDS. Usa50051
como puerto de escucha.python3 server.py 50051 --xds-creds
Una vez que el servidor obtiene la configuración necesaria de Cloud Service Mesh, verás el siguiente resultado:
2021-05-06 16:10:34,042: INFO Running with xDS Server credentials 2021-05-06 16:10:34,043: INFO Greeter server listening on port 50051 2021-05-06 16:10:34,046: INFO Maintenance server listening on port 50052
Go
Obtén el nombre del pod creado para el servicio
example-grpc-server
:kubectl get pods | grep example-grpc-server
Recibes comentarios como los siguientes:
default example-grpc-server-77548868d-l9hmf 1/1 Running 0 105s
Abre un shell en el pod del servidor:
kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/sh
En el shell, comprueba que el archivo de arranque de
/tmp/grpc-xds/td-grpc-bootstrap.json
coincida con el esquema descrito en la sección Archivo de arranque.Descarga la versión 1.41.0 de gRPC Go y ve al directorio que contiene la aplicación de servidor
xds-hello-world
.apk add curl curl -L https://github.com/grpc/grpc-go/archive/v1.42.0.tar.gz | tar -xz cd grpc-go-1.42.0/examples/features/xds/server
Compila y ejecuta el servidor con la marca
--xds_creds
para indicar la seguridad habilitada para xDS. Usa50051
como puerto de escucha:GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \ go run main.go \ -xds_creds \ -port 50051
Una vez que el servidor obtiene la configuración necesaria de Cloud Service Mesh, verás el siguiente resultado:
Using xDS credentials... Serving GreeterService on 0.0.0.0:50051 and HealthService on 0.0.0.0:50052
El proceso de comprobación del estado tarda entre 3 y 5 minutos en mostrar que tu servicio está en buen estado después de que se inicie el servidor.
Ejecuta el cliente y verifica la configuración
Compila y ejecuta el cliente helloworld
habilitado para xDS en el pod de cliente que has creado anteriormente.
Java
Obtén el nombre del pod del cliente:
kubectl get pods | grep example-grpc-client
Recibes comentarios como este:
default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 105s
Abre un shell en el pod del cliente:
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
En el shell de comandos, descarga la versión 1.42.1 de gRPC Java y crea la aplicación cliente
xds-hello-world
.curl -L https://github.com/grpc/grpc-java/archive/v1.42.1.tar.gz | tar -xz cd grpc-java-1.42.1/examples/example-xds ../gradlew --no-daemon installDist
Ejecuta el cliente con la marca
--xds-creds
para indicar la seguridad habilitada para xDS, el nombre del cliente y la cadena de conexión de destino:./build/install/example-xds/bin/xds-hello-world-client --xds-creds xds-client \ xds:///helloworld-gke:8000
Debería ver un resultado similar a este:
Greeting: Hello xds-client, from xds-server
C++
Obtén el nombre del pod del cliente:
kubectl get pods | grep example-grpc-client
Recibes comentarios como este:
default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 105s
Abre un shell en el pod del cliente:
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
Una vez que estés en la shell, descarga gRPC C++ y compila la aplicación cliente
xds-hello-world
.apt-get update -y && \ apt-get install -y \ build-essential \ clang \ python3 \ python3-dev
curl -L https://github.com/grpc/grpc/archive/master.tar.gz | tar -xz
cd grpc-master
tools/bazel build examples/cpp/helloworld:xds_greeter_client
Ejecuta el cliente con la marca
--xds-creds
para indicar la seguridad habilitada para xDS, el nombre del cliente y la cadena de conexión de destino:bazel-bin/examples/cpp/helloworld/xds_greeter_client --target=xds:///helloworld-gke:8000
Para ejecutar el cliente sin credenciales, usa lo siguiente:
bazel-bin/examples/cpp/helloworld/xds_greeter_client --target=xds:///helloworld-gke:8000 --nosecure
Debería ver un resultado similar a este:
Greeter received: Hello world
Python
Obtén el nombre del pod del cliente:
kubectl get pods | grep example-grpc-client
Recibes comentarios como este:
default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 105s
Abre un shell en el pod del cliente:
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
Una vez que estés en la shell, descarga la versión 1.41.0 de gRPC Python y compila la aplicación cliente de ejemplo.
apt-get update -y apt-get install -y python3 python3-pip python3 -m pip install virtualenv curl -L https://github.com/grpc/grpc/archive/v1.41.x.tar.gz | tar -xz cd grpc-1.41.x/examples/python/xds/ python3 -m virtualenv venv source venv/bin/activate python3 -m pip install -r requirements.txt
Ejecuta el cliente con la marca
--xds-creds
para indicar la seguridad habilitada para xDS, el nombre del cliente y la cadena de conexión de destino:python3 client.py xds:///helloworld-gke:8000 --xds-creds
Debería ver un resultado similar a este:
Greeter client received: Hello you from example-host!
Go
Obtén el nombre del pod del cliente:
kubectl get pods | grep example-grpc-client
Recibes comentarios como este:
default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 105s
Abre un shell en el pod del cliente:
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/sh
Una vez que estés en la shell, descarga gRPC Go versión 1.42.0 y ve al directorio que contiene la aplicación
xds-hello-world
cliente.apk add curl curl -L https://github.com/grpc/grpc-go/archive/v1.42.0.tar.gz | tar -xz cd grpc-go-1.42.0/examples/features/xds/client
Compila y ejecuta el cliente con la marca
--xds_creds
para indicar la seguridad habilitada para xDS, el nombre del cliente y la cadena de conexión de destino:GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \ go run main.go \ -xds_creds \ -name xds-client \ -target xds:///helloworld-gke:8000
Debería ver un resultado similar a este:
Greeting: Hello xds-client, from example-grpc-server-77548868d-l9hmf
Configurar el acceso a nivel de servicio con una política de autorización
Se requiere la compatibilidad con gRFC A41 para la compatibilidad con la política de autorización. Puedes encontrar las versiones de idioma necesarias en GitHub.
Sigue estas instrucciones para configurar el acceso a nivel de servicio con políticas de autorización. Antes de crear políticas de autorización, lee la advertencia de la sección Restringir el acceso mediante la autorización.
Para que sea más fácil verificar la configuración, crea un nombre de host adicional que el cliente pueda usar para hacer referencia al servicio helloworld-gke
.
Actualizar la especificación
GRPCRoute
almacenada anteriormente engrpc_route.yaml
name: helloworld-grpc-route hostnames: - helloworld-gke:8000 - helloworld-gke-noaccess:8000 meshes: - projects/PROJECT_NUMBER/locations/global/meshes/grpc-mesh rules: - action: destinations: - serviceName: projects/PROJECT_NUMBER/locations/global/backendServices/grpc-gke-helloworld-service
Vuelve a importar el recurso
GRPCRoute
desde la especificacióngrpc_route.yaml
.gcloud network-services grpc-routes import helloworld-grpc-route \ --source=grpc_route.yaml \ --location=global
En las siguientes instrucciones se crea una política de autorización que permite las solicitudes enviadas por la cuenta example-grpc-client
en la que el nombre de host es helloworld-gke:8000
y el puerto es 50051
.
gcloud
Crea una política de autorización creando un archivo llamado
helloworld-gke-authz-policy.yaml
.action: ALLOW name: helloworld-gke-authz-policy rules: - sources: - principals: - spiffe://PROJECT_ID.svc.id.goog/ns/default/sa/example-grpc-client destinations: - hosts: - helloworld-gke:8000 ports: - 50051
Importa la política.
gcloud network-security authorization-policies import \ helloworld-gke-authz-policy \ --source=helloworld-gke-authz-policy.yaml \ --location=global
Actualiza la política de endpoint para que haga referencia a la nueva política de autorización añadiendo lo siguiente al archivo
ep-mtls-psms.yaml
.authorizationPolicy: projects/${PROJECT_ID}/locations/global/authorizationPolicies/helloworld-gke-authz-policy
La política de endpoints ahora especifica que tanto mTLS como la política de autorización deben aplicarse a las solicitudes entrantes a los pods cuyos archivos de arranque de gRPC contengan la etiqueta
app:helloworld
.Importa la política:
gcloud network-services endpoint-policies import ep-mtls-psms \ --source=ep-mtls-psms.yaml --location=global
Validar la política de autorización
Sigue estas instrucciones para confirmar que la política de autorización funciona correctamente.
Java
Abre una shell en el pod de cliente que has usado anteriormente.
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
En el shell de comandos, ejecuta los siguientes comandos para validar la configuración.
cd grpc-java-1.42.1/examples/example-xds ./build/install/example-xds/bin/xds-hello-world-client --xds-creds xds-client \ xds:///helloworld-gke:8000
Debería ver un resultado similar a este:
Greeting: Hello xds-client, from xds-server
Vuelve a ejecutar el cliente con el nombre del servidor alternativo. Ten en cuenta que este es un caso de error. La solicitud no es válida porque la política de autorización solo permite el acceso al nombre de host
helloworld-gke:8000
../build/install/example-xds/bin/xds-hello-world-client --xds-creds xds-client \ xds:///helloworld-gke-noaccess:8000
Debería ver un resultado similar a este:
WARNING: RPC failed: Status{code=PERMISSION_DENIED}
Si no ves este resultado, es posible que la política de autorización aún no esté en uso. Espera unos minutos y vuelve a intentar todo el proceso de verificación.
Go
Abre una shell en el pod de cliente que has usado anteriormente.
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
En el shell de comandos, ejecuta los siguientes comandos para validar la configuración.
cd grpc-go-1.42.0/examples/features/xds/client GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \ go run main.go \ -xds_creds \ -name xds-client \ -target xds:///helloworld-gke:8000
Debería ver un resultado similar a este:
Greeting: Hello xds-client, from example-grpc-server-77548868d-l9hmf
Vuelve a ejecutar el cliente con el nombre del servidor alternativo. Ten en cuenta que este es un caso de error. La solicitud no es válida porque la política de autorización solo permite el acceso al nombre de host
helloworld-gke:8000
.GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \ go run main.go \ -xds_creds \ -name xds-client \ -target xds:///helloworld-gke-noaccess:8000
Debería ver un resultado similar a este:
could not greet: rpc error: code = PermissionDenied desc = Incoming RPC is not allowed: rpc error: code = PermissionDenied desc = incoming RPC did not match an allow policy exit status 1
Si no ves este resultado, es posible que la política de autorización aún no esté en uso. Espera unos minutos y vuelve a intentar todo el proceso de verificación.
Usar TLS en lugar de mTLS
Para usar TLS en este ejemplo, solo tienes que hacer un pequeño cambio.
En
ServerTlsPolicy
, sueltamtlsPolicy
:cat << EOF > server-tls-policy.yaml name: "server-tls-policy" serverCertificate: certificateProviderInstance: pluginInstance: google_cloud_private_spiffe EOF
Usa esta política en el
EndpointPolicy
:cat << EOF > ep-tls-psms.yaml name: "ep-mtls-psms" type: "GRPC_SERVER" serverTlsPolicy: "projects/${PROJECT_ID}/locations/global/serverTlsPolicies/server-tls-policy" trafficPortSelector: ports: - "50051" endpointMatcher: metadataLabelMatcher: metadataLabelMatchCriteria: "MATCH_ALL" metadataLabels: [] EOF
El
ClientTlsPolicy
de mTLS también funciona en el caso de TLS, pero se puede omitir la secciónclientCertificate
de la política, ya que no es necesaria para TLS:cat << EOF > client-tls-policy.yaml name: "client-tls-policy" serverValidationCa: - certificateProviderInstance: pluginInstance: google_cloud_private_spiffe EOF
Usar la seguridad de los servicios con el ejemplo de Wallet
En esta sección se ofrece una descripción general de alto nivel sobre cómo habilitar el ejemplo de Wallet con seguridad de servicio para Java, C++ y Go.
Java
Puedes encontrar el código fuente de ejemplo de Java en GitHub.
El código ya usa las credenciales XdsChannel
y XdsServer
cuando configuras la seguridad sin proxy.
En estas instrucciones se describe cómo configurar el ejemplo de Wallet con Go. El proceso es similar para Java. En las instrucciones se usa una imagen de Docker que ya existe y que se obtiene del Google Cloud repositorio de contenedores.
Para crear el ejemplo, siga estas instrucciones:
- Clona el repositorio y obtén los archivos del directorio gRPC examples.
- Edita el archivo
00-common-env.sh
. Comenta la línea que define el valor deWALLET_DOCKER_IMAGE
en la imagen de Docker de Go y descomenta la línea que define el valor deWALLET_DOCKER_IMAGE
en la imagen de Docker de Java. - Crea y configura instancias de Cloud Router siguiendo las instrucciones de Crear y configurar instancias de Cloud Router o usando la función
create_cloud_router_instances
de la secuencia de comandos10.apis.sh
. - Crea un clúster siguiendo las instrucciones del ejemplo
hello world
o con la funcióncreate_cluster
de la secuencia de comandos20-cluster.sh
. - Crea autoridades de certificación privadas siguiendo las instrucciones del Servicio de Autoridades de Certificación o con la secuencia de comandos
30-private-ca-setup.sh
. - Crea recursos de Kubernetes, incluidas cuentas de servicio, espacios de nombres, servicios de Kubernetes, NEGs y la implementación del lado del servidor para todos los servicios:
account
,stats
,stats_premium
,wallet_v1
ywallet_v2
. Para ello, usa la secuencia de comandos40-k8s-resources.sh
. - Para cada uno de los servicios que has creado, crea una comprobación del estado y un servicio de backend
con
create_health_check
ycreate_backend_service
en la secuencia de comandos50-td-components.sh
. - Crea los componentes de enrutamiento de Cloud Service Mesh mediante
create_routing_components
en la secuencia de comandos60-routing-components.sh
. - Crea los componentes de seguridad de la malla de servicios de Cloud para cada servicio de backend con
create_security_components
en la secuencia de comandos70-security-components.sh
. - Crea la implementación del cliente de Wallet con
create_client_deployment
en el script75-client-deployment.sh
. - Para verificar la configuración, inicia tu cliente tal como se describe en Verificar con clientes de grpc-wallet.
C++
Puedes encontrar el código fuente de ejemplo de C++ en GitHub. El código ya usa las credenciales XdsChannel
y XdsServer
cuando configuras la seguridad sin proxy.
En estas instrucciones se describe cómo configurar el ejemplo de Wallet con Go. El proceso es similar para C++. En las instrucciones se usa una imagen de Docker predefinida que se obtiene del Google Cloud repositorio de contenedores.
Para crear el ejemplo, siga estas instrucciones:
- Clona el repositorio y obtén los archivos del directorio gRPC examples.
- Edita el archivo
00-common-env.sh
. Comenta la línea que asigna el valor deWALLET_DOCKER_IMAGE
a la imagen de Docker de Go y descomenta la línea que asigna el valor deWALLET_DOCKER_IMAGE
a la imagen de Docker de C++. - Crea y configura instancias de Cloud Router siguiendo las instrucciones de Crear y configurar instancias de Cloud Router o usando la función
create_cloud_router_instances
de la secuencia de comandos10.apis.sh
. - Crea un clúster siguiendo las instrucciones del ejemplo
hello world
o con la funcióncreate_cluster
de la secuencia de comandos20-cluster.sh
. - Crea autoridades de certificación privadas siguiendo las instrucciones del Servicio de Autoridades de Certificación o con la secuencia de comandos
30-private-ca-setup.sh
. - Crea recursos de Kubernetes, incluidas cuentas de servicio, espacios de nombres, servicios de Kubernetes, NEGs y la implementación del lado del servidor para todos los servicios:
account
,stats
,stats_premium
,wallet_v1
ywallet_v2
. Para ello, usa la secuencia de comandos40-k8s-resources.sh
. - Para cada uno de los servicios que has creado, crea una comprobación del estado y un servicio de backend
con
create_health_check
ycreate_backend_service
en la secuencia de comandos50-td-components.sh
. - Crea los componentes de enrutamiento de Cloud Service Mesh mediante
create_routing_components
en la secuencia de comandos60-routing-components.sh
. - Crea los componentes de seguridad de la malla de servicios de Cloud para cada servicio de backend con
create_security_components
en la secuencia de comandos70-security-components.sh
. - Crea la implementación del cliente de Wallet con
create_client_deployment
en el script75-client-deployment.sh
. - Para verificar la configuración, inicia tu cliente tal como se describe en Verificar con clientes de grpc-wallet.
Go
Puedes encontrar código fuente de ejemplo de Go en GitHub. El código ya usa las credenciales XdsChannel
yXdsServer
cuando configuras la seguridad sin proxy.
En las instrucciones se usa una imagen Docker predefinida que se obtiene del Google Cloud repositorio de contenedores.
Para crear el ejemplo, siga estas instrucciones:
- Clona el repositorio y obtén los archivos del directorio gRPC examples.
- Edita el archivo
00-common-env.sh
para definir los valores correctos de las variables de entorno. - Crea y configura instancias de Cloud Router siguiendo las instrucciones de Crear y configurar instancias de Cloud Router o usando la función
create_cloud_router_instances
de la secuencia de comandos10.apis.sh
. - Crea un clúster siguiendo las instrucciones del ejemplo
hello world
o con la funcióncreate_cluster
de la secuencia de comandos20-cluster.sh
. - Crea autoridades de certificación privadas siguiendo las instrucciones del Servicio de Autoridades de Certificación o con la secuencia de comandos
30-private-ca-setup.sh
. - Crea recursos de Kubernetes, incluidas cuentas de servicio, espacios de nombres, servicios de Kubernetes, NEGs y la implementación del lado del servidor para todos los servicios:
account
,stats
,stats_premium
,wallet_v1
ywallet_v2
. Para ello, usa la secuencia de comandos40-k8s-resources.sh
. - Para cada uno de los servicios que has creado, crea una comprobación del estado y un servicio de backend
con
create_health_check
ycreate_backend_service
en la secuencia de comandos50-td-components.sh
. - Crea los componentes de enrutamiento de Cloud Service Mesh mediante
create_routing_components
en la secuencia de comandos60-routing-components.sh
. - Crea los componentes de seguridad de la malla de servicios de Cloud para cada servicio de backend con
create_security_components
en la secuencia de comandos70-security-components.sh
. - Crea la implementación del cliente de Wallet con
create_client_deployment
en el script75-client-deployment.sh
. - Para verificar la configuración, inicia tu cliente tal como se describe en Verificar con clientes de grpc-wallet.
Archivo de arranque
El proceso de configuración de esta guía usa un generador de bootstrap para crear el archivo de bootstrap necesario. En esta sección se proporciona información de referencia sobre el propio archivo de arranque.
El archivo de arranque contiene la información de configuración que necesita el código gRPC sin proxy, incluida la información de conexión del servidor xDS. El archivo de arranque contiene la configuración de seguridad que requiere la función de seguridad de gRPC sin proxy. El servidor gRPC requiere un campo adicional. Un archivo de arranque de ejemplo tiene este aspecto:
{ "xds_servers": [ { "server_uri": "trafficdirector.googleapis.com:443", "channel_creds": [ { "type": "google_default" } ], "server_features": [ "xds_v3" ] } ], "authorities": { "traffic-director-c2p.xds.googleapis.com": { "xds_servers": [ { "server_uri": "dns:///directpath-pa.googleapis.com", "channel_creds": [ { "type": "google_default" } ], "server_features": [ "xds_v3", "ignore_resource_deletion" ] } ], "client_listener_resource_name_template": "xdstp://traffic-director-c2p.xds.googleapis.com/envoy.config.listener.v3.Listener/%s" } }, "node": { "id": "projects/9876012345/networks/mesh:grpc-mesh/nodes/b59f49cc-d95a-4462-9126-112f794d5dd3", "cluster": "cluster", "metadata": { "INSTANCE_IP": "10.28.2.8", "TRAFFICDIRECTOR_DIRECTPATH_C2P_IPV6_CAPABLE": true, "TRAFFICDIRECTOR_GCP_PROJECT_NUMBER": "223606568246", "TRAFFICDIRECTOR_NETWORK_NAME": "default", "app": "helloworld" }, "locality": { "zone": "us-central1-c" } }, "certificate_providers": { "google_cloud_private_spiffe": { "plugin_name": "file_watcher", "config": { "certificate_file": "/var/run/secrets/workload-spiffe-credentials/certificates.pem", "private_key_file": "/var/run/secrets/workload-spiffe-credentials/private_key.pem", "ca_certificate_file": "/var/run/secrets/workload-spiffe-credentials/ca_certificates.pem", "refresh_interval": "600s" } } }, "server_listener_resource_name_template": "grpc/server?xds.resource.listening_address=%s" }
Actualizaciones del archivo de arranque del servicio de seguridad
Los siguientes campos reflejan las modificaciones relacionadas con la seguridad y el uso de xDS v3:
El campo id
de node
proporciona una identidad única al cliente de gRPC para Cloud Service Mesh. Debes proporcionar el Google Cloud número de proyecto y el nombre de la red
con el ID de nodo en este formato:
projects/{project number}/networks/{network name}/nodes/[UNIQUE_ID]
Por ejemplo, para el proyecto con el número 1234 y la red predeterminada, sería:
projects/1234/networks/default/nodes/client1
El campo INSTANCE_IP
es la dirección IP del pod o 0.0.0.0
para indicar
INADDR_ANY
. El servidor gRPC usa este campo para obtener el recurso Listener de Cloud Service Mesh para la seguridad del lado del servidor.
Campos de configuración de seguridad en el archivo de arranque
Clave JSON | Tipo | Valor | Notas |
---|---|---|---|
server_listener_resource_name_template |
Cadena | grpc/server?xds.resource.listening_address=%s |
Obligatorio para los servidores gRPC. gRPC usa este valor para componer el nombre del recurso para obtener el recurso `Listener` de Cloud Service Mesh para la seguridad del lado del servidor y otra configuración. gRPC usa este valor para formar la cadena del nombre del recurso. |
certificate_providers |
Estructura JSON | google_cloud_private_spiffe |
Obligatorio. El valor es una estructura JSON que representa un mapa de nombres a instancias de proveedor de certificados. Se usa una instancia de proveedor de certificados para obtener certificados de identidad y raíz. El archivo de arranque de ejemplo contiene un nombre: google_cloud_private_spiffe , con la estructura JSON de la instancia del proveedor de certificados como valor. Cada estructura JSON de instancia de proveedor de certificados tiene dos campos:
|
El contenido de la estructura JSON config
del complemento file_watcher
es el siguiente:
certificate_file
: cadena obligatoria. Este valor es la ubicación del certificado de identidad.private_key_file
: cadena obligatoria. El valor es la ubicación del archivo de clave privada, que debe coincidir con el certificado de identidad.ca_certificate_file
: cadena obligatoria. El valor es la ubicación del certificado raíz, también conocido como paquete de confianza.refresh_interval
: cadena opcional. El valor indica el intervalo de actualización, especificado mediante la representación de cadena de la asignación JSON de una duración. El valor predeterminado es "600s", una duración de 10 minutos.
Generador de Bootstrap
La imagen del contenedor del generador de bootstrap está disponible en
gcr.io/trafficdirector-prod/td-grpc-bootstrap:0.16.0
. Su código fuente está disponible en https://github.com/GoogleCloudPlatform/traffic-director-grpc-bootstrap
.
Estas son las opciones de línea de comandos que se usan con más frecuencia:
--output
: usa esta opción para especificar dónde se escribe el archivo de arranque de salida. Por ejemplo, el comando--output /tmp/bootstrap/td-grpc-bootstrap.json
genera el archivo de arranque en/tmp/bootstrap/td-grpc-bootstrap.json
en el sistema de archivos del pod.--config-mesh-experimental
: usa esta opción para especificar el nombre de la malla, que debe coincidir con el recursoMesh
.--node-metadata
: usa esta marca para rellenar los metadatos del nodo en el archivo de arranque. Esto es obligatorio cuando se usan matchers de etiquetas de metadatos enEndpointPolicy
, donde Cloud Service Mesh usa los datos de etiquetas proporcionados en la sección de metadatos de nodos del archivo de arranque. El argumento se proporciona con el formato clave=valor. Por ejemplo:--node-metadata version=prod --node-metadata type=grpc
La información anterior añade lo siguiente en la sección de metadatos de nodo del archivo de arranque:
{ "node": { ... "metadata": { "version": "prod", "type": "grpc", ... }, ... }, ... }
Eliminar el despliegue
También puedes ejecutar estos comandos para eliminar el despliegue que has creado con esta guía.
Para eliminar el clúster, ejecuta este comando:
gcloud container clusters delete CLUSTER_NAME --zone ZONE --quiet
Para eliminar los recursos que has creado, ejecuta estos comandos:
gcloud compute backend-services delete grpc-gke-helloworld-service --global --quiet gcloud compute network-endpoint-groups delete example-grpc-server --zone ZONE --quiet gcloud compute firewall-rules delete grpc-gke-allow-health-checks --quiet gcloud compute health-checks delete grpc-gke-helloworld-hc --quiet gcloud network-services endpoint-policies delete ep-mtls-psms \ --location=global --quiet gcloud network-security authorization-policies delete helloworld-gke-authz-policy \ --location=global --quiet gcloud network-security client-tls-policies delete client-mtls-policy \ --location=global --quiet gcloud network-security server-tls-policies delete server-tls-policy \ --location=global --quiet gcloud network-security server-tls-policies delete server-mtls-policy \ --location=global --quiet
Solución de problemas
Sigue estas instrucciones para resolver los problemas con tu implementación de seguridad.
Las cargas de trabajo no pueden obtener la configuración de Cloud Service Mesh
Si aparece un error similar a este:
PERMISSION_DENIED: Request had insufficient authentication scopes.
Asegúrate de lo siguiente:
- Has creado tu clúster de GKE con el argumento
--scopes=cloud-platform
argument. - Has asignado el
roles/trafficdirector.client
a tus cuentas de servicio de Kubernetes. - Has asignado el
roles/trafficdirector.client
a tu cuenta de servicio Google Cloud predeterminada (la cuenta ${GSA_EMAIL} de arriba). - Has habilitado el servicio (API)
trafficdirector.googleapis.com
.
Tu servidor gRPC no usa TLS/mTLS aunque la configuración de Cloud Service Mesh sea correcta
Asegúrate de especificar GRPC_SERVER
en la configuración de tus políticas de endpoint. Si has especificado SIDECAR_PROXY
, gRPC ignora la configuración.
No puedes crear el clúster de GKE con la versión solicitada
Es posible que el comando de creación del clúster de GKE falle y se muestre un error similar a este:
Node version "1.20.5-gke.2000" is unsupported.
Asegúrate de usar el argumento --release-channel rapid
en el comando de creación de clústeres. Debes usar el canal de lanzamiento rápido para obtener la versión correcta de esta actualización.
Aparece un error No usable endpoint
Si un cliente no puede comunicarse con el servidor debido a un error No usable endpoint
, es posible que el comprobador de estado haya marcado los back-ends del servidor como no disponibles.
Para comprobar el estado de los backends, ejecuta este comando gcloud
:
gcloud compute backend-services get-health grpc-gke-helloworld-service --global
Si el comando devuelve el estado del backend como incorrecto, puede deberse a uno de estos motivos:
- El cortafuegos no se ha creado o no contiene el intervalo de IPs de origen correcto.
- Las etiquetas de destino de tu firewall no coinciden con las del clúster que has creado.
Las cargas de trabajo no pueden comunicarse en la configuración de seguridad
Si tus cargas de trabajo no pueden comunicarse después de configurar la seguridad de tu malla de servicios sin proxy, sigue estas instrucciones para determinar la causa.
- Inhabilita la seguridad sin proxy y elimina los problemas en los casos prácticos de balanceo de carga de malla de servicio sin proxy. Para inhabilitar la seguridad en la malla, haz una de las siguientes acciones:
- Usar credenciales de texto sin formato en el lado del cliente y del servidor
- No configures la seguridad del servicio de backend ni la política de endpoint en la configuración de Cloud Service Mesh.
Sigue los pasos que se indican en el artículo Solucionar problemas de implementaciones de malla de servicios de Cloud sin proxy, ya que no hay ninguna configuración de seguridad en tu implementación.
Modifica tus cargas de trabajo para que usen credenciales xDS con texto sin formato o credenciales no seguras como credenciales alternativas. Mantén la configuración de Cloud Service Mesh con la seguridad inhabilitada, tal como se ha explicado anteriormente. En este caso, aunque gRPC permite que Cloud Service Mesh configure la seguridad, Cloud Service Mesh no envía información de seguridad, por lo que gRPC debería recurrir a las credenciales de texto sin formato (o no seguras), que deberían funcionar de forma similar al primer caso anterior. Si no funciona, haz lo siguiente:
- Aumenta el nivel de registro tanto en el cliente como en el servidor para que puedas ver los mensajes xDS intercambiados entre gRPC y Cloud Service Mesh.
- Asegúrate de que Cloud Service Mesh no tenga la seguridad habilitada en las respuestas de CDS y LDS que se envían a las cargas de trabajo.
- Asegúrate de que las cargas de trabajo no usen los modos TLS o mTLS en sus canales. Si ves algún mensaje de registro relacionado con negociaciones de TLS, comprueba el código fuente de tu aplicación y asegúrate de que no estés usando texto sin formato o inseguro como credenciales alternativas. Si el código fuente de la aplicación es correcto, puede que se trate de un error en la biblioteca gRPC.
Para verificar que la integración del servicio de CA con GKE funciona correctamente en tu clúster de GKE, sigue los pasos de resolución de problemas que se indican en esa guía del usuario. Asegúrate de que los certificados y las claves que proporciona esa función estén disponibles en el directorio especificado,
/var/run/secrets/workload-spiffe-credentials/
.Habilita TLS (en lugar de mTLS) en tu malla, tal como se ha descrito anteriormente, y reinicia las cargas de trabajo del cliente y del servidor.
- Aumenta el nivel de registro tanto en el cliente como en el servidor para poder ver los mensajes xDS intercambiados entre gRPC y Cloud Service Mesh.
- Asegúrate de que Cloud Service Mesh haya habilitado la seguridad en las respuestas de CDS y LDS que se envían a las cargas de trabajo.
El cliente falla con un CertificateException
y un mensaje Peer certificate SAN check failed
Esto indica que hay un problema con los valores de subjectAltNames
en el mensaje SecuritySettings
. Ten en cuenta que estos valores se basan en los servicios de Kubernetes que has creado para tu servicio backend. Por cada servicio de Kubernetes que hayas creado, hay un ID de SPIFFE asociado con este formato:
spiffe://${WORKLOAD_POOL}/ns/${K8S_NAMESPACE}/sa/${SERVICE_ACCOUNT}
Estos valores son los siguientes:
WORKLOAD_POOL
: el pool de carga de trabajo del clúster, que es${PROJECT_ID}.svc.id.goog
K8S_NAMESPACE
: el espacio de nombres de Kubernetes que has usado en el despliegue del servicio.SERVICE_ACCOUNT
: la cuenta de servicio de Kubernetes que has usado en la implementación del servicio
Por cada servicio de Kubernetes que hayas asociado a tu servicio de backend como grupo de endpoints de red, asegúrate de haber calculado correctamente el ID de SPIFFE y de haberlo añadido al campo subjectAltNames
del mensaje SecuritySettings
.
Las aplicaciones no pueden usar los certificados mTLS con tu biblioteca gRPC
Si tus aplicaciones no pueden usar los certificados mTLS con tu biblioteca gRPC, haz lo siguiente:
Verifica que la especificación del pod contenga la
security.cloud.google.com/use-workload-certificates
anotación que se describe en Crear un servicio gRPC sin proxy con NEGs.Verifica que se pueda acceder a los archivos que contienen la cadena de certificados junto con el certificado de hoja, la clave privada y los certificados de CA de confianza en las siguientes rutas desde el Pod:
- Cadena de certificados junto con el certificado de hoja: "/var/run/secrets/workload-spiffe-credentials/certificates.pem"
- Clave privada: "/var/run/secrets/workload-spiffe-credentials/private_key.pem"
- Paquete de AC: "/var/run/secrets/workload-spiffe-credentials/ca_certificates.pem"
Si los certificados del paso anterior no están disponibles, haz lo siguiente:
gcloud privateca subordinates describe SUBORDINATE_CA_POOL_NAME
--location=LOCATIONVerifica que el plano de control de GKE tenga el enlace de rol de IAM correcto, lo que le da acceso a Servicio de Autoridades de Certificación:
# Get the IAM policy for the CA gcloud privateca roots get-iam-policy ROOT_CA_POOL_NAME # Verify that there is an IAM binding granting access in the following format - members: - serviceAccount:service-projnumber@container-engine-robot.iam.gserviceaccount.com role: roles/privateca.certificateManager # Where projnumber is the project number (e.g. 2915810291) for the GKE cluster.
Comprueba que el certificado no haya caducado. Esta es la cadena de certificados y el certificado de hoja en
/var/run/secrets/workload-spiffe-credentials/certificates.pem
. Para comprobarlo, ejecuta este comando:cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
Para comprobar que tu aplicación admite el tipo de clave, ejecuta este comando:
cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Public Key Algorithm" -A 3
Verifica que tu aplicación Java gRPC tenga lo siguiente
keyAlgorithm
en el archivo YAMLWorkloadCertificateConfig
:
keyAlgorithm: rsa: modulusSize: 4096
Verifica que la CA usa la misma familia de claves que la clave del certificado.
El cliente, el servidor o el peer rechazan el certificado de una aplicación
- Verifica que la aplicación del otro extremo usa el mismo paquete de confianza para verificar el certificado.
- Comprueba que el certificado en uso no haya caducado (cadena de certificados junto con el certificado de hoja: "/var/run/secrets/workload-spiffe-credentials/certificates.pem").
Los pods permanecen en estado pendiente
Si los pods permanecen en estado pendiente durante el proceso de configuración, aumenta los recursos de CPU y memoria de los pods en la especificación de tu implementación.
No se puede crear un clúster con la marca --enable-mesh-certificates
Asegúrate de que estás usando la versión más reciente de la CLI de gcloud:
gcloud components update
Ten en cuenta que la marca --enable-mesh-certificates
solo funciona con gcloud beta
.
Los pods no se inician
Es posible que los pods que usan certificados de malla de GKE no se inicien si falla el aprovisionamiento de certificados. Esto puede ocurrir en situaciones como las siguientes:
- La configuración de
WorkloadCertificateConfig
oTrustConfig
no es correcta o falta. - No se aprueban las CSRs.
Para comprobar si el aprovisionamiento de certificados está fallando, consulta los eventos de Pod.
Comprueba el estado de tu Pod:
kubectl get pod -n POD_NAMESPACE POD_NAME
Haz los cambios siguientes:
POD_NAMESPACE
: el espacio de nombres de tu pod.POD_NAME
: el nombre de tu Pod.
Para consultar los eventos recientes de tu Pod, sigue estos pasos:
kubectl describe pod -n POD_NAMESPACE POD_NAME
Si el aprovisionamiento de certificados falla, verás un evento con
Type=Warning
,Reason=FailedMount
yFrom=kubelet
, así como un campoMessage
que empieza porMountVolume.SetUp failed for volume "gke-workload-certificates"
. El campoMessage
contiene información para solucionar problemas.Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedMount 13s (x7 over 46s) kubelet MountVolume.SetUp failed for volume "gke-workload-certificates" : rpc error: code = Internal desc = unable to mount volume: store.CreateVolume, err: unable to create volume "csi-4d540ed59ef937fbb41a9bf5380a5a534edb3eedf037fe64be36bab0abf45c9c": caPEM is nil (check active WorkloadCertificateConfig)
Consulta los siguientes pasos para solucionar problemas si tus pods no se inician debido a objetos mal configurados o a CSRs rechazadas.
WorkloadCertificateConfig
o TrustConfig
no están configurados correctamente
Asegúrate de que has creado los objetos WorkloadCertificateConfig
y TrustConfig
correctamente. Puedes diagnosticar errores de configuración en cualquiera de estos objetos con kubectl
.
Recupera el estado actual.
Para
WorkloadCertificateConfig
:kubectl get WorkloadCertificateConfig default -o yaml
Para
TrustConfig
:kubectl get TrustConfig default -o yaml
Inspecciona el resultado del estado. Un objeto válido tendrá una condición con
type: Ready
ystatus: "True"
.status: conditions: - lastTransitionTime: "2021-03-04T22:24:11Z" message: WorkloadCertificateConfig is ready observedGeneration: 1 reason: ConfigReady status: "True" type: Ready
En el caso de los objetos no válidos, se muestra
status: "False"
. Los camposreason
ymessage
contienen información adicional para solucionar problemas.
No se aprueban las CSRs
Si algo va mal durante el proceso de aprobación de la CSR, puede consultar los detalles del error en las condiciones type: Approved
y type: Issued
de la CSR.
Lista las CSRs pertinentes con
kubectl
:kubectl get csr \ --field-selector='spec.signerName=spiffe.gke.io/spiffe-leaf-signer'
Elige un CSR que sea
Approved
y noIssued
, o que no seaApproved
.Obtén los detalles de la CSR seleccionada con kubectl:
kubectl get csr CSR_NAME -o yaml
Sustituye
CSR_NAME
por el nombre que hayas elegido para la CSR.
Una CSR válida tiene una condición con type: Approved
y status: "True"
, y un certificado válido en el campo status.certificate
:
status:
certificate: <base64-encoded data>
conditions:
- lastTransitionTime: "2021-03-04T21:58:46Z"
lastUpdateTime: "2021-03-04T21:58:46Z"
message: Approved CSR because it is a valid SPIFFE SVID for the correct identity.
reason: AutoApproved
status: "True"
type: Approved
La información para solucionar problemas relacionados con CSRs no válidos aparece en los campos message
y reason
.
Faltan certificados en los pods
Obtén las especificaciones del pod:
kubectl get pod -n POD_NAMESPACE POD_NAME -o yaml
Haz los cambios siguientes:
POD_NAMESPACE
: el espacio de nombres de tu pod.POD_NAME
: el nombre de tu Pod.
Verifica que la especificación del pod contenga la
security.cloud.google.com/use-workload-certificates
anotación descrita en Configurar pods para recibir credenciales de mTLS.Verifica que el controlador de admisión de certificados de malla de GKE haya insertado correctamente un volumen de controlador CSI de tipo
workloadcertificates.security.cloud.google.com
en la especificación de tu pod:volumes: ... -csi: driver: workloadcertificates.security.cloud.google.com name: gke-workload-certificates ...
Comprueba si hay un volumen montado en cada uno de los contenedores:
containers: - name: ... ... volumeMounts: - mountPath: /var/run/secrets/workload-spiffe-credentials name: gke-workload-certificates readOnly: true ...
Verifica que los siguientes paquetes de certificados y la clave privada estén disponibles en las siguientes ubicaciones del pod:
- Paquete de cadena de certificados:
/var/run/secrets/workload-spiffe-credentials/certificates.pem
- Clave privada:
/var/run/secrets/workload-spiffe-credentials/private_key.pem
- Paquete de anclas de confianza de la AC:
/var/run/secrets/workload-spiffe-credentials/ca_certificates.pem
- Paquete de cadena de certificados:
Si los archivos no están disponibles, sigue estos pasos:
Recupera la instancia de CA Service (Preview) del clúster:
kubectl get workloadcertificateconfigs default -o jsonpath '{.spec.certificateAuthorityConfig.certificateAuthorityServiceConfig.endpointURI}'
Consulta el estado de la instancia del servicio de AC (vista previa):
gcloud privateca ISSUING_CA_TYPE describe ISSUING_CA_NAME \ --location ISSUING_CA_LOCATION
Haz los cambios siguientes:
ISSUING_CA_TYPE
: el tipo de CA emisora, que debe sersubordinates
oroots
.ISSUING_CA_NAME
: el nombre de la autoridad de certificación emisora.ISSUING_CA_LOCATION
: la región de la entidad certificadora emisora.
Obtén la política de gestión de identidades y accesos de la CA raíz:
gcloud privateca roots get-iam-policy ROOT_CA_NAME
Sustituye
ROOT_CA_NAME
por el nombre de tu AC raíz.En la política de gestión de identidades y accesos, comprueba que existe el
privateca.auditor
enlace de política:... - members: - serviceAccount:service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com role: roles/privateca.auditor ...
En este ejemplo,
PROJECT_NUMBER
es el número de proyecto de tu clúster.Obtén la política de gestión de identidades y accesos de la CA subordinada:
gcloud privateca subordinates get-iam-policy SUBORDINATE_CA_NAME
Sustituye
SUBORDINATE_CA_NAME
por el nombre de la AC subordinada.En la política de gestión de identidades y accesos, comprueba que existe el enlace de política
privateca.certificateManager
:... - members: - serviceAccount: service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com role: roles/privateca.certificateManager ...
En este ejemplo,
PROJECT_NUMBER
es el número de proyecto de tu clúster.
Las aplicaciones no pueden usar las credenciales de mTLS emitidas
Comprueba que el certificado no haya caducado:
cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
Comprueba que el tipo de clave que has usado sea compatible con tu aplicación.
cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Public Key Algorithm" -A 3
Comprueba que la AC emisora use la misma familia de claves que la clave del certificado.
Obtén el estado de la instancia del servicio de CA (vista previa):
gcloud privateca ISSUING_CA_TYPE describe ISSUING_CA_NAME \ --location ISSUING_CA_LOCATION
Haz los cambios siguientes:
ISSUING_CA_TYPE
: el tipo de CA emisora, que debe sersubordinates
oroots
.ISSUING_CA_NAME
: el nombre de la autoridad de certificación emisora.ISSUING_CA_LOCATION
: la región de la entidad certificadora emisora.
Comprueba que el
keySpec.algorithm
de la salida sea el mismo algoritmo de clave que has definido en el manifiesto YAMLWorkloadCertificateConfig
. La salida tiene este aspecto:config: ... subjectConfig: commonName: td-sub-ca subject: organization: TestOrgLLC subjectAltName: {} createTime: '2021-05-04T05:37:58.329293525Z' issuingOptions: includeCaCertUrl: true keySpec: algorithm: RSA_PKCS1_2048_SHA256 ...
Se rechazan los certificados
- Verifica que la aplicación del otro extremo usa el mismo paquete de confianza para verificar el certificado.
Comprueba que el certificado no haya caducado:
cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
Verifica que el código de cliente, si no usa la API de recarga de credenciales de gRPC Go, actualice periódicamente las credenciales del sistema de archivos.
Verifica que tus cargas de trabajo estén en el mismo dominio de confianza que tu CA. Los certificados de malla de GKE admiten la comunicación entre cargas de trabajo de un único dominio de confianza.
Limitaciones
La seguridad de los servicios de Cloud Service Mesh solo se admite en GKE. No puedes implementar la seguridad de los servicios con Compute Engine.
Cloud Service Mesh no admite situaciones en las que haya dos o más recursos de EndpointPolicy que coincidan por igual con un endpoint. Por ejemplo, dos políticas con las mismas etiquetas y puertos, o dos o más políticas con etiquetas diferentes que coincidan por igual con las etiquetas de un endpoint. Para obtener más información sobre cómo se asocian las políticas de endpoints con las etiquetas de un endpoint, consulta las APIs de EndpointPolicy.EndpointMatcher.MetadataLabelMatcher. En estas situaciones, Cloud Service Mesh no genera ninguna configuración de seguridad a partir de las políticas en conflicto.