Dienstsicherheit mit Envoy einrichten

Folgen Sie der Anleitung in diesem Leitfaden, um die Authentifizierung und Autorisierung zu konfigurieren. für Dienste, die mit Cloud Service Mesh und Envoy-Proxys bereitgestellt werden. Umfassende Informationen zur Sicherheit von Cloud Service Mesh-Diensten finden Sie unter Sicherheit von Cloud Service Mesh-Diensten.

Voraussetzungen

Prüfen Sie vor der Konfiguration der Dienstsicherheit für Cloud Service Mesh mit Envoy, ob Ihre Konfiguration die folgenden Voraussetzungen erfüllt:

Einrichtung vorbereiten

In den folgenden Abschnitten werden die Aufgaben beschrieben, die Sie ausführen müssen, bevor Sie den Cloud Service Mesh-Sicherheitsdienst einrichten. Diese Aufgaben sind:

  • Google Cloud CLI aktualisieren
  • Variablen einrichten
  • Aktivieren der für Cloud Service Mesh erforderlichen APIs mit Certificate Authority Service

gcloud-Befehlszeilentool aktualisieren

Führen Sie folgenden Befehl auf Ihrem lokalen Computer aus, um die Google Cloud CLI zu aktualisieren:

gcloud components update

Variablen einrichten

Legen Sie die folgenden Variablen fest, sodass Sie Code mit konsistenten Werten kopieren und einfügen können, wenn Sie das Beispiel in diesem Dokument durcharbeiten. Verwenden Sie die folgenden Werte:

  • PROJECT_ID: Verwenden Sie die ID Ihres Projekts.
  • CLUSTER_NAME: Verwenden Sie den Namen des Clusters, den Sie verwenden möchten, z. B. secure-td-cluster.
  • ZONE: Verwenden Sie die Zone, in der sich der Cluster befindet.
  • GKE_CLUSTER_URL: Verwenden Sie https://container.googleapis.com/v1/projects/PROJECT_ID/locations/ZONE/clusters/CLUSTER_NAME.
  • WORKLOAD_POOL: Verwenden Sie PROJECT_ID.svc.id.goog.
  • K8S_NAMESPACE: Verwenden Sie default.
  • DEMO_CLIENT_KSA: Verwenden Sie den Namen Ihres Kubernetes-Dienstkontos für den Client.
  • DEMO_SERVER_KSA: Verwenden Sie den Namen Ihres Kubernetes-Dienstkontos.
  • PROJNUM: Verwenden Sie die Projektnummer Ihres Projekts, die Sie in der Google Cloud Console oder mit diesem Befehl ermitteln können:

    gcloud projects describe PROJECT_ID --format="value(projectNumber)"
    
  • SA_GKE: Verwenden Sie service-PROJNUM@container-engine-robot.iam.gserviceaccount.com.

  • CLUSTER_VERSION: Verwenden Sie die aktuellste verfügbare Version. Sie finden diese in den Rapid Channel-Versionshinweisen. Die erforderliche Mindestversion ist 1.21.4-gke.1801. Dies ist die GKE-Clusterversion, die in diesem Beispiel verwendet werden soll.

Legen Sie hier die Werte fest:

# Substitute your project ID
PROJECT_ID=PROJECT_ID

# GKE cluster name and zone for this example.
CLUSTER_NAME=CLUSTER_NAME
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=K8S_NAMESPACE
DEMO_CLIENT_KSA=DEMO_CLIENT_KSA
DEMO_SERVER_KSA=DEMO_SERVER_KSA

# Compute other values
# Project number for your project
PROJNUM=PROJNUM

CLUSTER_VERSION=CLUSTER_VERSION
SA_GKE=service-PROJNUM@container-engine-robot.iam.gserviceaccount.com

APIs aktivieren

Verwenden Sie den gcloud services enable. Befehl zum Aktivieren aller APIs, die Sie zum Einrichten von Cloud Service Mesh benötigen mit Certificate Authority Service.

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

GKE-Cluster erstellen oder aktualisieren

Die Sicherheit von Cloud Service Mesh-Diensten hängt von der CA Service-Einbindung in GKE ab. Der GKE-Cluster muss zusätzlich zu den Anforderungen für die Einrichtung die folgenden Anforderungen erfüllen:

  • Verwenden Sie eine Mindestclusterversion von 1.21.4-gke.1801. Wenn Sie Funktionen einer späteren Version benötigen, können Sie diese Version über den Rapid Release Channel abrufen.
  • Der GKE-Cluster muss mit Mesh-Zertifikaten aktiviert und konfiguriert sein, wie unter Zertifizierungsstellen zum Ausstellen von Zertifikaten erstellen erläutert.
  1. Erstellen Sie einen neuen Cluster, der die Workload Identity Federation for GKE verwendet. Wenn Sie einen vorhandenen Cluster aktualisieren, fahren Sie mit dem nächsten Schritt fort. Der Wert, den Sie für --tags angeben, muss mit dem Namen übereinstimmen, der an das Flag --target-tags für den Befehl firewall-rules create im Abschnitt Cloud Service Mesh mit Cloud Load Balancing-Komponenten konfigurieren übergeben wurde.

    # 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
    

    Die Erstellung eines Clusters kann einige Minuten dauern.

  2. Wenn Sie einen vorhandenen Cluster verwenden, aktivieren Sie die Identitätsföderation von Arbeitslasten für GKE und GKE-Mesh-Zertifikate. Achten Sie darauf, dass der Cluster mit dem Flag --enable-ip-alias erstellt wurde, das nicht mit dem Befehl update verwendet werden kann.

    gcloud container clusters update CLUSTER_NAME \
      --enable-mesh-certificates
    
  3. Mit dem folgenden Befehl wechseln Sie zum neuen Cluster als Standardcluster für Ihre kubectl-Befehle:

    gcloud container clusters get-credentials CLUSTER_NAME \
      --zone ZONE
    

In einer Multi-Cluster-Umgebung bereitstellen

Wenn Sie die Bereitstellung in einer Multi-Cluster-Umgebung vornehmen, folgen Sie der in diesem Abschnitt beschriebenen allgemeinen Vorgehensweise. In dieser Anleitung wird davon ausgegangen, dass Client-Pods in einem Cluster und Server-Pods im anderen Cluster ausgeführt werden.

  1. Erstellen oder aktualisieren Sie die Cluster gemäß der Anleitung im vorherigen Abschnitt.

  2. Erfassen Sie mit dem folgenden Befehl die Pod-IP-Adressbereiche für jeden Cluster:

    gcloud compute firewall-rules list \
      --filter="name~gke-{CLUSTER_NAME}-[0-9a-z]*-all" \
      --format="value(sourceRanges)"
    

    Für Cluster mit dem Namen cluster-a und cluster-b geben die Befehle beispielsweise Ergebnisse wie die folgenden zurück:

    cluster-a, pod CIDR: 10.4.0.0/14, node network tag: gke-cluster-a-9cd18751-node
    cluster-b, pod CIDR: 10.8.0.0/14, node network tag: gke-cluster-b-acd14479-node
    
  3. Erstellen Sie VPC-Firewallregeln, die den Clustern ermöglichen, miteinander zu kommunizieren. Mit dem folgenden Befehl wird beispielsweise eine Firewallregel erstellt, die es den Pod-IP-Adressen cluster-a ermöglicht, mit cluster-b-Knoten zu kommunizieren:

    gcloud compute firewall-rules create per-cluster-a-pods \
      --allow="tcp,udp,icmp,esp,ah,sctp" \
      --target-tags="gke-cluster-b-acd14479-node"
    

    Mit dem folgenden Befehl wird eine Firewallregel erstellt, die es den cluster-b-Pod-IP-Adressen ermöglicht, mit cluster-a-Knoten zu kommunizieren:

    gcloud compute firewall-rules create per-cluster-b-pods \
      --allow="tcp,udp,icmp,esp,ah,sctp" \
      --target-tags="gke-cluster-a-9cd18751-node"
    

Cluster bei einer Flotte registrieren

Registrieren Sie den Cluster, den Sie unter GKE-Cluster erstellen erstellt oder aktualisiert haben bei einer Flotte. Durch Registrierung des Clusters lässt sich die projektübergreifende Konfiguration von Clustern vereinfachen.

Die Ausführung dieser Schritte kann bis zu zehn Minuten dauern.

  1. Registrieren Sie Ihren Cluster bei der Flotte:

    gcloud container fleet memberships register CLUSTER_NAME \
      --gke-cluster=ZONE/CLUSTER_NAME \
      --enable-workload-identity --install-connect-agent \
      --manifest-output-file=MANIFEST-FILE_NAME
    

    Ersetzen Sie dabei folgende Variablen:

    • CLUSTER_NAME: Der Name Ihres Clusters.
    • ZONE: Die Zone Ihres Clusters.
    • MANIFEST-FILE_NAME: Der Pfad, unter dem diese Befehle das Manifest für die Registrierung generieren.

    Nach erfolgreicher Registrierung wird eine Meldung wie die folgende angezeigt:

    Finished registering the cluster CLUSTER_NAME with the fleet.
  2. Wenden Sie die generierte Manifestdatei auf Ihren Cluster an:

    kubectl apply -f MANIFEST-FILE_NAME
    

    Wenn der Anwendungsprozess erfolgreich ist, werden Meldungen wie die folgenden angezeigt:

    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
    
  3. Rufen Sie die Mitgliedschaftsressource aus dem Cluster ab:

    kubectl get memberships membership -o yaml
    

    Die Ausgabe sollte den Workload Identity-Pool enthalten, der von der Flotte zugewiesen wurde, wobei PROJECT_ID Ihre Projekt-ID ist:

    workload_identity_pool: PROJECT_ID.svc.id.goog
    

    Das bedeutet, dass der Cluster erfolgreich registriert wurde.

Zertifizierungsstellen zum Ausstellen von Zertifikaten erstellen

Wenn Sie Zertifikate an Ihre Pods ausstellen möchten, erstellen Sie einen CA Service-Pool und die folgenden Zertifizierungsstellen (Certificate Authorities, CA):

  • Stamm-CA. Dies ist der Root of Trust für alle ausgestellten Mesh-Zertifikate. Sie können eine vorhandene Stamm-CA verwenden, sofern vorhanden. Erstellen Sie die Stamm-CA auf der Ebene enterprise, die für die Ausgabe von langlebigen Zertifikaten mit geringem Volumen vorgesehen ist.
  • Untergeordnete CA. Diese Zertifizierungsstelle stellt Zertifikate für Arbeitslasten aus. Erstellen Sie die untergeordnete CA in der Region, in der Ihr Cluster bereitgestellt wird. Erstellen Sie die untergeordnete Zertifizierungsstelle (Certificate Authority, CA) auf der Ebene devops, die für die Ausstellung von kurzlebigen Zertifikaten mit hohem Volumen vorgesehen ist.

Das Erstellen einer untergeordneten CA ist optional. Wir empfehlen aber dringend, eine solche Zertifizierungsstelle zu verwenden, anstatt zum Ausstellen von GKE-Mesh-Zertifikaten Ihre Stamm-CA zu nutzen. Wenn Sie die Stamm-CA zum Ausstellen von Mesh-Zertifikaten verwenden, achten Sie darauf, dass der standardmäßige konfigurationsbasierte Ausstellungsmodus zulässig ist.

Die untergeordnete Zertifizierungsstelle kann sich in einer anderen Region als der Cluster befinden. Es wird jedoch dringend empfohlen, sie in der Region zu erstellen, in der sich auch Ihr Cluster befindet, um die Leistung zu optimieren. Stamm- und untergeordnete CAs können sich Sie dagegen in verschiedenen Regionen befinden. Die Leistung oder Verfügbarkeit wird damit nicht beeinträchtigt.

CA Service wird in diesen Regionen unterstützt:

Name der Region Beschreibung der Region
asia-east1 Taiwan
asia-east2 Hongkong
asia-northeast1 Tokio
asia-northeast2 Osaka
asia-northeast3 Seoul
asia-south1 Mumbai
asia-south2 Delhi
asia-southeast1 Singapur
asia-southeast2 Jakarta
australia-southeast1 Sydney
australia-southeast2 Melbourne
europe-central2 Warschau
europe-north1 Finnland
europe-southwest1 Madrid
europe-west1 Belgien
europe-west2 London
europe-west3 Frankfurt
europe-west4 Niederlande
europe-west6 Zürich
europe-west8 Mailand
europe-west9 Paris
europe-west10 Berlin
europe-west12 Turin
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 South Carolina
us-east4 Northern Virginia
us-east5 Columbus
us-south1 Dallas
us-west1 Oregon
us-west2 Los Angeles
us-west3 Salt Lake City
us-west4 Las Vegas

Die Liste der unterstützten Standorte können Sie auch mit folgendem Befehl prüfen:

gcloud privateca locations list
  1. Weisen Sie den Personen, die einen CA-Pool und eine CA erstellen, die IAM-Rolle roles/privateca.caManager zu. Beachten Sie, dass für MEMBER das korrekte Format so lautet: user:userid@example.com. Wenn diese Person der aktuelle Nutzer ist, können Sie die aktuelle Nutzer-ID mit dem Shell-Befehl $(gcloud auth list --filter=status:ACTIVE --format="value(account)") abrufen.

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=MEMBER \
      --role=roles/privateca.caManager
    
  2. Weisen Sie die Rolle role/privateca.admin für CA Service Personen zu, die IAM-Richtlinien ändern müssen, wobei MEMBER eine Person ist, die diesen Zugriff benötigt, insbesondere Personen, die die folgenden Schritte ausführen, welche die Rollen privateca.auditor und privateca.certificateManager gewähren:

    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=MEMBER \
      --role=roles/privateca.admin
    
  3. Erstellen Sie einen Stamm-CA-Service-Pool.

    gcloud privateca pools create ROOT_CA_POOL_NAME \
      --location ROOT_CA_POOL_LOCATION \
      --tier enterprise
    
  4. Erstellen Sie eine Stamm-CA.

    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
    

    Verwenden Sie für diese Demoeinrichtung die folgenden Werte für die Variablen:

    • ROOT_CA_POOL_NAME=td_sec_pool
    • ROOT_CA_NAME=pkcs2-ca
    • ROOT_CA_POOL_LOCATION=us-east1
    • ROOT_CA_ORGANIZATION="TestCorpLLC"
  5. Erstellen Sie einen untergeordneten Pool und eine untergeordnete CA. Achten Sie darauf, dass der konfigurationsbasierte Standardausstellungsmodus weiterhin zulässig ist.

    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
    

    Verwenden Sie für diese Demoeinrichtung die folgenden Werte für die Variablen:

    • 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
  6. Weisen Sie die IAM-Rolle privateca.auditor für die Stamm-CA zu, um den Zugriff vom GKE-Dienstkonto zuzulassen:

    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"
    
  7. Weisen Sie der untergeordneten CA die IAM-Rolle privateca.certificateManager zu, um den Zugriff vom GKE-Dienstkonto zuzulassen:

    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"
    
  8. Speichern Sie die folgende WorkloadCertificateConfig-YAML-Konfiguration, um für Ihren Cluster festzulegen, wie Mesh-Zertifikate ausgegeben werden:

    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
    
    

    Dabei gilt:

    • Die Projekt-ID des Projekts, in dem der Cluster ausgeführt wird.
      PROJECT_ID
    • Der voll qualifizierte URI der Zertifizierungsstelle, die Ihre Mesh-Zertifikate ausstellt (ISSUING_CA_POOL_URI). Dies kann entweder die untergeordnete CA (empfohlen) oder die Stamm-CA sein. Das Format dafür ist:
      //privateca.googleapis.com/projects/PROJECT_ID/locations/SUBORDINATE_CA_POOL_LOCATION/caPools/SUBORDINATE_CA_POOL_NAME
  9. Speichern Sie die folgende TrustConfig-YAML-Konfiguration, damit Ihr Cluster weiß, wie den bereitgestellten Zertifikaten vertraut werden soll:

    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
    

    Dabei gilt:

    • Die Projekt-ID des Projekts, in dem der Cluster ausgeführt wird.
      PROJECT_ID
    • Der vollständig qualifizierte URI des Stamm-CA-Pools (ROOT_CA_POOL_URI). Das Format lautet:
      //privateca.googleapis.com/projects/PROJECT_ID/locations/ROOT_CA_POOL_LOCATION/caPools/ROOT_CA_POOL_NAME
  10. Wenden Sie die Konfigurationen auf Ihren Cluster an:

    kubectl apply -f WorkloadCertificateConfig.yaml
    kubectl apply -f TrustConfig.yaml
    

Identitäts- und Zugriffsverwaltung konfigurieren

Zum Erstellen der für die Einrichtung erforderlichen Ressourcen benötigen Sie die Rolle compute.NetworkAdmin. Diese Rolle enthält alle notwendigen Berechtigungen zum Erstellen, Aktualisieren, Löschen, Auflisten und Verwenden (d. h. zum Verweisen in anderen Ressourcen) der erforderlichen Ressourcen. Wenn Sie der Inhaber-Bearbeiter Ihres Projekts sind, wurde Ihnen diese Rolle automatisch zugewiesen.

Beachten Sie, dass die networksecurity.googleapis.com.clientTlsPolicies.use und networksecurity.googleapis.com.serverTlsPolicies.use werden nicht erzwungen, wenn Sie auf diese Ressourcen im Back-End-Dienst verweisen.

Wenn diese Berechtigungen in Zukunft erzwungen werden und Sie die Rolle compute.NetworkAdmin verwenden, entstehen keine Probleme, wenn diese Prüfung erzwungen wird.

Wenn Sie benutzerdefinierte Rollen verwenden, müssen Sie die entsprechende Berechtigung .use angeben, sollte diese Prüfung in Zukunft erzwungen werden. Andernfalls werden Sie in Zukunft verfügt Ihre benutzerdefinierte Rolle möglicherweise nicht über die erforderlichen Berechtigungen um auf clientTlsPolicy oder serverTlsPolicy aus dem Back-End-Dienst zu verweisen, oder Endpunktrichtlinie.

Die folgende Anleitung ermöglicht es dem Standarddienstkonto, auf die Cloud Service Mesh Security API zuzugreifen und die Kubernetes-Dienstkonten zu erstellen.

  1. IAM so konfigurieren, dass das Standarddienstkonto Zugriff erhält der Cloud Service Mesh Security API.

    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
    
  2. Richten Sie Kubernetes-Dienstkonten ein. Die Client- und Server-Deployments in den folgenden Abschnitten verwenden die Knames der Kubernetes-Server- und Clientdienstkonten.

    kubectl create serviceaccount --namespace K8S_NAMESPACE DEMO_SERVER_KSA
    kubectl create serviceaccount --namespace K8S_NAMESPACE DEMO_CLIENT_KSA
    
  3. Erlauben Sie den Kubernetes-Dienstkonten, die Identität des standardmäßigen Compute Engine-Dienstkontos zu übernehmen, indem Sie eine IAM-Richtlinienbindung zwischen diesen beiden erstellen. Durch diese Bindung kann das Kubernetes-Dienstkonto als Compute Engine-Standarddienstkonto verwendet werden.

    gcloud iam service-accounts add-iam-policy-binding  \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:PROJECT_ID.svc.id.goog[K8S_NAMESPACE/DEMO_SERVER_KSA]" ${GSA_EMAIL}
    
    gcloud iam service-accounts add-iam-policy-binding  \
      --role roles/iam.workloadIdentityUser  \
      --member "serviceAccount:PROJECT_ID.svc.id.goog[K8S_NAMESPACE/DEMO_CLIENT_KSA]" ${GSA_EMAIL}
    
  4. Versehen Sie die Kubernetes-Dienstkonten mit Anmerkungen, um sie mit dem Compute Engine-Standarddienstkonto zu verknüpfen.

    kubectl annotate --namespace K8S_NAMESPACE \
      serviceaccount DEMO_SERVER_KSA \
      iam.gke.io/gcp-service-account=${GSA_EMAIL}
    
    kubectl annotate --namespace K8S_NAMESPACE \
      serviceaccount DEMO_CLIENT_KSA \
      iam.gke.io/gcp-service-account=${GSA_EMAIL}
    

Cloud Service Mesh einrichten

Verwenden Sie die folgenden Anleitungen, um den Sidecar-Injektor zu installieren, einen Testdienst einzurichten und andere Deployment-Aufgaben auszuführen.

Envoy-Sidecar-Injektor im Cluster installieren

Folgen Sie der Anleitung in den beiden folgenden Abschnitten der Cloud Service Mesh-Einrichtung für GKE-Pods mit automatischer Envoy-Einschleusung zum Bereitstellen und Aktivieren der Envoy-Sidecar-Einfügung in Ihrem Cluster:

Führen Sie beide Anleitungen aus, bevor Sie einen Testdienst einrichten.

Testdienst einrichten

Nach Installation des Envoy-Sidecar-Injektors richten Sie mithilfe dieser Anleitung einen Testdienst für Ihr Deployment ein.

wget -q -O -  https://storage.googleapis.com/traffic-director/security/ga/service_sample.yaml | sed -e s/DEMO_SERVER_KSA_PLACEHOLDER/DEMO_SERVER_KSA/g > service_sample.yaml

kubectl apply -f service_sample.yaml

Die Datei service_sample.yaml enthält die Pod-Spezifikation für Ihre Demoserveranwendung. Es gibt einige Annotationen, die nur für Cloud Service Mesh gelten Sicherheit.

Cloud Service Mesh-Proxy-Metadaten

Die Pod-Spezifikation gibt die Annotation proxyMetadata an:

spec:
...
      annotations:
        cloud.google.com/proxyMetadata: '{"app": "payments"}'
...

Wenn der Pod initialisiert wird, übernimmt der Sidecar-Proxy diese Annotation und überträgt sie an Cloud Service Mesh. Cloud Service Mesh kann diese Informationen dann verwenden, um eine gefilterte Konfiguration zurückzusenden:

  • Später in dieser Anleitung sehen Sie, dass die Endpunktrichtlinie einen Endpunkt-Matcher angibt.
  • Der Endpunkt-Matcher gibt an, dass nur Clients mit einem Label mit dem Namen app und dem Wert payments die gefilterte Konfiguration erhalten.

Vom CA Service signierte Mesh-Zertifikate und Schlüssel verwenden

Die Pod-Spezifikation gibt die Annotation enableManagedCerts an:

spec:
...
      annotations:
        ...
        cloud.google.com/enableManagedCerts: "true"
...

Wenn der Pod initialisiert wird, Schlüssel werden automatisch im lokalen Sidecar-Proxy-Dateisystem bereitgestellt.

Abfangport für eingehenden Traffic konfigurieren

Die Pod-Spezifikation gibt die Annotation includeInboundPorts an:

spec:
...
      annotations:
        ...
        cloud.google.com/includeInboundPorts: "8000"
...

Dies ist der Port, den die Serveranwendung auf Verbindungen überwacht. Wenn der Pod initialisiert wird, übernimmt der Sidecar-Proxy diese Annotation und überträgt sie an Cloud Service Mesh. Cloud Service Mesh kann diese Informationen dann verwenden, um Zurückgefilterte Konfiguration, die den gesamten an diesen Port eingehenden Traffic abfängt und Sicherheitsrichtlinien darauf anwenden können.

Der Systemdiagnoseport muss sich vom Anwendungsport unterscheiden. Andernfalls gelten dieselben Sicherheitsrichtlinien für eingehende Verbindungen zum Systemdiagnoseport. Dies kann dazu führen, dass die Verbindungen abgelehnt werden, was dazu führt, dass der Server fälschlicherweise als fehlerhaft gekennzeichnet wird.

GKE-Dienste mit NEGs konfigurieren

GKE-Dienste müssen über Netzwerk-Endpunktgruppen (NEGs) verfügbar gemacht werden, damit Sie sie als Back-Ends eines Cloud Service Mesh-Back-End-Dienstes konfigurieren können. Das in dieser Einrichtungsanleitung bereitgestellte Paket service_sample.yaml verwendet den NEG-Namen service-test-neg in der folgenden Annotation:

...
metadata:
  annotations:
    cloud.google.com/neg: '{"exposed_ports": {"80":{"name": "service-test-neg"}}}'
spec:
  ports:
  - port: 80
    name: service-test
    protocol: TCP
    targetPort: 8000

Sie müssen die Datei service_sample.yaml nicht ändern.

Namen der NEG speichern

Speichern Sie den Namen der NEG in der Variablen NEG_NAME:

NEG_NAME="service-test-neg"

Clientanwendung in GKE bereitstellen

Führen Sie den folgenden Befehl aus, um einen Democlient mit einem Envoy-Proxy als Sidecar zu starten. Damit müssen Sie die Sicherheitsfeatures demonstrieren.

wget -q -O -  https://storage.googleapis.com/traffic-director/security/ga/client_sample.yaml | sed -e s/DEMO_CLIENT_KSA_PLACEHOLDER/DEMO_CLIENT_KSA/g > client_sample.yaml

kubectl apply -f client_sample.yaml

Die Client-Pod-Spezifikation enthält nur die Annotation enableManagedCerts. Dies ist erforderlich, um die notwendigen Volumes für von GKE verwaltete Mesh-Zertifikate und Schlüssel bereitzustellen, die von der CA Service-Instanz signiert sind.

Ressourcen für Systemdiagnosen, Firewallregel und Back-End-Dienste konfigurieren

In diesem Abschnitt erstellen Sie Ressourcen für die Systemdiagnose, die Firewallregel und den Back-End-Dienst für Cloud Service Mesh.

  1. Erstellen Sie die Systemdiagnose:

    gcloud compute health-checks create http td-gke-health-check \
      --use-serving-port
    
  2. Erstellen Sie die Firewallregel, um IP-Adressbereiche für die Systemdiagnose zuzulassen.

    gcloud compute firewall-rules create fw-allow-health-checks \
       --action ALLOW \
       --direction INGRESS \
       --source-ranges 35.191.0.0/16,130.211.0.0/22 \
      --rules tcp
    
  3. Erstellen Sie den Back-End-Dienst und verknüpfen Sie die Systemdiagnose mit dem Back-End-Dienst.

    gcloud compute backend-services create td-gke-service \
      --global \
      --health-checks td-gke-health-check \
      --load-balancing-scheme INTERNAL_SELF_MANAGED
    
  4. Fügen Sie dem Back-End-Dienst die zuvor erstellte NEG als Back-End hinzu.

    gcloud compute backend-services add-backend td-gke-service \
      --global \
      --network-endpoint-group ${NEG_NAME} \
      --network-endpoint-group-zone ZONE \
      --balancing-mode RATE \
     --max-rate-per-endpoint 5
    

Mesh- und HTTPRoute-Ressourcen konfigurieren

In diesem Abschnitt erstellen Sie Mesh- und HTTPRoute-Ressourcen.

  1. Erstellen Sie die Ressourcenspezifikation Mesh und speichern Sie sie in einer Datei namens mesh.yaml.

    name: sidecar-mesh
    interceptionPort: 15001
    

    Der Interception-Port wird standardmäßig auf 15001 gesetzt, wenn Sie ihn im mesh.yaml-Datei.

  2. Erstellen Sie die Mesh-Ressource mit der Spezifikation mesh.yaml.

    gcloud network-services meshes import sidecar-mesh \
      --source=mesh.yaml \
      --location=global
    
  3. Erstellen Sie die Spezifikation HTTPRoute und speichern Sie sie in einer Datei mit dem Namen http_route.yaml.

    Sie können entweder PROJECT_ID oder PROJECT_NUMBER verwenden.

    name: helloworld-http-route
    hostnames:
    - service-test
    meshes:
    - projects/PROJNUM/locations/global/meshes/sidecar-mesh
    rules:
    - action:
       destinations:
       - serviceName: "projects/PROJNUM/locations/global/backendServices/td-gke-service"
    
  4. Erstellen Sie die Ressource HTTPRoute mithilfe der Spezifikation in der http_route.yaml-Datei.

    gcloud network-services http-routes import helloworld-http-route \
      --source=http_route.yaml \
      --location=global
    

Die Konfiguration des Cloud Service Mesh ist abgeschlossen und Sie können jetzt konfigurieren Authentifizierungs- und Autorisierungsrichtlinien.

Dienst-zu-Dienst-Sicherheit einrichten

Richten Sie die Sicherheit von Dienst zu Dienst mithilfe der folgenden Abschnitte ein.

mTLS im Mesh-Netzwerk aktivieren

Zum Einrichten von mTLS in Ihrem Mesh-Netzwerk müssen Sie den ausgehenden Traffic zum Backend-Dienst und eingehenden Traffic an den Endpunkt sichern.

Format für Richtlinienverweise

Beachten Sie das folgende erforderliche Format für Verweise auf Server-TLS-, Client-TLS- und Autorisierungsrichtlinien:

projects/PROJECT_ID/locations/global/[serverTlsPolicies|clientTlsPolicies|authorizationPolicies]/[server-tls-policy|client-mtls-policy|authz-policy]

Beispiel:

projects/PROJECT_ID/locations/global/serverTlsPolicies/server-tls-policy
projects/PROJECT_ID/locations/global/clientTlsPolicies/client-mtls-policy
projects/PROJECT_ID/locations/global/authorizationPolicies/authz-policy

Ausgehenden Traffic zum Backend-Dienst schützen

Zum Sichern des ausgehenden Traffics erstellen Sie zuerst eine Client-TLS-Richtlinie, die Folgendes tut:

  • Verwendet google_cloud_private_spiffe als Plug-in für clientCertificate, damit Envoy die von GKE verwalteten Mesh-Zertifikate als Clientidentität nutzt.
  • Verwendet google_cloud_private_spiffe als Plug-in für serverValidationCa, damit Envoy die von GKE verwalteten Mesh-Zertifikate zur Servervalidierung nutzt.

Als Nächstes hängen Sie die Client-TLS-Richtlinie an den Backend-Dienst an. Dies bewirkt Folgendes:

  • Wendet die Authentifizierungsrichtlinie aus der Client-TLS-Richtlinie auf ausgehende Verbindungen zu Endpunkten des Back-End-Dienstes an.
  • SAN (Subject Alternative Names) weist den Client an, die genaue Identität des Servers zu bestätigen, zu dem eine Verbindung hergestellt wird.
  1. Erstellen Sie die Client-TLS-Richtlinie in der Datei client-mtls-policy.yaml:

    name: "client-mtls-policy"
    clientCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    serverValidationCa:
    - certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    
  2. Importieren Sie die Client-TLS-Richtlinie:

    gcloud network-security client-tls-policies import client-mtls-policy \
        --source=client-mtls-policy.yaml --location=global
    
  3. Hängen Sie die Client-TLS-Richtlinie an den Back-End-Dienst an. Dadurch wird die mTLS-Authentifizierung für alle ausgehenden Anfragen vom Client an diesen Back-End-Dienst erzwungen.

    gcloud compute backend-services export td-gke-service \
        --global --destination=demo-backend-service.yaml
    

    Hängen Sie die folgenden Zeilen an demo-backend-service.yaml an:

    securitySettings:
      clientTlsPolicy: projects/PROJECT_ID/locations/global/clientTlsPolicies/client-mtls-policy
      subjectAltNames:
        - "spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_SERVER_KSA"
    
  4. Importieren Sie die Werte:

    gcloud compute backend-services import td-gke-service \
        --global --source=demo-backend-service.yaml
    
  5. Führen Sie optional den folgenden Befehl aus, um zu prüfen, ob die Anfrage fehlschlägt. Dies ist ein unerwarteter Fehler, da der Client Zertifikate vom Endpunkt erwartet, aber der Endpunkt nicht mit einer Sicherheitsrichtlinie programmiert wurde.

    # Get the name of the Podrunning Busybox.
    BUSYBOX_POD=$(kubectl get po -l run=client -o=jsonpath='{.items[0].metadata.name}')
    
    # Command to execute that tests connectivity to the service service-test.
    TEST_CMD="wget -q -O - service-test; echo"
    
    # Execute the test command on the pod.
    kubectl exec -it $BUSYBOX_POD -c busybox -- /bin/sh -c "$TEST_CMD"
    

    Die Ausgabe sieht so aus:

    wget: server returned error: HTTP/1.1 503 Service Unavailable
    

Eingehenden Traffic zum Endpunkt schützen

Erstellen Sie zuerst eine Server-TLS-Richtlinie, um den eingehenden Traffic zu sichern:

  • Verwendet google_cloud_private_spiffe als Plug-in für serverCertificate, damit Envoy die von GKE verwalteten Mesh-Zertifikate als Serveridentität nutzt.
  • Verwendet google_cloud_private_spiffe als Plug-in für clientValidationCa, damit Envoy die von GKE verwalteten Mesh-Zertifikate zur Clientvalidierung verwendet.
  1. Speichern Sie die Server-TLS-Richtlinienwerte in einer Datei mit dem Namen server-mtls-policy.yaml.

    name: "server-mtls-policy"
    serverCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    mtlsPolicy:
      clientValidationCa:
      - certificateProviderInstance:
          pluginInstance: google_cloud_private_spiffe
    
  2. Erstellen Sie die Server-TLS-Richtlinie:

    gcloud network-security server-tls-policies import server-mtls-policy \
        --source=server-mtls-policy.yaml --location=global
    
  3. Erstellen Sie eine Datei mit dem Namen ep_mtls.yaml, die den Endpunkt-Matcher enthält, und hängen Sie die Server-TLS-Richtlinie an.

    endpointMatcher:
      metadataLabelMatcher:
        metadataLabelMatchCriteria: MATCH_ALL
        metadataLabels:
        - labelName: app
          labelValue: payments
    name: "ep"
    serverTlsPolicy: projects/PROJECT_ID/locations/global/serverTlsPolicies/server-mtls-policy
    type: SIDECAR_PROXY
    
  4. Importieren Sie den Endpunkt-Matcher.

    gcloud network-services endpoint-policies import ep \
        --source=ep_mtls.yaml --location=global
    

Einrichtung validieren

Führen Sie dazu den Befehl curl aus: Wenn die Anfrage erfolgreich ist, wird x-forwarded-client-cert in der Ausgabe angezeigt. Der Header wird nur ausgegeben, wenn die Verbindung eine mTLS-Verbindung ist.

# Get the name of the Podrunning Busybox.
BUSYBOX_POD=$(kubectl get po -l run=client -o=jsonpath='{.items[0].metadata.name}')

# Command to execute that tests connectivity to the service service-test.
TEST_CMD="wget -q -O - service-test; echo"

# Execute the test command on the pod.
kubectl exec -it $BUSYBOX_POD -c busybox -- /bin/sh -c "$TEST_CMD"

Die Ausgabe sieht in etwa so aus:

GET /get HTTP/1.1
Host: service-test
content-length: 0
x-envoy-internal: true
accept: */*
x-forwarded-for: 10.48.0.6
x-envoy-expected-rq-timeout-ms: 15000
user-agent: curl/7.35.0
x-forwarded-proto: http
x-request-id: redacted
x-forwarded-client-cert: By=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_SERVER_KSA;Hash=Redacted;Subject="Redacted;URI=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_KSA

Der Header x-forwarded-client-cert wird vom serverseitigen Envoy eingefügt und enthält seine eigene Identität (Server) und die Identität des Quellclients. Da wir sowohl die Client- als auch die Serveridentitäten sehen, ist dies ein Signal für eine mTLS-Verbindung.

Zugriff auf Dienstebene mit einer Autorisierungsrichtlinie konfigurieren

In dieser Anleitung wird eine Autorisierungsrichtlinie erstellt, mit der Anfragen vom DEMO_CLIENT_KSA-Konto zugelassen werden, in denen der Hostname service-test lautet, der Port 8000 ist und die HTTP-Methode GET lautet. Informieren Sie sich vor dem Erstellen von Autorisierungsrichtlinien über die Warnung unter Zugriff mithilfe der Autorisierung einschränken.

  1. Erstellen Sie eine Autorisierungsrichtlinie, indem Sie eine Datei mit dem Namen authz-policy.yaml erstellen.

    action: ALLOW
    name: authz-policy
    rules:
    - sources:
      - principals:
        - spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_KSA
      destinations:
      - hosts:
        - service-test
        ports:
        - 8000
        methods:
        - GET
    
  2. Importieren Sie die Richtlinie:

    gcloud network-security authorization-policies import authz-policy \
      --source=authz-policy.yaml \
      --location=global
    
  3. Aktualisieren Sie die Endpunktrichtlinie so, dass sie auf die neue Autorisierungsrichtlinie verweist. Hängen Sie dazu Folgendes an die Datei ep_mtls.yaml an:

    authorizationPolicy: projects/PROJECT_ID/locations/global/authorizationPolicies/authz-policy
    

    Die Endpunktrichtlinie gibt jetzt an, dass sowohl mTLS als auch die Autorisierungsrichtlinie für eingehende Anfragen an Pods erzwungen werden müssen, deren Envoy-Sidecar-Proxys das Label app:payments haben.

  4. Importieren Sie die Richtlinie:

    gcloud network-services endpoint-policies import ep \
        --source=ep_mtls.yaml --location=global
    

Einrichtung validieren

Führen Sie die folgenden Befehle aus, um die Einrichtung zu validieren.

# Get the name of the Podrunning Busybox.
BUSYBOX_POD=$(kubectl get po -l run=client -o=jsonpath='{.items[0].metadata.name}')

# Command to execute that tests connectivity to the service service-test.
# This is a valid request and will be allowed.
TEST_CMD="wget -q -O - service-test; echo"

# Execute the test command on the pod.
kubectl exec -it $BUSYBOX_POD -c busybox -- /bin/sh -c "$TEST_CMD"

Die erwartete Ausgabe sieht in etwa so aus:

GET /get HTTP/1.1
Host: service-test
content-length: 0
x-envoy-internal: true
accept: */*
x-forwarded-for: redacted
x-envoy-expected-rq-timeout-ms: 15000
user-agent: curl/7.35.0
x-forwarded-proto: http
x-request-id: redacted
x-forwarded-client-cert: By=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_SERVER_KSA;Hash=Redacted;Subject="Redacted;URI=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_KSA

Führen Sie die folgenden Befehle aus, um zu testen, ob die Autorisierungsrichtlinie ungültige Anfragen korrekt ablehnt:

# Failure case
# Command to execute that tests connectivity to the service service-test.
# This is an invalid request and server will reject because the server
# authorization policy only allows GET requests.
TEST_CMD="wget -q -O - service-test --post-data='' ; echo"

# Execute the test command on the pod.
kubectl exec -it $BUSYBOX_POD -c busybox -- /bin/sh -c "$TEST_CMD"

Die erwartete Ausgabe sieht in etwa so aus:

<RBAC: access denied HTTP/1.1 403 Forbidden>

Autorisierungsrichtlinien für Sidecars in GKE einrichten

In diesem Abschnitt erfahren Sie, wie Sie verschiedene Arten von Autorisierungsrichtlinien für Cloud Service Mesh-Sidecars in GKE einrichten.

Bevor Sie eine Autorisierungsrichtlinie erstellen können, müssen Sie die GCPAuthzPolicy-CustomResourceDefinition (CRD) installieren:

curl https://github.com/GoogleCloudPlatform/gke-networking-recipes/blob/main/gateway-api/config/mesh/crd/experimental/gcpauthzpolicy.yaml \
| kubectl apply -f -

Autorisierungsrichtlinie zum Ablehnen von Anfragen

Wenn Sie eine Arbeitslast haben, die nur ausgehende Anrufe tätigen soll, z. B. eine Cronjobs können Sie eine Autorisierungsrichtlinie so konfigurieren, dass eingehende HTTP-Anfragen an die Arbeitslast senden. Im folgenden Beispiel werden eingehende HTTP-Anfragen an die Arbeitslast example-app abgelehnt.

Führen Sie die folgenden Schritte aus, um die Autorisierungsrichtlinie „Deny“ (Ablehnen) zu erstellen und anzuwenden:

  1. Erstellen Sie eine benutzerdefinierte Richtlinie, indem Sie eine Datei mit dem Namen deny-all-authz-policy.yaml erstellen:

    cat >deny-all-authz-policy.yaml <<EOF
    apiVersion: networking.gke.io/v1
    kind: GCPAuthzPolicy
    metadata:
      name: my-workload-authz
      namespace: ns1
    spec:
    targetRefs:
    - kind: Deployment
      name: example-app
    httpRules:
    - to:
        operations:
        - paths:
          - type: Prefix
            value: "/"
    action: DENY
    EOF
    
  2. Wenden Sie die Richtlinie an:

    kubectl apply -f deny-all-authz-policy.yaml
    

Autorisierungsrichtlinie zum Zulassen von Anfragen

Sie können auch eine Zulassungsrichtlinie konfigurieren, sodass nur Anfragen zugelassen werden, die einer und die übrigen ablehnen. Im folgenden Beispiel wird ein Autorisierungsrichtlinie für das example-app-Deployment, um nur mTLS-Anfragen zuzulassen von Pods mit der Identität spiffee://cluster.local/ns1/pod1.

Führen Sie die folgenden Schritte aus, um die Autorisierungsrichtlinie „Zulassen“ zu erstellen und anzuwenden:

  1. Erstellen Sie eine benutzerdefinierte Richtlinie, indem Sie eine Datei mit dem Namen allow-authz-policy.yaml erstellen:

    cat >allow-authz-policy.yaml <<EOF
    apiVersion: networking.gke.io/v1
    kind: GCPAuthzPolicy
    metadata:
      name: my-workload-authz
      namespace: ns1
    spec:
    targetRefs:
    - kind: Deployment
      name: example-app
    httpRules:
    - from:
        sources:
        - principals:
          - type: Exact
            value: "spiffee://cluster.local/ns1/pod1"
    action: ALLOW
    EOF
    
  2. Wenden Sie die Richtlinie an:

    kubectl apply -f allow-authz-policy.yaml
    

Ingress-Gateway-Sicherheit einrichten

In diesem Abschnitt wird davon ausgegangen, dass Sie den Abschnitt zur Sicherheit zwischen Diensten abgeschlossen haben, einschließlich der Einrichtung Ihres GKE-Clusters mit dem automatischen Sidecar-Injektor, der Erstellung einer Zertifizierungsstelle und der Erstellung einer Endpunktrichtlinie.

In diesem Abschnitt stellen Sie einen Envoy-Proxy als Ingress-Gateway bereit, das TLS-Verbindungen beendet und Anfragen von den internen Clients eines Clusters autorisiert.

TLS an einem Ingress-Gateway beenden (zum Vergrößern klicken)
TLS an einem Ingress-Gateway beenden (zum Vergrößern klicken)

So richten Sie ein Ingress-Gateway zum Beenden von TLS ein:

  1. Stellen Sie einen Kubernetes-Dienst bereit, der über eine interne Cluster-IP-Adresse erreichbar ist.
    1. Die Bereitstellung besteht aus einem eigenständigen Envoy-Proxy, der als Kubernetes-Dienst und stellt eine Verbindung zu Cloud Service Mesh her.
  2. Erstellen Sie eine Server-TLS-Richtlinie, um TLS zu beenden.
  3. Erstellen Sie eine Autorisierungsrichtlinie, um eingehende Anfragen zu autorisieren.

Ingress-Gateway-Dienst für GKE bereitstellen

Führen Sie den folgenden Befehl aus, um den Ingress-Gateway-Dienst in GKE bereitzustellen:

wget -q -O -  https://storage.googleapis.com/traffic-director/security/ga/gateway_sample_xdsv3.yaml | sed -e s/PROJECT_NUMBER_PLACEHOLDER/PROJNUM/g | sed -e s/NETWORK_PLACEHOLDER/default/g | sed -e s/DEMO_CLIENT_KSA_PLACEHOLDER/DEMO_CLIENT_KSA/g > gateway_sample.yaml

kubectl apply -f gateway_sample.yaml

Die Datei gateway_sample.yaml ist die Spezifikation für das Ingress-Gateway. In den folgenden Abschnitten werden einige Ergänzungen der Spezifikation beschrieben.

Cloud Service Mesh-Sidecar-Einfügung deaktivieren

Die Spezifikation gateway_sample.yaml stellt einen Envoy-Proxy als einzigen Container bereit. In den vorherigen Schritten wurde Envoy als Sidecar in einen Anwendungscontainer eingefügt. Sie können die Sidecar-Injektion für diesen Kubernetes-Dienst mit der folgenden Anweisung deaktivieren, damit Anfragen nicht von mehreren Envoys verarbeitet werden:

sidecar.istio.io/inject: "false"

Das richtige Volume bereitstellen

Die Spezifikation gateway_sample.yaml stellt das Volume gke-workload-certificates bereit. Dieses Volume wird auch bei der Sidecar-Bereitstellung verwendet, aber es wird automatisch vom Sidecar-Injektor hinzugefügt, wenn die Annotation cloud.google.com/enableManagedCerts: "true" erkannt wird. Das Volume gke-workload-certificates enthält die von GKE verwalteten SPIFFE-Zertifikate und -Schlüssel, die von der eingerichteten CA Service-Instanz signiert werden.

Interne IP-Adresse des Clusters festlegen

Konfigurieren Sie das Ingress-Gateway mit einem Dienst vom Typ ClusterInternal. Dadurch wird ein intern auflösbarer DNS-Hostname für mesh-gateway erstellt. Wenn ein Client eine Anfrage an mesh-gateway:443 sendet, leitet Kubernetes die Anfrage sofort an den Port 8080 der Ingress-Gateway-Bereitstellung weiter.

TLS für ein Ingress-Gateway aktivieren

Folgen Sie dieser Anleitung, um TLS für ein Ingress-Gateway zu aktivieren.

  1. Erstellen Sie eine Server-TLS-Richtlinienressource, um TLS-Verbindungen zu beenden, mit den Werten in einer Datei mit dem Namen server-tls-policy.yaml:

    description: tls server policy
    name: server-tls-policy
    serverCertificate:
      certificateProviderInstance:
        pluginInstance: google_cloud_private_spiffe
    
  2. Importieren Sie die Server-TLS-Richtlinie:

    gcloud network-security server-tls-policies import server-tls-policy \
        --source=server-tls-policy.yaml --location=global
    
  3. Erstellen Sie ein neues Ziel Gateway und speichern Sie es in der Datei td-gke-gateway.yaml. Dadurch wird die Server-TLS-Richtlinie angehängt und das Ingress-Gateway für den Envoy-Proxy konfiguriert, um eingehenden TLS-Traffic zu beenden.

    name: td-gke-gateway
    scope: gateway-proxy
    ports:
    - 8080
    type: OPEN_MESH
    serverTLSPolicy: projects/PROJECT_ID/locations/global/serverTlsPolicies/server-tls-policy
    
  4. Importieren Sie das Gateway:

    gcloud network-services gateways import td-gke-gateway \
      --source=td-gke-gateway.yaml \
      --location=global
    
  5. Erstellen und speichern Sie einen neuen HTTPRoute mit dem Namen td-gke-route, der auf das Gateway verweist und alle Anfragen an td-gke-service weiterleitet.

    name: td-gke-route
    hostnames:
    - mesh-gateway
    gateways:
    - projects/PROJECT_NUMBER/locations/global/gateways/td-gke-gateway
    rules:
    - action:
        destinations:
        - serviceName: "projects/PROJECT_NUMBER/locations/global/backendServices/td-gke-service"
    
  6. Importieren Sie die HTTPRoute:

    gcloud network-services httproutes import td-gke-route \
      --source=td-gke-route.yaml \
      --location=global
    
    
  7. Aktualisieren Sie optional die Autorisierungsrichtlinie für die Back-Ends, um Anfragen zuzulassen, wenn alle folgenden Bedingungen erfüllt sind:

    • Anfragen von DEMO_CLIENT_KSA gesendet. Für die Bereitstellung des Ingress-Gateways wird das Dienstkonto DEMO_CLIENT_KSA verwendet.
    • Anfragen mit dem Host mesh-gateway oder service-test
    • Port: 8000

    Sie müssen diese Befehle nur ausführen, wenn Sie eine Autorisierungsrichtlinie für Ihre Back-Ends konfiguriert haben. Wenn auf dem Endpunkt keine Autorisierungsrichtlinie vorhanden ist oder keine Übereinstimmung zwischen Host- und Quellprinzipal in der Autorisierungsrichtlinie vorliegt, wird eine Anfrage ohne diesen Schritt zulässig. Fügen Sie diese Werte zu authz-policy.yaml hinzu:

    action: ALLOW
    name: authz-policy
    rules:
    - sources:
      - principals:
        - spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_KSA
      destinations:
      - hosts:
        - service-test
        - mesh-gateway
        ports:
        - 8000
        methods:
        - GET
    
  8. Importieren Sie die Richtlinie:

    gcloud network-security authorization-policies import authz-policy \
      --source=authz-policy.yaml \
      --location=global
    

Ingress-Gateway-Deployment validieren

Sie verwenden einen neuen Container mit dem Namen debug, um Anfragen an das Ingress-Gateway zu senden, um die Bereitstellung zu validieren.

In der folgenden Spezifikation behält die Annotation "sidecar.istio.io/inject":"false" der Cloud Service Mesh-Sidecar-Injektor daran, automatisch eine Sidecar-Datei einzufügen, Proxy. Es gibt kein Sidecar, um den debug-Container beim Anfragerouting zu unterstützen. Der Container muss zum Routing mit dem Ingress-Gateway verbunden sein.

Die Spezifikation enthält das Flag --no-check-certificate, das die Validierung des Serverzertifikats ignoriert. Der debug-Container verfügt nicht über die Zertifikate zur CA-Validierung, die für gültige Zertifikate erforderlich sind, die von CA Service signiert wurden und vom Ingress-Gateway zum Beenden von TLS verwendet werden.

In einer Produktionsumgebung empfehlen wir Ihnen, das CA Service-Validierungszertifikat herunterzuladen und es auf Ihrem Client bereitzustellen oder zu installieren. Entfernen Sie nach der Installation des Validierungszertifikats die Option --no-check-certificate des Befehls wget.

Führen Sie dazu diesen Befehl aus:

kubectl run -i --tty --rm debug --image=busybox --restart=Never  --overrides='{ "metadata": {"annotations": { "sidecar.istio.io/inject":"false" } } }'  -- /bin/sh -c "wget --no-check-certificate -qS -O - https://mesh-gateway; echo"

Die Ausgabe sollte in etwa so aussehen:

GET / HTTP/1.1
Host: 10.68.7.132
x-forwarded-client-cert: By=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_SERVER_KSA;Hash=Redacted;Subject="Redacted;URI=spiffe://PROJECT_ID.svc.id.goog/ns/K8S_NAMESPACE/sa/DEMO_CLIENT_KSA
x-envoy-expected-rq-timeout-ms: 15000
x-envoy-internal: true
x-request-id: 5ae429e7-0e18-4bd9-bb79-4e4149cf8fef
x-forwarded-for: 10.64.0.53
x-forwarded-proto: https
content-length: 0
user-agent: Wget

Führen Sie den folgenden Befehl für einen negativen Test aus:

# Negative test
# Expect this to fail because gateway expects TLS.
kubectl run -i --tty --rm debug --image=busybox --restart=Never  --overrides='{ "metadata": {"annotations": { "sidecar.istio.io/inject":"false" } } }'  -- /bin/sh -c "wget --no-check-certificate -qS -O - http://mesh-gateway:443/headers; echo"

Die Ausgabe sollte in etwa so aussehen:

wget: error getting response: Connection reset by peer

Führen Sie den folgenden Befehl für einen negativen Test aus:

# Negative test.
# AuthorizationPolicy applied on the endpoints expect a GET request. Otherwise
# the request is denied authorization.
kubectl run -i --tty --rm debug --image=busybox --restart=Never  --overrides='{ "metadata": {"annotations": { "sidecar.istio.io/inject":"false" } } }'  -- /bin/sh -c "wget --no-check-certificate -qS -O - https://mesh-gateway --post-data=''; echo"

Die Ausgabe sollte in etwa so aussehen:

HTTP/1.1 403 Forbidden
wget: server returned error: HTTP/1.1 403 Forbidden

Deployment löschen

Optional können Sie diese Befehle ausführen, um die Bereitstellung zu löschen, die Sie in dieser Anleitung erstellt haben.

Führen Sie den folgenden Befehl aus, um den Cluster zu löschen:

gcloud container clusters delete CLUSTER_NAME --zone ZONE --quiet

Führen Sie die folgenden Befehle aus, um die von Ihnen erstellten Ressourcen zu löschen:

gcloud compute backend-services delete td-gke-service --global --quiet
cloud compute network-endpoint-groups delete service-test-neg --zone ZONE --quiet
gcloud compute firewall-rules delete fw-allow-health-checks --quiet
gcloud compute health-checks delete td-gke-health-check --quiet
gcloud network-services endpoint-policies delete ep \
    --location=global --quiet
gcloud network-security authorization-policies delete authz-gateway-policy \
   --location=global --quiet
gcloud network-security authorization-policies delete 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

Beschränkungen

Die Sicherheit des Cloud Service Mesh-Dienstes wird nur unterstützt mit GKE Sie können die Dienstsicherheit nicht mit der Compute Engine bereitstellen.

Fehlerbehebung

Dieser Abschnitt enthält Informationen zur Behebung von Problemen, die während der Einrichtung des Sicherheitsdiensts auftreten können.

Verbindungsfehler

Wenn die Verbindung aufgrund des Fehlers upstream connect oder disconnect/reset before headers fehlschlägt, sehen Sie sich die Envoy-Logs an. Möglicherweise wird eine der folgenden Lognachrichten angezeigt:

gRPC config stream closed: 5, Requested entity was not found

gRPC config stream closed: 2, no credential token is found

Wenn Sie diese Fehler im Envoy-Log sehen, ist es möglich, dass das Dienstkonto-Token falsch bereitgestellt wurde oder eine andere audience verwendet wird oder beides.

Weitere Informationen finden Sie unter Fehlermeldungen in den Envoy-Logs weisen auf ein Konfigurationsproblem hin.

Pods nicht erstellt

Informationen zur Fehlerbehebung finden Sie unter Fehlerbehebung bei automatischen Bereitstellungen für GKE-Pods.

Envoy authentifiziert sich nicht bei Cloud Service Mesh

Wenn Envoy (envoy-proxy) eine Verbindung zu Cloud Service Mesh herstellt, um die xDS-Konfiguration abzurufen, verwendet es die Identitätsföderation von Arbeitslasten für GKE und das Standarddienstkonto der Compute Engine-VM, sofern der Bootstrap nicht geändert wurde. Wenn die Authentifizierung fehlschlägt, erreicht Envoy nicht den Bereitschaftszustand.

Cluster kann nicht mit --workload-identity-certificate-authority flag erstellt werden

Wenn dieser Fehler angezeigt wird, prüfen Sie, ob Sie die neueste Version der Google Cloud CLI ausführen:

gcloud components update

Pods verbleiben im Status „Ausstehend“

Wenn die Pods während der Einrichtung im Status "Ausstehend" verbleiben, erhöhen Sie die CPU- und Arbeitsspeicherressourcen für die Pods in der Deployment-Spezifikation.

Cluster mit dem Flag --enable-mesh-certificates kann nicht erstellt werden

Prüfen Sie, ob die neueste Version der gcloud CLI ausgeführt wird:

gcloud components update

Beachten Sie, dass das Flag --enable-mesh-certificates nur mit gcloud beta funktioniert.

Pods werden nicht gestartet

Pods, die GKE-Mesh-Zertifikate verwenden, starten möglicherweise nicht, wenn die Zertifikatbereitstellung fehlschlägt. Das kann in Situationen wie den folgenden passieren:

  • WorkloadCertificateConfig oder TrustConfig ist falsch konfiguriert oder fehlt.
  • CSRs werden nicht genehmigt.

Sie können prüfen, ob die Zertifikatbereitstellung fehlschlägt, indem Sie die Pod-Ereignisse prüfen.

  1. Prüfen Sie den Status Ihres Pods:

    kubectl get pod -n POD_NAMESPACE POD_NAME
    

    Dabei gilt:

    • POD_NAMESPACE: der Namespace Ihres Pods.
    • POD_NAME: der Name Ihres Pods.
  2. Prüfen Sie die letzten Ereignisse für den Pod:

    kubectl describe pod -n POD_NAMESPACE POD_NAME
    
  3. Wenn die Bereitstellung von Zertifikaten fehlschlägt, wird ein Ereignis mit Type=Warning, Reason=FailedMount, From=kubelet und mit einem Message-Feld angezeigt, das mit MountVolume.SetUp failed for volume "gke-workload-certificates" beginnt. Das Feld Message enthält Informationen zur Fehlerbehebung.

    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)
    
  4. Führen Sie die folgenden Schritte zur Fehlerbehebung aus, wenn die Pods nicht starten, weil falsch konfigurierte Objekte oder abgelehnte CSRs vorliegen.

WorkloadCertificateConfig oder TrustConfig ist falsch konfiguriert

Prüfen Sie, ob die WorkloadCertificateConfig- und TrustConfig-Objekte korrekt erstellt wurden. Sie können Fehlkonfigurationen für eines dieser Objekte mit kubectl diagnostizieren.

  1. Rufen Sie den aktuellen Status ab.

    Für WorkloadCertificateConfig:

    kubectl get WorkloadCertificateConfig default -o yaml
    

    Für TrustConfig:

    kubectl get TrustConfig default -o yaml
    
  2. Prüfen Sie die Statusausgabe. Ein gültiges Objekt hat eine Bedingung mit type: Ready und status: "True".

    status:
      conditions:
      - lastTransitionTime: "2021-03-04T22:24:11Z"
        message: WorkloadCertificateConfig is ready
        observedGeneration: 1
        reason: ConfigReady
        status: "True"
        type: Ready
    

    Bei ungültigen Objekten wird stattdessen status: "False" angezeigt. Die Felder reason und message enthalten zusätzliche Informationen zur Fehlerbehebung.

CSRs sind nicht genehmigt

Wenn bei der CSR-Genehmigung ein Fehler auftritt, können Sie die Fehlerdetails in den Bedingungen type: Approved und type: Issued der CSR überprüfen.

  1. Listen Sie die relevanten CSRs mithilfe von kubectl auf:

    kubectl get csr \
      --field-selector='spec.signerName=spiffe.gke.io/spiffe-leaf-signer'
    
  2. Wählen Sie eine CSR aus, für die entweder Approved und nicht Issued gilt oder für die Approved nicht gilt.

  3. Rufen Sie mithilfe von kubectl Details zur ausgewählten CSR ab:

    kubectl get csr CSR_NAME -o yaml
    

    Ersetzen Sie CSR_NAME durch den Namen der ausgewählten CSR.

Eine gültige CSR hat eine Bedingung mit type: Approved und status: "True" und ein gültiges Zertifikat im Feld 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

Informationen zur Fehlerbehebung für ungültige CSRs werden in den Feldern message und reason angezeigt.

Anwendungen können keine ausgestellten mTLS-Anmeldedaten verwenden

  1. Prüfen Sie, ob das Zertifikat noch gültig ist:

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
    
  2. Prüfen Sie, ob der verwendete Schlüsseltyp von der Anwendung unterstützt wird.

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Public Key Algorithm" -A 3
    
  3. Prüfen Sie, ob die ausstellende Zertifizierungsstelle die gleiche Schlüsselfamilie wie der Zertifikatschlüssel verwendet.

    1. Rufen Sie den Status der CA Service-Instanz (Vorschau) ab:

      gcloud privateca ISSUING_CA_TYPE describe ISSUING_CA_NAME \
        --location ISSUING_CA_LOCATION
      

      Dabei gilt:

      • ISSUING_CA_TYPE: der ausstellende CA-Typ, der entweder subordinates oder roots sein muss.
      • ISSUING_CA_NAME: der Name der ausstellenden CA.
      • ISSUING_CA_LOCATION: die Region der ausstellenden Zertifizierungsstelle.
    2. Prüfen Sie, ob der keySpec.algorithm in der Ausgabe der gleiche Schlüsselalgorithmus ist wie der, den Sie im YAML-Manifest WorkloadCertificateConfig definiert haben. Sie erhalten folgende Ausgabe:

      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
       ...
      

Zertifikate werden abgelehnt

  1. Prüfen Sie, ob die Peer-Anwendung dasselbe Vertrauens-Bundle verwendet, um das Zertifikat zu verifizieren.
  2. Prüfen Sie, ob das Zertifikat noch gültig ist:

    cat /var/run/secrets/workload-spiffe-credentials/certificates.pem | openssl x509 -text -noout | grep "Not After"
    
  3. Prüfen Sie, ob der Clientcode regelmäßig die Anmeldedaten aus dem Dateisystem aktualisiert, wenn die Go API für das Neuladen der Anmeldedaten für gRPC nicht verwendet wird.

  4. Prüfen Sie, ob sich Ihre Arbeitslasten in derselben vertrauenswürdigen Domain wie Ihre Zertifizierungsstelle befinden. GKE-Mesh-Zertifikate unterstützen die Kommunikation zwischen Arbeitslasten in einer einzigen vertrauenswürdigen Domain.