Configura la seguridad del servicio con gRPC sin proxy
En esta guía, se muestra cómo configurar un servicio de seguridad para una malla de servicios de gRPC sin proxy.
Requisitos
Antes de configurar la seguridad del servicio para la malla de servicios sin proxy de gRPC, asegúrate de cumplir con los siguientes requisitos.
- Tu implementación cumple con los requisitos Prepárate para configurar las APIs de Service Enrutamiento con Envoy y las 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 necesarias con uno de los siguientes lenguajes:
- gRPC para Java
- gRPC para C++
- gRPC para Python
- gRPC para Go Puedes encontrar las versiones de lenguaje necesarias en GitHub.
- Tienes acceso al generador de arranque, versión 0.16.0. La imagen del generador de arranque se encuentra en el repositorio de contenedores de Google Cloud.
- Cumples con todos los requisitos para el balanceo de cargas de malla de servicios sin proxy de gRPC.
- Tienes permisos suficientes para crear o actualizar Cloud Service Mesh y Recursos de la malla de servicios de Google Cloud para usar la seguridad de PSM. Si deseas obtener información completa sobre los permisos necesarios, consulta Prepárate para configurar Cloud Service Mesh con servicios de gRPC sin proxy.
- Tienes los permisos necesarios para usar Certificate Authority Service, que se describen en Crea autoridades certificadas para emitir certificados.
Configura la administración de identidades y accesos
Debes tener los permisos necesarios para usar Google Kubernetes Engine. Como mínimo, debes tener las siguientes funciones:
- Función
roles/container.clusterAdmin
de GKE roles/compute.instanceAdmin
función de Compute Engine- La función
roles/iam.serviceAccountUser
A fin de crear los recursos necesarios para la configuración, debes tener la función compute.NetworkAdmin
. Esta función contiene todos los permisos necesarios para crear, actualizar, borrar, enumerar y usar (es decir, hacer referencia a esto en otros recursos) los recursos necesarios. Si eres propietario o editor de tu proyecto, automáticamente tienes esta función.
Ten en cuenta que networksecurity.googleapis.com.clientTlsPolicies.use
y
Las networksecurity.googleapis.com.serverTlsPolicies.use
no se aplican de manera forzosa cuando
hacer referencia a estos recursos
en el recurso del servicio de backend.
Si esto se aplica en el futuro y usas la función compute.NetworkAdmin
, no notarás ningún problema cuando se aplique esta verificación.
Si usas funciones personalizadas y esta verificación se aplica en el futuro, debes asegurarte de incluir el permiso .use
correspondiente. De lo contrario, en el futuro, es posible que tu función personalizada no tenga los permisos necesarios para hacer referencia a clientTlsPolicy
o serverTlsPolicy
desde el servicio de backend.
Prepárate para la configuración
La seguridad de la malla de servicios sin proxy (PSM) agrega seguridad a una malla de servicios configurada para el balanceo de cargas según la documentación de servicios de gRPC sin proxy. En una malla de servicios sin proxy, un cliente de gRPC usa el esquema xds:
en el URI para acceder al servicio, lo que habilita las funciones de balanceo de cargas de PSM y descubrimiento de extremos.
Actualiza los clientes y servidores de gRPC a la versión correcta
Compila o vuelve a compilar tus aplicaciones con la versión mínima de gRPC compatible con tu lenguaje.
Actualiza el archivo de arranque
Las aplicaciones de gRPC usan un solo archivo de arranque, el cual debe tener todos los campos que requiere el código del cliente y el servidor de gRPC. Un generador de arranque genera de forma automática el archivo de arranque 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 muestra.
Descripción general de la configuración
Este proceso de configuración es una extensión del Configuración de Cloud Service Mesh con GKE y servicios de gRPC sin proxy. Se hace referencia a los pasos existentes sin modificar de ese procedimiento de configuración cada vez que se aplican.
Las principales mejoras en la configuración de Cloud Service Mesh con GKE son las siguientes:
- Configura el servicio de CA, en el que creas grupos de CA privados y las autoridades certificadoras obligatorias.
- Crea un clúster de GKE con GKE Federación de identidades para cargas de trabajo para GKE y funciones de certificados de malla y servicio de CA y la integración de datos.
- Configurar la emisión de certificados de malla en el clúster
- Crear las cuentas de servicio de cliente y servidor
- Configurar el servidor de ejemplo que usa las APIs de xDS y las credenciales del servidor de xDS para adquirir 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ódigos para usar credenciales de xDS en las siguientes ubicaciones:
Actualiza la CLI de Google Cloud
Para actualizar la CLI de Google Cloud, ejecuta el siguiente comando:
gcloud components update
Configura variables de entorno
En esta guía, usas los comandos de Cloud Shell, y la información repetida en los comandos se representa con múltiples variables de entorno. Establece tus valores específicos según 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
Habilita el acceso a las API requeridas
En esta sección, se explica cómo habilitar el acceso a las API necesarias.
Ejecuta el siguiente comando para habilitar Cloud Service Mesh y otras APIs necesaria para la seguridad de la malla de servicios de 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
Crea o actualiza un clúster de GKE
La seguridad de los servicios de Cloud Service Mesh depende del servicio de integración en GKE. El clúster de GKE debe cumplir con los siguientes requisitos además de los requisitos para la configuración:
- Usa una versión de clúster mínima de 1.21.4-gke.1801. Si necesitas funciones que se encuentran en una versión posterior, puedes obtenerla del canal de versiones rápido.
- El clúster de GKE debe estar habilitado y configurado con certificados de malla de trabajo, como se describe en Crea autoridades certificadoras para emitir certificados.
Crea un clúster nuevo que use la federación de identidades para cargas de trabajo para GKE. Si actualizas un clúster existente, avanza al siguiente paso. El valor que le asigna a
--tags
debe coincidir con el nombre que se pasó a la marca--target-tags
para el Comandofirewall-rules create
en la sección Configura 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 tomar varios minutos en completarse.
Si usas un clúster existente, activa la federación de identidades para cargas de trabajo 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 a fin de cambiar al clúster nuevo como el clúster predeterminado para los comandos de
kubectl
:gcloud container clusters get-credentials CLUSTER_NAME \ --zone ZONE
Registra clústeres con una flota
Registra el clúster que creaste o actualizaste en Crea un clúster de GKE con una flota. El registro del clúster facilita la configuración de clústeres en varios proyectos.
Ten en cuenta que estos pasos pueden demorar hasta diez minutos en completarse.
Registra tu clúster con 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
de la siguiente manera:
- CLUSTER_NAME: Es el nombre del clúster.
- ZONE: La zona del clúster.
- MANIFEST-FILE_NAME: Es la ruta de acceso en la que estos comandos generan el manifiesto para el registro.
Cuando el proceso de registro se realice de forma correcta, 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
Cuando el proceso de la aplicación se realice de forma correcta, 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 la membresía del clúster:
kubectl get memberships membership -o yaml
El resultado debe incluir el grupo de Workload Identity que asigna la flota, en el que PROJECT_ID es el ID de tu proyecto:
workload_identity_pool: PROJECT_ID.svc.id.goog
Esto significa que el clúster se registró correctamente.
Crea autoridades certificadoras para emitir certificados
Para emitir certificados a tus pods, crea un grupo de servicios de CA y las siguientes autoridades certificadoras (CA):
- CA raíz. Esta es la raíz de confianza de todos los certificados de malla emitidos. Puedes usar una CA raíz existente si tienes una. Crea la CA raíz en el nivel
enterprise
, que está destinado a la emisión de certificados de larga duración y bajo volumen. - CA subordinada. Esta CA emite certificados para cargas de trabajo. Crea la CA subordinada en la región en la que se implementa el clúster. Crea la CA subordinada en el nivel
devops
, que está destinado a la emisión de certificados de corta duración y gran volumen.
Crear una CA subordinada es opcional, pero te recomendamos crear una en lugar de usar tu CA raíz para emitir certificados de malla de GKE. Si decides usar la CA raíz para emitir certificados de malla, asegúrate de que se mantenga el modo de emisión basado en configuración predeterminado.
La CA subordinada puede estar en una región diferente de tu clúster, pero recomendamos crearla en la misma región que tu clúster para optimizar el rendimiento. Sin embargo, puedes crear las CA subordinadas y raíz en regiones diferentes sin ningún impacto en el rendimiento o la disponibilidad.
Estas regiones son compatibles con el servicio de CA:
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 |
Delhi |
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 |
Virginia del Norte |
us-east5 |
Columbus |
us-south1 |
Dallas |
us-west1 |
Oregón |
us-west2 |
Los Ángeles |
us-west3 |
Salt Lake City |
us-west4 |
Las Vegas |
La lista de ubicaciones compatibles también se puede verificar ejecutando el siguiente comando:
gcloud privateca locations list
Otorga la
roles/privateca.caManager
de IAM a las personas que crean un grupo de CA y una CA. Ten en cuenta que, para MEMBER, el formato correcto esuser:userid@example.com
. Si esa persona es el usuario actual, puedes obtener el ID del usuario actual 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
Otorga la función
role/privateca.admin
para el servicio de AC a personas que necesitan modificar las políticas de IAM, en las queMEMBER
es un persona que necesita este acceso, específicamente, cualquier persona que realice los pasos siguientes que otorgan los permisosprivateca.auditor
y Roles deprivateca.certificateManager
:gcloud projects add-iam-policy-binding PROJECT_ID \ --member=MEMBER \ --role=roles/privateca.admin
Crea el grupo de servicios de 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
En esta configuración de demostración, usa 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 CA subordinada. Asegúrate de que el modo de emisión basado en la configuración predeterminado permanezca 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
En esta configuración de demostración, usa 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
Otorga la función
privateca.auditor
de IAM al grupo de CA 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"
Otorga la función
privateca.certificateManager
de IAM para que el grupo CA subordinado permita 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 de YAML
WorkloadCertificateConfig
para indicarle 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
Reemplaza lo siguiente:
- El ID del proyecto del proyecto en el que se ejecuta tu clúster.
PROJECT_ID
- El URI completamente calificado de la CA que emite los certificados de malla (ISSUING_CA_POOL_URI). Puede ser tu CA subordinada (recomendada) o la CA raíz. El formato es:
//privateca.googleapis.com/projects/PROJECT_ID/locations/SUBORDINATE_CA_POOL_LOCATION/caPools/SUBORDINATE_CA_POOL_NAME
- El ID del proyecto del proyecto en el que se ejecuta tu clúster.
Guarda la siguiente configuración de YAML
TrustConfig
para indicarle 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
Reemplaza lo siguiente:
- El ID del proyecto del proyecto en el que se ejecuta tu clúster.
PROJECT_ID
- El URI completamente calificado del grupo de CA raíz (ROOT_CA_POOL_URI). El formato es:
//privateca.googleapis.com/projects/PROJECT_ID/locations/ROOT_CA_POOL_LOCATION/caPools/ROOT_CA_POOL_NAME
- El ID del proyecto del proyecto en el que se ejecuta tu clúster.
Aplica las configuraciones a tu clúster.
kubectl apply -f WorkloadCertificateConfig.yaml kubectl apply -f TrustConfig.yaml
Crea un servicio de gRPC sin proxy con NEG
Para la seguridad de PSM, necesitas un servidor gRPC sin proxy capaz de usar xDS para
adquirir la configuración de seguridad de Cloud Service Mesh. Este paso es similar al de Configura servicios de GKE con NEG de la guía de configuración del balanceo de cargas de PSM, pero debes usar el servidor helloworld
con xDS habilitado del ejemplo de xDS en el repositorio grpc-java
en lugar de la imagen de java-example-hostname
.
Debes compilar y ejecutar este servidor en un contenedor compilado a partir de una imagen de openjdk:8-jdk
.
También puedes usar la característica de NEG con nombre, que te permite especificar un nombre para el NEG. Esto simplifica los pasos posteriores porque la implementación conoce el nombre del NEG sin tener que buscarlo.
El siguiente es un ejemplo completo de la especificación de Kubernetes del servidor de gRPC. Ten en cuenta lo siguiente:
- La especificación crea una cuenta de servicio de Kubernetes,
example-grpc-server
, que usa el Pod del servidor de gRPC. - En la especificación, se usa el campo
name
en la anotacióncloud.google.com/neg
del servicio para especificar el nombre de NEGexample-grpc-server
. - La variable
${PROJNUM}
representa el número de tu proyecto. - En la especificación, se usa la sección
initContainers
para ejecutar un generador de arranque a fin de propagar el archivo de arranque que necesita la biblioteca de gRPC sin proxy. Este archivo de arranque reside en/tmp/grpc-xds/td-grpc-bootstrap.json
en el contenedor del servidor de gRPC llamadoexample-grpc-server
.
Agrega la siguiente anotación a las especificaciones del Pod:
annotations: security.cloud.google.com/use-workload-certificates: ""
Puedes ver la ubicación correcta en la especificación completa que sigue.
Cuando se crea, 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 de forma automática.certificates.pem
es un conjunto de certificados con formato PEM que se puede presentar en otro Pod como la cadena de certificados de cliente o usarse como una cadena de certificados de servidor.ca_certificates.pem
es un conjunto de certificados con formato PEM que se usa como anclajes de confianza cuando se valida la cadena de certificados de cliente que presenta otro Pod o la cadena de certificados de servidor que se recibe cuando se conecta a otro Pod.
Ten en cuenta que ca_certificates.pem
contiene certificados para el dominio de confianza local de las cargas de trabajo, que es el grupo de cargas de trabajo del clúster.
El certificado de hoja en certificates.pem
contiene la siguiente aserción de identidad de SPIFFE de texto sin formato:
spiffe://WORKLOAD_POOL/ns/NAMESPACE/sa/KUBERNETES_SERVICE_ACCOUNT
En esta aserción, sucede lo siguiente:
- 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 lenguaje crean la especificación que se usará en este ejemplo.
Java
Ejecuta el siguiente comando para asegurarte de que el número de proyecto esté configurado de forma correcta:
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 esté configurado de forma correcta:
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 esté configurado de forma correcta:
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 esté configurado de forma correcta:
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
Otorga las funciones necesarias 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 verificar que el servicio y el Pod se creen correctamente:
kubectl get deploy/example-grpc-server kubectl get svc/example-grpc-server
Verifica que el nombre de NEG sea correcto:
gcloud compute network-endpoint-groups list \ --filter "name=example-grpc-server" --format "value(name)"
El comando debe mostrar el nombre de NEG
example-grpc-server
.
Configura Cloud Service Mesh con componentes del balanceo de cargas de Google Cloud
Los pasos de esta sección son similares a los de Configura Cloud Service Mesh con componentes de balanceo de cargas, pero hay algunos cambios, como se describe en las siguientes secciones.
Crea la verificación de estado, la regla de firewall y el servicio de backend
Cuando el servidor de gRPC está configurado para usar mTLS, las verificaciones de estado de gRPC no funcionan porque el cliente de verificación de estado no puede presentar un certificado de cliente válido a los servidores. Para abordar esto, puedes usar uno de dos métodos.
En el primer método, el servidor debe crear un puerto de entrega adicional que se designe como puerto de verificación de estado. Esto se conecta a un servicio de verificación de estado especial, como texto sin formato o TLS para ese puerto.
El servidor de ejemplo helloworld
de xDS usa PORT_NUMBER
+ 1 como el puerto de verificación de estado de texto simple. En el ejemplo, se usa 50052 como puerto de verificación de estado porque 50051 es el puerto del servidor de aplicaciones de gRPC.
En el segundo método, debes configurar la verificación de estado para comprobar solo la conectividad TCP con el puerto de entrega de la aplicación. Esto solo verifica la conectividad y genera tráfico innecesario al servidor cuando hay protocolos de enlace TLS fallidos. Por este motivo, te recomendamos que uses el primer método.
Crea la verificación de estado. Ten en cuenta que la verificación de estado no comenzará hasta que crees y, también, inicies el servidor.
Si creas un puerto de entrega designado para la verificación de estado, que es el enfoque que recomendamos, usa este comando:
gcloud compute health-checks create grpc grpc-gke-helloworld-hc \ --enable-logging --port 50052
Si creas una verificación de estado de TCP, la cual no recomendamos, usa este comando:
gcloud compute health-checks create tcp grpc-gke-helloworld-hc \ --use-serving-port
Crea el firewall. Asegúrate de que el valor de
--target-tags
coincida con el valor que proporcionaste para--tags
en la sección Crea o actualiza 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
Vincula 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
Esto es similar a la forma en que configuras los recursos Mesh
y GRPCRoute
en Configura servicios de gRPC sin proxy.
Crea la especificación
Mesh
y guárdala en un archivo llamadomesh.yaml
.name: grpc-mesh
Importa el recurso
Mesh
desde 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
desde la especificacióngrpc_route.yaml
.gcloud network-services grpc-routes import helloworld-grpc-route \ --source=grpc_route.yaml \ --location=global
Configura Cloud Service Mesh con seguridad de gRPC sin proxy
En este ejemplo, se muestra cómo configurar mTLS en el lado del cliente y del servidor.
Formato de las referencias de políticas
Ten en cuenta el siguiente formato obligatorio para hacer referencia a las políticas de TLS del servidor y 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
Configura mTLS en el servidor
Primero, crea una política de TLS para el servidor. La política solicita al gRPC del lado del servidor que use la configuración del complemento certificateProvicerInstance
identificada por el nombre google_cloud_private_spiffe
para el certificado de identidad, que es parte de serverCertificate
. En la sección mtlsPolicy
, se indica la seguridad mTLS y se usa el mismo google_cloud_private_spiffe
que la configuración del complemento para clientValidationCa
, que es la especificación del certificado raíz (validación).
A continuación, crea una política de extremos. Esto especifica que un backend, por ejemplo, un servidor de gRPC, que usa el puerto 50051
con cualquier etiqueta de metadatos o ninguna etiqueta, recibe la política de TLS del servidor adjunta llamada server-mtls-policy
. Tú especificas los metadatos
etiquetas que usan MATCH_ALL
o un valor admitido. Las etiquetas de metadatos compatibles se pueden encontrar en el campo endpointMatcher.metadataLabelMatcher.metadataLabelMatchCriteria
del documento NetworkServicesEndpointPolicy. Crea la política de extremos con un archivo temporal
ep-mtls-psms.yaml
, que contiene los valores del recurso de la política de extremos
con la política que ya definiste.
Crea un archivo temporal
server-mtls-policy.yaml
en el directorio actual con los valores del recurso de la política de 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
mediante la importación del 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 extremos mediante 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
Importa el archivo
ep-mtls-psms.yaml
para crear el recurso de política de extremo:gcloud beta network-services endpoint-policies import ep-mtls-psms \ --source=ep-mtls-psms.yaml --location=global
Configura mTLS en el cliente
La política de seguridad del cliente está vinculada con el servicio de backend. Cuando un cliente accede a un backend (el servidor de gRPC) a través del servicio de backend, la política de seguridad adjunta del cliente se envía al cliente.
Crea el contenido de los recursos de la política de TLS del 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
mediante la importación del 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 agrega detalles de
subjectAltNames
en el mensajeSecuritySettings
, como en el siguiente ejemplo. Reemplaza${PROJECT_ID}
por el valor del ID del proyecto, que es el siguiente: El valor de la variable de entorno${PROJECT_ID}
que se describió 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 de gRPC en la especificación de 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
Agrega el mensaje
securitySettings
al servicio de backend que ya creaste. Con estos pasos se exporta el contenido del servicio de backend actual, se agrega el mensaje desecuritySetting
del cliente y se vuelve a importar el contenido nuevo 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
Verifica la configuración
Se completó la configuración de Cloud Service Mesh, incluida la seguridad del servidor y del cliente. A continuación, prepara y ejecuta las cargas de trabajo del servidor y del cliente. Esto completa el ejemplo.
Crea un cliente de gRPC sin proxy
Este paso es similar al paso anterior Crea un servicio de gRPC sin proxy.
Usa el cliente helloworld
habilitado para xDS desde el directorio de ejemplo de xDS en el repositorio grpc-java
. Compila y ejecuta el cliente en un contenedor compilado a partir de una imagen openjdk:8-jdk
. La especificación de Kubernetes para el cliente de gRPC hace lo siguiente.
- Crea una cuenta de servicio de Kubernetes
example-grpc-client
que usa el Pod de cliente de gRPC. ${PROJNUM}
representa el número de proyecto y se debe reemplazar por el número real.
Agrega la siguiente anotación a las especificaciones del Pod:
annotations: security.cloud.google.com/use-workload-certificates: ""
Cuando se crea, 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 de forma automática.certificates.pem
es un conjunto de certificados con formato PEM que se puede presentar en otro Pod como la cadena de certificados de cliente o usarse como una cadena de certificados de servidor.ca_certificates.pem
es un conjunto de certificados con formato PEM que se usa como anclajes de confianza cuando se valida la cadena de certificados de cliente que presenta otro Pod o la cadena de certificados de servidor que se recibe cuando se conecta a otro Pod.
Ten en cuenta que ca_certificates.pem
contiene los certificados raíz del dominio de confianza local para las cargas de trabajo, que es el grupo de cargas de trabajo del clúster.
El certificado de hoja en certificates.pem
contiene la siguiente aserción de identidad de SPIFFE de texto sin formato:
spiffe://WORKLOAD_POOL/ns/NAMESPACE/sa/KUBERNETES_SERVICE_ACCOUNT
En esta aserción, sucede lo siguiente:
- 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 lenguaje crean la especificación que se usará en este ejemplo.
Java
Ejecuta el siguiente comando para asegurarte de que el número de proyecto esté configurado de forma correcta:
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 - --config-mesh-experimental - "grpc-mesh" - "/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 esté configurado de forma correcta:
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 esté configurado de forma correcta:
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 esté configurado de forma correcta:
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
Otorga las funciones necesarias 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
Verifica que el Pod se esté ejecutando.
kubectl get pods
El comando muestra información similar a la siguiente:
NAMESPACE NAME READY STATUS RESTARTS AGE default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 104s [..skip..]
Ejecuta el servidor
Compila y ejecuta el servidor helloworld
con xDS habilitado en el Pod del servidor que creaste antes.
Java
Obtén el nombre del Pod creado para el servicio
example-grpc-server
:kubectl get pods | grep example-grpc-server
Verás comentarios como los siguientes:
default example-grpc-server-77548868d-l9hmf 1/1 Running 0 105s
Abre una shell al pod servidor:
kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
En la shell, verifica que el archivo de arranque en
/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 para Java y compila la aplicación del 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, con50051
como el puerto de escucha yxds-server
como el 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 del En 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
Verás comentarios como los siguientes:
default example-grpc-server-77548868d-l9hmf 1/1 Running 0 105s
Abre una shell al pod servidor:
kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
En la shell, verifica que el archivo de arranque en
/tmp/grpc-xds/td-grpc-bootstrap.json
coincida con el esquema descrito en la sección Archivo de arranque.Descarga gRPC para C++ y compila la aplicación del 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 mediante
50051
como el puerto de escucha yxds_greeter_server
como el 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
Después de que el servidor obtenga 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
Verás comentarios como los siguientes:
default example-grpc-server-77548868d-l9hmf 1/1 Running 0 105s
Abre una shell al pod servidor:
kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/bash
En la shell, verifica que el archivo de arranque en
/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 para Python y compila 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 la seguridad habilitada para xDS, con50051
como el puerto de escucha.python3 server.py 50051 --xds-creds
Una vez que el servidor obtiene la configuración necesaria del En 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
Verás comentarios como los siguientes:
default example-grpc-server-77548868d-l9hmf 1/1 Running 0 105s
Abre una shell al pod servidor:
kubectl exec -it example-grpc-server-77548868d-l9hmf -- /bin/sh
En la shell, verifica que el archivo de arranque en
/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 para Go y navega al directorio que contiene la aplicación del 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, con50051
como el puerto de escucha:GRPC_GO_LOG_VERBOSITY_LEVEL=2 GRPC_GO_LOG_SEVERITY_LEVEL="info" \ go run main.go \ -xds_creds \ -port 50051
Después de que el servidor obtenga 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 verificación de estado toma entre 3 y 5 minutos para mostrar que el servicio está en buen estado después de iniciarse.
Ejecuta el cliente y verifica la configuración
Compila y ejecuta el cliente helloworld
habilitado para xDS en el Pod de cliente que creaste antes.
Java
Obtén el nombre del pod cliente:
kubectl get pods | grep example-grpc-client
Verás comentarios como los siguientes:
default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 105s
Abre una shell al pod de cliente:
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
En la shell de comandos, descarga la versión 1.42.1 de gRPC para Java y compila 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 string de conexión de destino:./build/install/example-xds/bin/xds-hello-world-client --xds-creds xds-client \ xds:///helloworld-gke:8000
Deberías ver un resultado similar a este:
Greeting: Hello xds-client, from xds-server
C++
Obtén el nombre del pod cliente:
kubectl get pods | grep example-grpc-client
Verás comentarios como los siguientes:
default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 105s
Abre una shell al pod de cliente:
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
Una vez que estés dentro de la shell, descarga gRPC para 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 string 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ías ver un resultado similar a este:
Greeter received: Hello world
Python
Obtén el nombre del pod cliente:
kubectl get pods | grep example-grpc-client
Verás comentarios como los siguientes:
default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 105s
Abre una shell al pod de cliente:
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
Una vez que estés dentro de la shell, descarga la versión 1.41.0 de gRPC para 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 string de conexión de destino:python3 client.py xds:///helloworld-gke:8000 --xds-creds
Deberías ver un resultado similar a este:
Greeter client received: Hello you from example-host!
Go
Obtén el nombre del pod cliente:
kubectl get pods | grep example-grpc-client
Verás comentarios como los siguientes:
default example-grpc-client-7c969bb997-9fzjv 1/1 Running 0 105s
Abre una shell al pod de cliente:
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/sh
Una vez que estés dentro de la shell, descarga la versión 1.42.0 de gRPC para Go y navega al directorio que contiene la aplicación cliente
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/client
Compila y ejecuta el cliente con la marca
--xds_creds
para indicar Seguridad habilitada para xDS, nombre de cliente y 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ías ver un resultado similar a este:
Greeting: Hello xds-client, from example-grpc-server-77548868d-l9hmf
Configura el acceso a nivel de servicio con una política de autorización
Se requiere compatibilidad con gRFC A41 para la compatibilidad con políticas de autorización. Puedes encontrar las versiones de lenguaje necesarias en GitHub.
Usa 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 precaución en Restringir el acceso con autorización.
Para facilitar la verificación de la configuración, crea un nombre de host adicional que el cliente pueda usar para referirse al servicio helloworld-gke
.
Actualiza la especificación
GRPCRoute
que se almacenó antes 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
Con las siguientes instrucciones, se crea una política de autorización que permite solicitudes que envía la cuenta example-grpc-client
en la que el nombre de host es helloworld-gke:8000
y el puerto es 50051
.
gcloud
Para crear una política de autorización, crea 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 extremos para hacer referencia a la política de autorización nueva. Para ello, agrega lo siguiente al archivo
ep-mtls-psms.yaml
.authorizationPolicy: projects/${PROJECT_ID}/locations/global/authorizationPolicies/helloworld-gke-authz-policy
La política de extremo ahora especifica que mTLS y la política de autorización se deben aplicar en las solicitudes entrantes a los Pods cuyos archivos de arranque de gRPC contienen la etiqueta
app:helloworld
.Importa la política:
gcloud network-services endpoint-policies import ep-mtls-psms \ --source=ep-mtls-psms.yaml --location=global
Valida la política de autorización
Usa estas instrucciones para confirmar que la política de autorización funciona de forma correcta.
Java
Abre una shell al Pod de cliente que usaste antes.
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
En la 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ías 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ías 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 no esté en usar todavía. Espera unos minutos y vuelve a probar todo el proceso de verificación.
Go
Abre una shell al Pod de cliente que usaste antes.
kubectl exec -it example-grpc-client-7c969bb997-9fzjv -- /bin/bash
En la 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ías 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ías 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 no esté en usar todavía. Espera unos minutos y vuelve a probar todo el proceso de verificación.
Usa TLS en lugar de mTLS
En este ejemplo, el uso de TLS solo requiere un pequeño cambio.
En
ServerTlsPolicy
, descarta elmtlsPolicy
:cat << EOF > server-tls-policy.yaml name: "server-tls-policy" serverCertificate: certificateProviderInstance: pluginInstance: google_cloud_private_spiffe EOF
En su lugar, usa esta política en
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
ClientTlsPolicy
para mTLS también funciona en el caso de TLS, pero la secciónclientCertificate
de la política se puede descartar, 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
Usa la seguridad del servicio con el ejemplo de Wallet
En esta sección, se proporciona una descripción general de alto nivel sobre cómo habilitar el ejemplo de Vault con seguridad de servicios para Java, C++ y Go.
Java
Puedes encontrar el código fuente de ejemplo para Java en github.
El código ya usa las credenciales XdsChannel
y XdsServer
cuando configuras la seguridad sin proxy.
En estas instrucciones, se describe la configuración del ejemplo de Vault con Go. El proceso es similar para Java En las instrucciones se usa una imagen de Docker preexistente que se obtuvo del repositorio de contenedores de Google Cloud.
Para crear el ejemplo, sigue estas instrucciones:
- Clona el repositorio y obtén los archivos en el directorio Ejemplos de gRPC.
- Edita el archivo
00-common-env.sh
. Marca como comentario la línea existente que establece el valor deWALLET_DOCKER_IMAGE
en la imagen de Docker de Go y quita los comentarios de la línea que establece el valor deWALLET_DOCKER_IMAGE
en la imagen de Docker de Java. - Crea y configura instancias de Cloud Router con las instrucciones que aparecen en Crea y configura instancias de Cloud Router o con la función
create_cloud_router_instances
en la secuencia de comandos10.apis.sh
. - Crea un clúster mediante las instrucciones para el ejemplo
hello world
o la funcióncreate_cluster
en la secuencia de comandos20-cluster.sh
. - Crea autoridades certificadoras privadas con las instrucciones para el servicio de CA o con la secuencia de comandos
30-private-ca-setup.sh
. - Crea recursos de Kubernetes, incluidas las cuentas de servicio, los espacios de nombres, los servicios de Kubernetes, los NEG y la implementación en el lado del servidor para todos los servicios:
account
,stats
,stats_premium
,wallet_v1
ywallet_v2
, con la secuencia de comandos40-k8s-resources.sh
. - Para cada uno de los servicios que creaste, crea una verificación de estado y un servicio de backend mediante
create_health_check
ycreate_backend_service
en la secuencia de comandos50-td-components.sh
. - Crea los componentes de enrutamiento de Cloud Service Mesh con
create_routing_components
en la secuencia de comandos60-routing-components.sh
. - Crear los componentes de seguridad de Cloud Service Mesh para cada servicio de backend
con
create_security_components
en la secuencia de comandos70-security-components.sh
. - Crea la implementación de cliente de Marketplace mediante
create_client_deployment
en la secuencia de comandos75-client-deployment.sh
. - Para verificar la configuración, inicia el cliente como se describe en Verifica con los clientes de grpc-wallet.
C++
Puedes encontrar el código fuente de ejemplo para C++ en github. El código ya usa las credenciales XdsChannel
y XdsServer
cuando configuras la seguridad sin proxy.
En estas instrucciones, se describe la configuración del ejemplo de Vault con Go. El proceso es similar para C++ En las instrucciones se usa una imagen de Docker preexistente que se obtuvo del repositorio de contenedores de Google Cloud.
Para crear el ejemplo, sigue estas instrucciones:
- Clona el repositorio y obtén los archivos en el directorio Ejemplos de gRPC.
- Edita el archivo
00-common-env.sh
. Comenta la línea existente que establece el valor deWALLET_DOCKER_IMAGE
en la imagen de Docker de Go y quita el comentario de la línea que establece el valor deWALLET_DOCKER_IMAGE
en la imagen de Docker de C++. - Crea y configura instancias de Cloud Router con las instrucciones que aparecen en Crea y configura instancias de Cloud Router o con la función
create_cloud_router_instances
en la secuencia de comandos10.apis.sh
. - Crea un clúster mediante las instrucciones para el ejemplo
hello world
o la funcióncreate_cluster
en la secuencia de comandos20-cluster.sh
. - Crea autoridades certificadoras privadas con las instrucciones para el servicio de AC o con la secuencia de comandos
30-private-ca-setup.sh
. - Crea recursos de Kubernetes, incluidas las cuentas de servicio, los espacios de nombres, los servicios de Kubernetes, los NEG y la implementación en el lado del servidor para todos los servicios:
account
,stats
,stats_premium
,wallet_v1
ywallet_v2
, con la secuencia de comandos40-k8s-resources.sh
. - Para cada uno de los servicios que creaste, crea una verificación de estado y un servicio de backend mediante
create_health_check
ycreate_backend_service
en la secuencia de comandos50-td-components.sh
. - Crea los componentes de enrutamiento de Cloud Service Mesh con
create_routing_components
en la secuencia de comandos60-routing-components.sh
. - Crear los componentes de seguridad de Cloud Service Mesh para cada servicio de backend
con
create_security_components
en la secuencia de comandos70-security-components.sh
. - Crea la implementación de cliente de Marketplace mediante
create_client_deployment
en la secuencia de comandos75-client-deployment.sh
. - Para verificar la configuración, inicia el cliente como se describe en Verifica con los clientes de grpc-wallet.
Go
Puedes encontrar código fuente de ejemplo para Go en GitHub. El código ya usa las credenciales XdsChannel
y XdsServer
cuando configuras la seguridad sin proxy.
En las instrucciones se usa una imagen de Docker preexistente que se obtuvo del repositorio de contenedores de Google Cloud.
Para crear el ejemplo, sigue estas instrucciones:
- Clona el repositorio y obtén los archivos en el directorio Ejemplos de gRPC.
- Edita el archivo
00-common-env.sh
a fin de establecer los valores correctos para las variables de entorno. - Crea y configura instancias de Cloud Router con las instrucciones que aparecen en Crea y configura instancias de Cloud Router o con la función
create_cloud_router_instances
en la secuencia de comandos10.apis.sh
. - Crea un clúster mediante las instrucciones para el ejemplo
hello world
o la funcióncreate_cluster
en la secuencia de comandos20-cluster.sh
. - Crea autoridades certificadoras privadas con las instrucciones para el servicio de CA o con la secuencia de comandos
30-private-ca-setup.sh
. - Crea recursos de Kubernetes, incluidas las cuentas de servicio, los espacios de nombres, los servicios de Kubernetes, los NEG y la implementación en el lado del servidor para todos los servicios:
account
,stats
,stats_premium
,wallet_v1
ywallet_v2
, con la secuencia de comandos40-k8s-resources.sh
. - Para cada uno de los servicios que creaste, crea una verificación de estado y un servicio de backend mediante
create_health_check
ycreate_backend_service
en la secuencia de comandos50-td-components.sh
. - Crea los componentes de enrutamiento de Cloud Service Mesh con
create_routing_components
en la secuencia de comandos60-routing-components.sh
. - Crear los componentes de seguridad de Cloud Service Mesh para cada servicio de backend
con
create_security_components
en la secuencia de comandos70-security-components.sh
. - Crea la implementación de cliente de Marketplace mediante
create_client_deployment
en la secuencia de comandos75-client-deployment.sh
. - Para verificar la configuración, inicia el cliente como se describe en Verifica con los clientes de grpc-wallet.
Archivo de arranque
En el proceso de configuración de esta guía, se usa un generador de arranque para crear el archivo de arranque requerido. En esta sección, se proporciona información de referencia sobre el archivo de arranque.
El archivo de arranque contiene información de configuración que requiere el código de gRPC sin proxy, incluida la información de conexión para el 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 de gRPC requiere un campo adicional. Un archivo de arranque de muestra se ve de la siguiente manera:
{ "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 para el servicio de seguridad
Los siguientes campos reflejan las modificaciones relacionadas con la seguridad y el uso de xDS v3:
El campo id
dentro de node
proporciona una identidad única al cliente de gRPC para Cloud Service Mesh. Debes proporcionar el número del proyecto de Google Cloud y el nombre de red con el ID del nodo en este formato:
projects/{project number}/networks/{network name}/nodes/[UNIQUE_ID]
El siguiente es un ejemplo para el proyecto 1234 y la red predeterminada:
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 de gRPC usa este campo para recuperar el recurso de objeto de escucha desde Cloud Service Mesh para la seguridad del servidor.
Campos de configuración de seguridad en el archivo de arranque
Clave JSON | Tipo | Valor | Notas |
---|---|---|---|
server_listener_resource_name_template |
String | grpc/server?xds.resource.listening_address=%s |
Obligatorio para los servidores gRPC. gRPC usa este valor con el objetivo de componer el nombre del recurso para recuperar el recurso “Listener” de Cloud Service Mesh para la seguridad del servidor y otros parámetros de configuración. gRPC usa esto para formar la cadena del nombre del recurso |
certificate_providers |
Struct de JSON | google_cloud_private_spiffe |
Obligatorio. El valor es un struct de JSON que representa una asignación de nombres para instancias de proveedor de certificados. Se usa una instancia de proveedor de certificados para recuperar identidades y certificados raíz. El archivo de arranque de ejemplo contiene un nombre, google_cloud_private_spiffe , con el struct de JSON de la instancia del proveedor del certificado como valor. Cada struct de JSON de instancia del proveedor de certificados tiene dos campos:
|
El contenido de la estructura JSON config
para el complemento file_watcher
es el siguiente:
certificate_file
: string obligatoria. Este valor es la ubicación del certificado de identidad.private_key_file
: string obligatoria. El valor es la ubicación del archivo de clave privada, que debe coincidir con el certificado de identidad.ca_certificate_file
: string obligatoria. El valor es la ubicación del certificado raíz, que también se conoce como el paquete de confianza.refresh_interval
: string opcional. El valor indica el intervalo de actualización, especificado con la representación de string de una asignación JSON de Duration. El valor predeterminado es “600s”, una duración de 10 minutos.
Generador de arranque
La imagen del contenedor del generador de arranque 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
.
Las opciones de línea de comandos más usadas son las siguientes:
--output
: Usa esta opción para especificar dónde se escribe el archivo de arranque de salida, por ejemplo, el comando de arranque--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 coinciden con el recursoMesh
.--node-metadata
: Usa esta marca para propagar los metadatos del nodo en el archivo de arranque. Esto es obligatorio cuando usas comparadores de etiquetas de metadatos enEndpointPolicy
, en los que Cloud Service Mesh usa los datos de etiquetas proporcionados en la sección de metadatos de nodo del archivo de arranque. El argumento se proporciona en el formato clave=valor, por ejemplo:--node-metadata version=prod --node-metadata type=grpc
.
Con la información anterior, se agrega lo siguiente en la sección de metadatos de nodo del archivo de arranque:
{ "node": { ... "metadata": { "version": "prod", "type": "grpc", ... }, ... }, ... }
Borrar la implementación
También puedes ejecutar estos comandos para borrar la implementación que creaste con esta guía.
Para borrar el clúster, ejecuta este comando:
gcloud container clusters delete CLUSTER_NAME --zone ZONE --quiet
Para borrar los recursos que creaste, 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
Soluciona problemas
Usa estas instrucciones para resolver problemas con la implementación de seguridad.
Las cargas de trabajo no pueden obtener la configuración de Cloud Service Mesh
Podría aparecer un error similar a este:
PERMISSION_DENIED: Request had insufficient authentication scopes.
Asegúrate de que se den las siguientes condiciones:
- Creaste tu clúster de GKE con el argumento
--scopes=cloud-platform
. - Asignaste el
roles/trafficdirector.client
a tus cuentas de servicio de Kubernetes. - Asignaste
roles/trafficdirector.client
a tu cuenta de servicio de Google Cloud predeterminada (la cuenta ${GSA_EMAIL} anterior). - Habilitaste el servicio
trafficdirector.googleapis.com
(API).
Tu servidor de gRPC no usa TLS/mTLS incluso con la configuración correcta de Cloud Service Mesh
Asegúrate de especificar GRPC_SERVER
en la configuración de las políticas de extremos. Si especificaste SIDECAR_PROXY
, gRPC ignora la configuración.
No puedes crear el clúster de GKE con la versión de clúster solicitada
El comando de creación del clúster de GKE podría fallar con un error similar al siguiente:
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 versiones rápido para obtener la versión correcta de esta.
Si aparece el error No usable endpoint
Si un cliente no puede comunicarse con el servidor debido a un error No usable endpoint
, es posible que el verificador de estado haya marcado los backends del servidor como en mal estado.
Para verificar el estado de los backends, ejecuta este comando gcloud
:
gcloud compute backend-services get-health grpc-gke-helloworld-service --global
Si el comando muestra que el backend está en mal estado, puede deberse a uno de estos motivos:
- El firewall no se creó o no contiene el rango de IP de origen correcto.
- Las etiquetas de destino de tu firewall no coinciden con las etiquetas del clúster que creaste.
Las cargas de trabajo no pueden comunicarse en la configuración de seguridad
Si las cargas de trabajo no pueden comunicarse después de configurar la seguridad de la malla de servicios sin proxy, sigue estas instrucciones para determinar la causa.
- Inhabilita la seguridad sin proxy y elimina los problemas en los casos de uso de balanceo de cargas de la malla de servicios sin proxy. Para inhabilitar la seguridad en la malla, realiza una de las siguientes acciones:
- Usa credenciales de texto sin formato en el cliente y el servidor O
- no configures la seguridad del servicio de backend ni la política de extremos en la configuración de Cloud Service Mesh.
Sigue los pasos que se indican en Solución de problemas de implementaciones de Cloud Service Mesh sin proxy, ya que no hay una configuración de seguridad en la implementación.
Modifica las cargas de trabajo para usar credenciales de xDS con texto simple o credenciales no seguras como credenciales de resguardo. Mantén la configuración de Cloud Service Mesh con la seguridad inhabilitada, como se mencionó anteriormente. En este caso, aunque gRPC permite que Cloud Service Mesh configure la seguridad, Cloud Service Mesh no envía información de seguridad, en cuyo caso, gRPC debería recurrir a credenciales de texto sin formato (o credenciales inseguras), que deberían funcionar similar al primer caso anterior. Si este caso no funciona, haz lo siguiente:
- Aumenta el nivel de registro en el cliente y 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 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 mensajes de registro relacionados con los protocolos de enlace TLS, verifica el código fuente de tu aplicación y asegúrate de usar texto no seguro o simple como credenciales de resguardo. Si el código fuente de la aplicación es correcto, es posible que sea un error en la biblioteca de gRPC.
Verifica que la integración del servicio de CA con GKE funcione de forma correcta para tu clúster de GKE mediante los pasos para solucionar problemas de esa guía del usuario. Asegúrate de que los certificados y claves que proporciona esa característica estén disponibles en el directorio especificado,
/var/run/secrets/workload-spiffe-credentials/
.Habilitar TLS (en lugar de mTLS) en la malla, como se describió anteriormente, y reiniciar las cargas de trabajo del cliente y el servidor.
- Aumentar el nivel de registro del lado del cliente y del servidor para poder para ver los mensajes xDS intercambiados entre gRPC y Cloud Service Mesh.
- Asegúrate de que Cloud Service Mesh tenga habilitada 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 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 creaste para tu servicio de backend. Para cada servicio de Kubernetes que creaste, hay un ID de SPIFFE asociado, en este formato:
spiffe://${WORKLOAD_POOL}/ns/${K8S_NAMESPACE}/sa/${SERVICE_ACCOUNT}
Estos valores son los siguientes:
WORKLOAD_POOL
: el grupo de cargas de trabajo del clúster, que es${PROJECT_ID}.svc.id.goog
K8S_NAMESPACE
: el espacio de nombres de Kubernetes que usaste en la implementación del servicioSERVICE_ACCOUNT
: la cuenta de servicio de Kubernetes que usaste en la implementación del servicio
Para cada servicio de Kubernetes que adjuntaste al servicio de backend como un grupo de extremos de red, asegúrate de haber calculado de forma correcta el ID de SPIFFE y haber agregado ese ID de SPIFFE al campo subjectAltNames
en el mensaje SecuritySettings
.
Las aplicaciones no pueden usar los certificados mTLS con tu biblioteca de gRPC
Si tus aplicaciones no pueden usar los certificados mTLS con tu biblioteca de gRPC, haz lo siguiente:
Verifica que la especificación del pod contenga la anotación
security.cloud.google.com/use-workload-certificates
que se describe en Crea un servicio de gRPC sin proxy con NEG.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 certificado de hoja: "/var/run/secrets/workload-spiffe-credentials/certificates.pem"
- Clave privada: “/var/run/secrets/workload-spiffe-credentials/private_key.pem”
- Paquete de CA: "/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 la vinculación de función de IAM correcta y otórgale acceso al servicio de CA:
# 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.
Verifica que el certificado no haya vencido. Esta es la cadena de certificados y el certificado de hoja en
/var/run/secrets/workload-spiffe-credentials/certificates.pem
. Como comprobación, ejecuta este comando:cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
Ejecuta el siguiente comando para verificar que el tipo de clave 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
Verifica que tu aplicación de Java para gRPC tenga el siguiente
keyAlgorithm
en el archivo YAMLWorkloadCertificateConfig
:
keyAlgorithm: rsa: modulusSize: 4096
Verifica que la CA use la misma familia de claves que la clave del certificado.
El cliente, el servidor o el par rechazaron el certificado de una aplicación
- Verifica que la aplicación par use el mismo paquete de confianza para verificar el certificado.
- Verifica que el certificado en uso no esté vencido (cadena de certificados junto con 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 para los pods en tu especificación de implementación.
No se pudo crear el clúster con la marca --enable-mesh-certificates
Asegúrate de ejecutar 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 suceder en situaciones como las siguientes:
WorkloadCertificateConfig
oTrustConfig
no están bien configurados o no se encuentran.- No se aprueban las CSR.
Para verificar si el aprovisionamiento de certificados falla, revisa los eventos del pod.
Verifica el estado del Pod:
kubectl get pod -n POD_NAMESPACE POD_NAME
Reemplaza lo siguiente:
POD_NAMESPACE
: es el espacio de nombres del Pod.POD_NAME
: es el nombre del Pod.
Revisa los eventos recientes de tu pod:
kubectl describe pod -n POD_NAMESPACE POD_NAME
Si falla el aprovisionamiento de certificados, verás un evento con
Type=Warning
,Reason=FailedMount
,From=kubelet
y un campoMessage
que comienza conMountVolume.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 de solución de problemas si el motivo por el que tus pods no se inician es porque hay objetos mal configurados o CSR rechazadas.
La configuración de WorkloadCertificateConfig
o TrustConfig
es incorrecta
Asegúrate de haber creado los objetos WorkloadCertificateConfig
y TrustConfig
de forma correcta. Puedes diagnosticar una configuración incorrecta en cualquiera de estos objetos mediante 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, aparece
status: "False"
en su lugar. Los camposreason
ymessage
contienen detalles adicionales sobre la solución de problemas.
Las CSR no están aprobadas.
Si algo sale mal durante el proceso de aprobación de la CSR, puedes verificar los detalles del error en las condiciones de type: Approved
y type: Issued
de la CSR.
Enumera las CSR relevantes mediante
kubectl
:kubectl get csr \ --field-selector='spec.signerName=spiffe.gke.io/spiffe-leaf-signer'
Elige una CSR que tenga el estado
Approved
y noIssued
, o que no tenga el estadoApproved
.Obtén detalles de la CSR seleccionada con kubectl:
kubectl get csr CSR_NAME -o yaml
Reemplaza
CSR_NAME
por el nombre de la CSR que elegiste.
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 de solución de problemas para CSR no válidas aparece en los campos message
y reason
.
Faltan certificados en los pods
Obtén las especificaciones de pod para tu pod:
kubectl get pod -n POD_NAMESPACE POD_NAME -o yaml
Reemplaza lo siguiente:
POD_NAMESPACE
: es el espacio de nombres del Pod.POD_NAME
: es el nombre del Pod.
Verifica que las especificaciones del pod contengan la anotación
security.cloud.google.com/use-workload-certificates
que se describe en Configura pods para recibir credenciales de mTLS.Verifica que el controlador de admisión de certificados de malla de GKE inserte de forma correcta un volumen de controlador CSI de tipo
workloadcertificates.security.cloud.google.com
en tu especificación de pods:volumes: ... -csi: driver: workloadcertificates.security.cloud.google.com name: gke-workload-certificates ...
Comprueba la presencia de una activación de volumen 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 ancla de confianza de CA:
/var/run/secrets/workload-spiffe-credentials/ca_certificates.pem
- Paquete de cadena de certificados:
Si los archivos no están disponibles, realiza los siguientes pasos:
Recupera la instancia del servicio de CA (vista previa) del clúster:
kubectl get workloadcertificateconfigs default -o jsonpath '{.spec.certificateAuthorityConfig.certificateAuthorityServiceConfig.endpointURI}'
Recupera el estado de la instancia del servicio de CA (vista previa):
gcloud privateca ISSUING_CA_TYPE describe ISSUING_CA_NAME \ --location ISSUING_CA_LOCATION
Reemplaza lo siguiente:
ISSUING_CA_TYPE
: el tipo de CA de la emisión, que debe sersubordinates
oroots
.ISSUING_CA_NAME
: el nombre de la CA emisora.ISSUING_CA_LOCATION
: la región de la CA emisora.
Obtén la política de IAM para la CA raíz:
gcloud privateca roots get-iam-policy ROOT_CA_NAME
Reemplaza
ROOT_CA_NAME
por el nombre de tu CA raíz.En la política de IAM, verifica que exista la vinculación de la política
privateca.auditor
:... - members: - serviceAccount:service-PROJECT_NUMBER@container-engine-robot.iam.gserviceaccount.com role: roles/privateca.auditor ...
En este ejemplo,
PROJECT_NUMBER
es el número del proyecto de tu clúster.Obtén la política de IAM para la CA subordinada:
gcloud privateca subordinates get-iam-policy SUBORDINATE_CA_NAME
Reemplaza
SUBORDINATE_CA_NAME
por el nombre de la CA subordinada.En la política de IAM, verifica que exista la vinculación de la 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 del proyecto de tu clúster.
Las aplicaciones no pueden usar las credenciales de mTLS emitidas
Verifica que el certificado no haya vencido:
cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
Comprueba que tu aplicación admita el tipo de clave que usaste.
cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Public Key Algorithm" -A 3
Comprueba que la CA 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
Reemplaza lo siguiente:
ISSUING_CA_TYPE
: el tipo de CA de la emisión, que debe sersubordinates
oroots
.ISSUING_CA_NAME
: el nombre de la CA emisora.ISSUING_CA_LOCATION
: la región de la CA emisora.
Comprueba que el
keySpec.algorithm
en el resultado sea el mismo algoritmo de clave que definiste en el manifiesto de YAMLWorkloadCertificateConfig
. El resultado se verá así: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 ...
Los certificados se rechazan
- Verifica que la aplicación par use el mismo paquete de confianza para verificar el certificado.
Verifica que el certificado no haya vencido:
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 usas la API de recarga de credenciales de gRPC para Go, actualice las credenciales del sistema de archivos de forma periódica.
Verifica que las cargas de trabajo estén en el mismo dominio de confianza que la CA. Los certificados de malla de GKE admiten la comunicación entre cargas de trabajo en un solo dominio de confianza.
Limitaciones
La seguridad del servicio de Cloud Service Mesh solo es compatible con GKE. No puedes implementar la seguridad del servicio con Compute Engine.
Cloud Service Mesh no es compatible con situaciones en las que hay dos o más recursos de políticas de extremos que coinciden de manera equitativa con un extremo, por ejemplo, dos políticas con las mismas etiquetas y puertos, o dos o más políticas con diferentes etiquetas que coinciden de manera equitativa con las etiquetas de un extremo. Para obtener más información sobre cómo de extremo se vinculan con las etiquetas de un extremo, consulta la APIs para EndpointPolicy.EndpointMatcher.MetadataLabelMatcher. En estos casos, Cloud Service Mesh no genera una configuración de seguridad de cualquiera de las políticas en conflicto.