Utiliser Workload Identity avec AWS

Cette rubrique explique comment activer Workload Identity pour vos charges de travail GKE sur AWS afin de contrôler leur accès aux ressources AWS.

Pour en savoir plus sur l'utilisation de Workload Identity avec les comptes IAM (gestion de l'authentification et des accès) Google Cloud pour contrôler l'accès aux ressources GCP, consultez Utiliser Workload Identity avec Google Cloud.

Présentation

Workload Identity utilise les autorisations IAM d'AWS pour contrôler l'accès aux ressources cloud. Avec Workload Identity, vous pouvez attribuer différents rôles IAM à chaque charge de travail. Ce contrôle précis des autorisations vous permet de suivre le principe du moindre privilège. Sans Workload Identity, vous devez attribuer des rôles IAM AWS à vos nœuds GKE sur AWS, ce qui accorde à toutes les charges de travail du nœud les mêmes autorisations que le nœud lui-même.

Pour activer Workload Identity pour votre cluster, mettez en œuvre les étapes suivantes qui sont regroupées en fonction des rôles d'administration qui les exécutent.

Administrateur du cluster

  1. Créez un bucket Cloud Storage pour stocker les données de découverte OIDC.
  2. Créez un rôle Identity and Access Management pour lire les données de ce bucket.
  3. Créez un cluster d'utilisateur avec Workload Identity activé.
  4. Créez un webhook sur votre cluster qui applique des identifiants Workload Indentity aux pods lors de la création. Si vous ne souhaitez pas utiliser le webhook, vous pouvez définir manuellement les variables d'environnement dans vos pods.
  5. Configurez le fournisseur AWS OIDC.
  6. Créez des rôles et stratégies AWS IAM.
Administrateur ou développeur de cluster
  1. Créez des comptes de service Kubernetes et associez-leur des stratégies AWS.
Développeur
  1. Appliquez des identifiants à vos pods.

Prérequis

Pour réaliser la procédure décrite dans ce document, vous devez effectuer les opérations suivantes :

  • Un service de gestion GKE sur AWS.
  • Clusters d'utilisateurs exécutant une version de Kubernetes supérieure à 1.17.9.

  • Les autorisations et outils suivants.

Autorisations

Pour créer un cluster avec Workload Identity activé, vous devez disposer des autorisations suivantes :

Google Cloud

  • Créez un bucket Cloud Storage lisible publiquement avec l'accès uniforme au niveau du bucket activé.
  • Accordez des autorisations de lecture/écriture à management-sa@PROJECT_NAME.iam.gserviceaccount.com sur le bucket.

AWS

  • Créer un fournisseur AWS OIDC
  • Créer des rôles AWS IAM

Outils

Sur votre ordinateur local, nous vous recommandons d'installer l'outil jq.

Créer le bucket de découverte OIDC

Cette section s'adresse aux administrateurs de cluster.

Votre cluster d'utilisateur doit stocker les données de découverte OIDC dans un bucket Cloud Storage accessible publiquement. Le bucket inclut une configuration de découverte et des clés publiques OIDC. AWS utilise le contenu pour authentifier les requêtes de vos clusters d'utilisateurs.

Votre bucket doit comporter les attributs suivants :

Si vous n'avez pas de bucket avec ces attributs, créez-en un à l'aide des commandes gsutil suivantes :

BUCKET=BUCKET_NAME
gsutil mb -b on gs://${BUCKET}
gsutil iam ch allUsers:objectViewer gs://${BUCKET}

Remplacez BUCKET_NAME par le nom de votre nouveau bucket.

Accorder des autorisations au compte de service de gestion

Le compte de service Identity and Access Management pour le service de gestion de GKE sur AWS nécessite des autorisations pour lire et écrire des objets dans ce bucket.

  1. Accordez les autorisations de votre compte de service de gestion à l'aide de la commande gsutil suivante.

    MANAGEMENT_SA=management-sa@PROJECT_NAME.iam.gserviceaccount.com
    gsutil iam ch serviceAccount:${MANAGEMENT_SA}:admin gs://${BUCKET}
    

    Remplacez PROJECT_NAME par votre projet Google Cloud.

  2. Créez un rôle IAM doté des autorisations nécessaires pour gérer ce bucket. Pour créer le rôle, commencez par enregistrer la définition du rôle dans un fichier, puis créez le rôle et associez-le à votre compte de service de gestion.

    Pour effectuer ces étapes, exécutez les commandes suivantes :

    cat << EOF >  anthos-oidc-role.yaml
    title: anthosAwsOidcStorageAdmin
    description: permissions to manage the OIDC buckets
    stage: GA
    includedPermissions:
    - storage.buckets.get
    EOF
    
    gcloud iam roles create anthosAwsOidcStorageAdmin --project=PROJECT_NAME \
      --file=anthos-oidc-role.yaml
    
    gcloud projects add-iam-policy-binding \
      PROJECT_NAME \
      --member=serviceAccount:${MANAGEMENT_SA} \
      --role=projects/PROJECT_NAME/roles/anthosAwsOidcStorageAdmin
    

    Remplacez PROJECT_NAME par votre projet Google Cloud.

    Google Cloud CLI confirme la création de la liaison de stratégie.

Créer un cluster d'utilisateur

Cette section s'adresse aux administrateurs de cluster.

Créer un cluster d'utilisateur avec Workload Identity activé

Créez un cluster d'utilisateur contenant des détails sur votre bucket de découverte OIDC. Vous définissez ces informations dans le champ spec.controlPlane.workloadIdentity.oidcDiscoveryGCSBucket de votre fichier AWSCluster.

Dans cet exemple, vous créez un cluster manuellement à partir des objets CRD AWSCluster et AWSNodePool.

  1. Accédez au répertoire contenant votre configuration GKE sur AWS. Vous avez créé ce répertoire lors de l'installation du service de gestion.

    cd anthos-aws

  2. À partir de votre répertoire anthos-aws, utilisez anthos-gke pour basculer vers le contexte de votre service de gestion.

    cd anthos-aws
    anthos-gke aws management get-credentials

  3. Ouvrez un éditeur de texte et copiez la définition AWSCluster suivante dans un fichier nommé custom-cluster.yaml.

    apiVersion: multicloud.cluster.gke.io/v1
    kind: AWSCluster
    metadata:
      name: CLUSTER_NAME
    spec:
      region: AWS_REGION
      networking:
        vpcID: VPC_ID
        podAddressCIDRBlocks: POD_ADDRESS_CIDR_BLOCKS
        serviceAddressCIDRBlocks: SERVICE_ADDRESS_CIDR_BLOCKS
        ServiceLoadBalancerSubnetIDs: SERVICE_LOAD_BALANCER_SUBNETS
      controlPlane:
        version:  CLUSTER_VERSION # Latest version is 1.25.5-gke.2100
        instanceType: AWS_INSTANCE_TYPE
        keyName: SSH_KEY_NAME
        subnetIDs:
        - CONTROL_PLANE_SUBNET_IDS
        securityGroupIDs:
        - CONTROL_PLANE_SECURITY_GROUPS
        iamInstanceProfile: CONTROL_PLANE_IAM_ROLE
        rootVolume:
          sizeGiB: ROOT_VOLUME_SIZE
          volumeType: ROOT_VOLUME_TYPE # Optional
          iops: ROOT_VOLUME_IOPS # Optional
          kmsKeyARN: ROOT_VOLUME_KEY # Optional
        etcd:
          mainVolume:
            sizeGiB: ETCD_VOLUME_SIZE
            volumeType: ETCD_VOLUME_TYPE # Optional
            iops: ETCD_VOLUME_IOPS # Optional
            kmsKeyARN: ETCD_VOLUME_KEY # Optional
        databaseEncryption:
          kmsKeyARN: ARN_OF_KMS_KEY
        hub: # Optional
          membershipName: ANTHOS_CONNECT_NAME
        cloudOperations: # Optional
          projectID: YOUR_PROJECT
          location: GCP_REGION
          enableLogging: ENABLE_LOGGING
          enableMonitoring: ENABLE_MONITORING
        workloadIdentity: # Optional
          oidcDiscoveryGCSBucket: WORKLOAD_IDENTITY_BUCKET
    

    Remplacez l'élément suivant :

    • CLUSTER_NAME : nom du cluster
    • AWS_REGION : région AWS dans laquelle le cluster s'exécute.

    • VPC_ID : ID du VPC dans lequel votre cluster s'exécute.

    • POD_ADDRESS_CIDR_BLOCKS : plage d'adresses IPv4 utilisées par les pods du cluster. Actuellement, une seule plage est acceptée. La plage ne doit chevaucher aucun sous-réseau accessible depuis votre réseau. Vous pouvez utiliser la même plage en toute sécurité sur plusieurs objets AWSCluster différents. Exemple :10.2.0.0/16

    • SERVICE_ADDRESS_CIDR_BLOCKS : plage d'adresses IPv4 utilisées par les services du cluster. Actuellement, une seule plage est acceptée. La plage ne doit chevaucher aucun sous-réseau accessible depuis votre réseau. Vous pouvez utiliser la même plage en toute sécurité sur plusieurs objets AWSCluster différents. Exemple :10.1.0.0/16

    • SERVICE_LOAD_BALANCER_SUBNETS : ID de sous-réseau où GKE sur AWS peut créer des équilibreurs de charge publics ou privés.

    • CLUSTER_VERSION : version de Kubernetes compatible avec GKE sur AWS. La version la plus récente est 1.25.5-gke.2100.

    • AWS_INSTANCE_TYPE : type d'instance EC2 compatible.

    • SSH_KEY_NAME : paire de clé AWS EC2.

    • CONTROL_PLANE_SUBNET_IDS : ID de sous-réseau dans les zones de disponibilité où vos instances de plan de contrôle sont exécutées.

    • CONTROL_PLANE_SECURITY_GROUPS : ID de groupe de sécurité créé lors de l'installation du service de gestion. Vous pouvez personnaliser ce paramètre en ajoutant tous les identifiants de groupe de sécurité requis pour la connexion au plan de contrôle.

    • CONTROL_PLANE_IAM_PROFILE : nom du profil d'instance AWS EC2 attribué aux instances dupliquées du plan de contrôle.

    • ROOT_VOLUME_SIZE : taille, en gibioctet (Gio) des volumes racines de votre plan de contrôle.

    • ROOT_VOLUME_TYPE par le type de volume EBS. Par exemple, gp3.

    • ROOT_VOLUME_IOPS par le nombre d'opérations d'E/S par seconde (IOPS) provisionné pour le volume. Valable uniquement lorsque la valeur de volumeType est GP3. Pour plus d'informations, consultez la section Volumes SSD à usage général (gp3).

    • ROOT_VOLUME_KEY par le nom de ressource Amazon de la clé KMS AWS qui chiffre les volumes racine de votre instance de plan de contrôle.

    • ETCD_VOLUME_SIZE : taille des volumes utilisés par etcd.

    • ETCD_VOLUME_TYPE par le type de volume EBS. Par exemple, gp3.

    • ETCD_VOLUME_IOPS par le nombre d'opérations d'E/S par seconde (IOPS) provisionné pour le volume. Valable uniquement lorsque la valeur de volumeType est gp3. Pour plus d'informations, consultez la section Volumes SSD à usage général (gp3).

    • ETCD_VOLUME_KEY par le nom de ressource Amazon de la clé KMS AWS qui chiffre les volumes de données etcd de votre plan de contrôle.

    • ARN_OF_KMS_KEY : clé AWS KMS utilisée pour chiffrer les secrets du cluster.

    • ANTHOS_CONNECT_NAME : nom d'appartenance Connect utilisé pour enregistrer votre cluster. Le nom de l'appartenance doit être unique. Par exemple, projects/YOUR_PROJECT/locations/global/memberships/CLUSTER_NAME, où YOUR_PROJECT est votre projet Google Cloud et CLUSTER_NAME est un nom unique dans votre projet. Ce champ est facultatif.

    • YOUR_PROJECT : ID de votre projet.

    • GCP_REGION : région Google Cloud dans laquelle vous souhaitez stocker les journaux. Choisissez une région proche de la région AWS. Pour plus d'informations, consultez la section Emplacements mondiaux – Régions et zones. Vous pouvez, par exemple, opter pour la région us-central1.

    • ENABLE_LOGGING : true ou false, pour indiquer si Cloud Logging doit être activé ou non sur les nœuds du plan de contrôle.

    • ENABLE_MONITORING : true ou false, pour indiquer si Cloud Monitoring doit être activé ou non sur les nœuds du plan de contrôle.

    • WORKLOAD_IDENTITY_BUCKET : nom du bucket Cloud Storage contenant vos informations de découverte Workload Identity. Ce champ est facultatif.

  4. Créez un ou plusieurs pools AWSNodePools pour votre cluster. Ouvrez un éditeur de texte et copiez la définition AWSCluster suivante dans un fichier nommé custom-nodepools.yaml.

    apiVersion: multicloud.cluster.gke.io/v1
    kind: AWSNodePool
    metadata:
      name: NODE_POOL_NAME
    spec:
      clusterName: AWSCLUSTER_NAME
      version:  CLUSTER_VERSION # latest version is 1.25.5-gke.2100
      region: AWS_REGION
      subnetID: AWS_SUBNET_ID
      minNodeCount: MINIMUM_NODE_COUNT
      maxNodeCount: MAXIMUM_NODE_COUNT
      maxPodsPerNode: MAXIMUM_PODS_PER_NODE_COUNT
      instanceType: AWS_NODE_TYPE
      keyName: KMS_KEY_PAIR_NAME
      iamInstanceProfile: NODE_IAM_PROFILE
      proxySecretName: PROXY_SECRET_NAME
      rootVolume:
        sizeGiB: ROOT_VOLUME_SIZE
        volumeType: VOLUME_TYPE # Optional
        iops: IOPS # Optional
        kmsKeyARN: NODE_VOLUME_KEY # Optional 
    

    Remplacez l'élément suivant :

    • NODE_POOL_NAME : un nom unique pour votre pool AWSNodePool ;
    • AWSCLUSTER_NAME : nom du cluster AWSCluster. Exemple : staging-cluster.
    • CLUSTER_VERSION : une version Kubernetes GKE sur AWS compatible.
    • AWS_REGION : même région AWS que votre AWSCluster.
    • AWS_SUBNET_ID : sous-réseau AWS situé dans la même région que votre cluster AWS.
    • MINIMUM_NODE_COUNT : nombre minimal de nœuds dans le pool de nœuds. Pour en savoir plus, consultez la page Procéder au scaling des clusters d'utilisateur.
    • MAXIMUM_NODE_COUNT : nombre maximal de nœuds dans le pool de nœuds.
    • MAXIMUM_PODS_PER_NODE_COUNT : nombre maximal de pods que GKE sur AWS peut attribuer à un nœud.
    • AWS_NODE_TYPE : un type d'instance AWS EC2.
    • KMS_KEY_PAIR_NAME : Paire de clés KMS AWS attribuée à chaque nœud de calcul de pool de nœuds.
    • NODE_IAM_PROFILE : Nom du profil d'instance AWS EC2 attribué aux nœuds du pool.
    • ROOT_VOLUME_SIZE : taille, en gibioctet (Gio) des volumes racines de votre plan de contrôle.
    • VOLUME_TYPE : type de volume EBS AWS du nœud. Par exemple, gp3.
    • IOPS : nombre d'opérations d'E/S par seconde (IOPS) provisionné pour les volumes. Valable uniquement lorsque la valeur de volumeType est gp3.
    • NODE_VOLUME_KEY : ARN de la clé KMS AWS utilisée pour chiffrer le volume. Pour plus d'informations, consultez la page Utiliser des clés gérées par le client (CMK) pour chiffrer des volumes.
  5. Appliquez les fichiers manifeste à votre service de gestion.

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl apply -f custom-cluster.yaml
    env HTTPS_PROXY=http://localhost:8118 \
      kubectl apply -f custom-nodepools.yaml
    

Créer un fichier kubeconfig

Pendant le démarrage de votre cluster d'utilisateur, vous pouvez créer un contexte kubeconfig pour votre nouveau cluster d'utilisateur. Vous utilisez ce contexte pour vous authentifier auprès d'un utilisateur ou d'un cluster de gestion.

  1. Utilisez anthos-gke aws clusters get-credentials pour générer un objet kubeconfig pour votre cluster d'utilisateur dans ~/.kube/config.

    env HTTPS_PROXY=http://localhost:8118 \
      anthos-gke aws clusters get-credentials CLUSTER_NAME
    

    Remplacez CLUSTER_NAME par le nom de votre cluster. Exemple : cluster-0.

  2. Utilisez kubectl pour vous authentifier auprès de votre nouveau cluster d'utilisateur.

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl cluster-info
    

    Si votre cluster est prêt, le résultat inclut les URL des composants Kubernetes qu'il contient.

Afficher l'état de votre cluster

Le service de gestion provisionne les ressources AWS lorsque vous appliquez un élément AWSCluster ou AWSNodePool.

  1. À partir de votre répertoire anthos-aws, utilisez anthos-gke pour basculer vers le contexte de votre service de gestion.

    cd anthos-aws
    anthos-gke aws management get-credentials

  2. Pour répertorier vos clusters, utilisez kubectl get AWSClusters.

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl get AWSClusters
    

    Le résultat inclut le nom, l'état, l'âge, la version et le point de terminaison de chaque cluster.

    Par exemple, le résultat suivant n'inclut qu'un seul AWSCluster nommé cluster-0 :

    NAME        STATE          AGE     VERSION         ENDPOINT
    cluster-0   Provisioning   2m41s   1.25.5-gke.2100   gke-xyz.elb.us-east-1.amazonaws.com
    

Afficher les événements de votre cluster

Pour afficher les événements Kubernetes récents de votre cluster d'utilisateur, utilisez kubectl get events.

  1. À partir de votre répertoire anthos-aws, utilisez anthos-gke pour basculer vers le contexte de votre service de gestion.

    cd anthos-aws
    anthos-gke aws management get-credentials

  2. Exécutez kubectl get events.

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl get events
    

Le résultat inclut des informations, des avertissements et des erreurs liés à votre service de gestion.

Créer le webhook Workload Identity

Cette section s'adresse aux administrateurs de cluster.

Pour fournir les identifiants Workload Identity à vos charges de travail sans configuration supplémentaire, vous pouvez éventuellement créer un webhook sur vos clusters d'utilisateurs. Ce webhook intercepte les requêtes de création de pod, puis met à la disposition du pod les informations AWS IAM suivantes en tant que variables d'environnement :

  • AWS_ROLE_ARN : nom de la ressource Amazon (ARN) du rôle IAM
  • aws-iam-token : jeton échangé pour les identifiants AWS IAM
  • AWS_WEB_IDENTITY_TOKEN_FILE : chemin d'accès au jeton stocké

Grâce à ces variables, vos charges de travail peuvent appeler l'outil de ligne de commande ou le SDK AWS afin d'accéder aux ressources attribuées au rôle AWS.

La création du webhook est facultative. Si vous décidez de ne pas créer de webhook, vous devez définir les variables d'environnement répertoriées précédemment dans le pod. Pour plus d'informations sur l'utilisation d'un webhook, consultez la section Appliquer des identifiants sans le webhook.

Créer des fichiers YAML pour le webhook

Pour déployer le webhook, procédez comme suit :

  1. À partir de votre répertoire anthos-aws, utilisez anthos-gke pour basculer vers le contexte de votre service de gestion.

    cd anthos-aws
    anthos-gke aws management get-credentials

  2. Obtenez le nom du cluster d'utilisateur avec kubectl :

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl get awscluster
    

    kubectl répertorie tous vos clusters d'utilisateurs. Choisissez le cluster d'utilisateur que vous avez créé avec Workload Identity activé.

  3. Définissez le nom du cluster dans une variable d'environnement.

    CLUSTER_NAME=CLUSTER_NAME
    

    Remplacez CLUSTER_NAME par le nom de votre cluster. Exemple : cluster-0.

  4. Définissez des variables d'environnement pour l'image de pod et l'espace de noms de Workload Identity.

    IDENTITY_IMAGE=amazon/amazon-eks-pod-identity-webhook:ed8c41f
    
    WEBHOOK_NAMESPACE=workload-identity-webhook
    
  5. Générez le fichier manifeste YAML du webhook dans un fichier nommé aws-webhook.yaml en procédant comme suit :

    env HTTPS_PROXY=http://localhost:8118 \
      anthos-gke aws clusters get-credentials ${CLUSTER_NAME}
    
    CLUSTER_CA=$(env HTTPS_PROXY=http://localhost:8118 \
      kubectl config view --raw -o json  | jq -r '.clusters[] | select(.name == "'$(kubectl config current-context)'") | .cluster."certificate-authority-data"')
    
    cat << EOF > aws-webhook.yaml
    apiVersion: v1
    kind: Namespace
    metadata:
      name: ${WEBHOOK_NAMESPACE}
    ---
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: pod-identity-webhook
      namespace: ${WEBHOOK_NAMESPACE}
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: Role
    metadata:
      name: pod-identity-webhook
      namespace: ${WEBHOOK_NAMESPACE}
    rules:
      - apiGroups: ['']
        resources: ['secrets']
        verbs: ['create']
      - apiGroups: ['']
        resources: ['secrets']
        verbs: ['get', 'update', 'patch']
        resourceNames:
          - pod-identity-webhook
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: RoleBinding
    metadata:
      name: pod-identity-webhook
      namespace: ${WEBHOOK_NAMESPACE}
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: Role
      name: pod-identity-webhook
    subjects:
      - kind: ServiceAccount
        name: pod-identity-webhook
        namespace: ${WEBHOOK_NAMESPACE}
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRole
    metadata:
      name: pod-identity-webhook
    rules:
      - apiGroups: ['']
        resources: ['serviceaccounts']
        verbs: ['get', 'watch',  'list']
      - apiGroups:  ['certificates.k8s.io']
        resources: ['certificatesigningrequests']
        verbs:  ['create', 'get', 'list', 'watch']
    ---
    apiVersion: rbac.authorization.k8s.io/v1
    kind: ClusterRoleBinding
    metadata:
      name: pod-identity-webhook
    roleRef:
      apiGroup: rbac.authorization.k8s.io
      kind: ClusterRole
      name: pod-identity-webhook
    subjects:
      - kind: ServiceAccount
        name: pod-identity-webhook
        namespace: ${WEBHOOK_NAMESPACE}
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: pod-identity-webhook
      namespace: ${WEBHOOK_NAMESPACE}
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: pod-identity-webhook
      template:
        metadata:
          labels:
            app: pod-identity-webhook
        spec:
          serviceAccountName: pod-identity-webhook
          containers:
            - name: pod-identity-webhook
              image: ${IDENTITY_IMAGE}
              imagePullPolicy: Always
              command:
                - /webhook
                - --in-cluster
                - --namespace=${WEBHOOK_NAMESPACE}
                - --service-name=pod-identity-webhook
                - --tls-secret=pod-identity-webhook
                - --annotation-prefix=eks.amazonaws.com
                - --token-audience=sts.amazonaws.com
                - --logtostderr
              volumeMounts:
                - name: webhook-certs
                  mountPath: /var/run/app/certs
                  readOnly: false
          volumes:
            - name: webhook-certs
              emptyDir: {}
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: pod-identity-webhook
      namespace: ${WEBHOOK_NAMESPACE}
      annotations:
        prometheus.io/port: '443'
        prometheus.io/scheme: https
        prometheus.io/scrape: 'true'
    spec:
      ports:
        - port: 443
          targetPort: 443
      selector:
        app: pod-identity-webhook
    ---
    apiVersion: admissionregistration.k8s.io/v1
    kind: MutatingWebhookConfiguration
    metadata:
      name: pod-identity-webhook
      namespace: ${WEBHOOK_NAMESPACE}
    webhooks:
      - name: pod-identity-webhook.amazonaws.com
        failurePolicy: Ignore
        sideEffects: 'None'
        admissionReviewVersions: ['v1beta1']
        clientConfig:
          service:
            name: pod-identity-webhook
            namespace: ${WEBHOOK_NAMESPACE}
            path: /mutate
          caBundle: ${CLUSTER_CA}
        rules:
          - operations: ['CREATE']
            apiGroups: ['']
            apiVersions: ['v1']
            resources: ['pods']
    EOF
    

    Le contenu de aws-webhook.yaml est prêt à être appliqué à votre cluster.

Appliquer le webhook à votre cluster d'utilisateur

Pour appliquer le webhook à votre cluster d'utilisateur, procédez comme suit :

  1. Appliquez le fichier aws-webhook.yaml à votre cluster d'utilisateur.

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl apply -f aws-webhook.yaml
    
  2. Lorsque vous appliquez le fichier manifeste, le pod de webhook génère des demandes de signature de certificat Kubernetes (CSR). Approuver toutes les demandes de system:serviceaccount:${WEBHOOK_NAMESPACE}:pod-identity-webhook avec kubectl certificate approve.

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl certificate approve $(env HTTPS_PROXY=http://localhost:8118 \ &&\
      kubectl get csr -o \
        jsonpath="{.items[?(@.spec.username==\"system:serviceaccount:${WEBHOOK_NAMESPACE}:pod-identity-webhook\")].metadata.name}")
    
  3. Vérifiez qu'il n'existe aucune demande de signature de certificat client non approuvée.

    Utilisez kubectl get csr pour vérifier que toutes les CSR du demandeur system:serviceaccount:${WEBHOOK_NAMESPACE}:pod-identity-webhook sont approuvées :

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl get csr
    

    Réponse :

    NAME        AGE   REQUESTOR                                            CONDITION
    csr-mxrt8   10s   system:serviceaccount:default:pod-identity-webhook   Approved,Issued
    

Configurer le fournisseur AWS OIDC

Cette section s'adresse aux administrateurs de cluster.

Pour créer un fournisseur OIDC sur AWS, AWS requiert une autorité de certification intermédiaire ou une empreinte de certification de serveur. Vos identifiants de découverte OIDC sont stockés sur storage.googleapis.com, avec un certificat signé par une autorité de certification intermédiaire nommée GTS CA 1C3. L'empreinte SHA-1 de son autorité de certification intermédiaire GTS CA 1C3 est 08745487E891C19E3078C1F2A07E452950EF36F6.

Pour enregistrer votre bucket de découverte OIDC en tant que fournisseur OIDC avec AWS, procédez comme suit :

  1. À partir de votre répertoire anthos-aws, utilisez anthos-gke pour basculer vers le contexte de votre service de gestion.

    cd anthos-aws
    anthos-gke aws management get-credentials

  2. Enregistrez l'URL de l'émetteur OIDC, le chemin d'hôte de l'émetteur et l'empreinte Cloud Storage dans les variables d'environnement.

    ISSUER_URL=$(env HTTPS_PROXY=http://localhost:8118 \
      kubectl get awscluster ${CLUSTER_NAME} -o jsonpath='{.status.workloadIdentityInfo.issuerURL}')
    ISSUER_HOSTPATH=${ISSUER_URL#"https://"}
    CA_THUMBPRINT=08745487E891C19E3078C1F2A07E452950EF36F6
    
  3. Utilisez l'outil de ligne de commande aws pour créer un fournisseur OIDC sur AWS.

    aws iam create-open-id-connect-provider \
      --url ${ISSUER_URL} \
      --thumbprint-list ${CA_THUMBPRINT} \
      --client-id-list sts.amazonaws.com
    

Mettre à jour l'empreinte

Si Google effectue une rotation de l'autorité de certification pour storage.googleapis.com, exécutez les commandes suivantes :

  1. Copiez l'empreinte mise à jour du certificat, 08745487E891C19E3078C1F2A07E452950EF36F6.

  2. Suivez les instructions de la commande aws iam update-open-id-connect-provider-thumbprint. Utilisez storage.googleapis.com comme nom d'hôte cible et 08745487E891C19E3078C1F2A07E452950EF36F6 comme empreinte.

Créer des rôles et des stratégies AWS IAM

Cette section s'adresse aux administrateurs de cluster.

Créer un rôle AWS IAM pour lier un compte de service Kubernetes Le rôle IAM dispose des autorisations pour sts:AssumeRoleWithWebIdentity.

Pour créer le rôle, procédez comme suit :

  1. Recherchez ou créez une stratégie AWS IAM, qui accorde les autorisations nécessaires pour vos charges de travail.

    Vous avez besoin de la stratégie AWS IAM du nom de ressource Amazon (ARN) de la stratégie. Exemple :arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess

  2. Définissez les variables d'environnement avec vos informations d'authentification.

    KSA_NAME=KUBERNETES_SERVICE_ACCOUNT
    WORKLOAD_NAMESPACE=WORKLOAD_IDENTITY_NAMESPACE
    
    AWS_ROLE_NAME=AWS_ROLE_NAME
    AWS_POLICY=EXISTING_AWS_POLICY
    

    Remplacez l'élément suivant :

    • KUBERNETES_SERVICE_ACCOUNT : nom du nouveau compte de service Kubernetes
    • WORKLOAD_IDENTITY_NAMESPACE : nom de l'espace de noms où les charges de travail sont exécutées
    • AWS_ROLE_NAME : nom du nouveau rôle AWS pour vos charges de travail
    • EXISTING_AWS_POLICY : nom de la ressource Amazon (ARN) d'une stratégie IAM AWS existante (par exemple, arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess).
  3. À partir de votre répertoire anthos-aws, utilisez anthos-gke pour basculer vers le contexte de votre service de gestion.

    cd anthos-aws
    anthos-gke aws management get-credentials

  4. Créez une stratégie AWS IAM qui permet à votre cluster utilisateur d'utiliser des identifiants de sécurité temporaires avec le service AWS Security Token Service :

    CLUSTER_ID=$(env HTTPS_PROXY=http://localhost:8118 \
      kubectl get awscluster ${CLUSTER_NAME} -o jsonpath='{.status.clusterID}')
    
    # Get the ID Provider ARN
    PROVIDER_ARN=$(aws iam list-open-id-connect-providers  \
    | jq '.OpenIDConnectProviderList' \
    | jq ".[] | select(.Arn |  contains(\"${CLUSTER_ID}\"))"   \
    | jq  '.Arn' | tr -d '"')
    
    # Create AWS role and policy
    cat > irp-trust-policy.json << EOF
    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Principal": {
            "Federated": "${PROVIDER_ARN}"
          },
          "Action": "sts:AssumeRoleWithWebIdentity",
          "Condition": {
            "StringEquals": {
              "${ISSUER_HOSTPATH}:sub": "system:serviceaccount:${WORKLOAD_NAMESPACE}:${KSA_NAME}"
            }
          }
        }
      ]
    }
    EOF
    
  5. Pour créer un rôle AWS IAM avec cette stratégie et lui associer votre stratégie existante, exécutez les commandes suivantes :

    aws iam create-role \
      --role-name ${AWS_ROLE_NAME} \
      --assume-role-policy-document file://irp-trust-policy.json
    aws iam update-assume-role-policy \
      --role-name ${AWS_ROLE_NAME} \
      --policy-document file://irp-trust-policy.json
    aws iam attach-role-policy \
      --role-name ${AWS_ROLE_NAME} \
      --policy-arn ${AWS_POLICY}
    

    L'outil de ligne de commande aws confirme que la stratégie est associée à votre rôle.

Créer des comptes de service Kubernetes pour les charges de travail

Cette section est destinée aux développeurs ou aux administrateurs de cluster.

Pour créer des comptes de service Kubernetes liés au rôle AWS IAM précédemment spécifié, procédez comme suit :

  1. À partir de votre répertoire anthos-aws, utilisez anthos-gke pour basculer vers le contexte de votre cluster d'utilisateur.

    cd anthos-aws
    env HTTPS_PROXY=http://localhost:8118 \
      anthos-gke aws clusters get-credentials CLUSTER_NAME
    Remplacez CLUSTER_NAME par le nom de votre cluster d'utilisateur.

  2. Créez le compte de service Kubernetes en exécutant les commandes suivantes :

    S3_ROLE_ARN=$(aws iam get-role \
      --role-name AWS_ROLE_NAME \
      --query Role.Arn --output text)
    
    cat << EOF  > k8s-service-account.yaml
    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: ${KSA_NAME}
      namespace: WORKLOAD_IDENTITY_NAMESPACE
    EOF
    
    env HTTPS_PROXY=http://localhost:8118 \
    kubectl apply -f k8s-service-account.yaml
    
    env HTTPS_PROXY=http://localhost:8118 \
    kubectl annotate sa --namespace ${WORKLOAD_NAMESPACE} ${KSA_NAME} eks.amazonaws.com/role-arn=${S3_ROLE_ARN}
    

    Remplacez l'élément suivant :

    • AWS_ROLE_NAME : nom du rôle AWS IAM à appliquer à vos charges de travail
    • WORKLOAD_IDENTITY_NAMESPACE : nom de l'espace de noms où les charges de travail sont exécutées

Appliquer des identifiants à vos pods

Cette section s'adresse aux développeurs.

Dans cette section, nous partons du principe que vous avez déployé le webhook Workload Identity. Si vous n'avez pas déployé le webhook, passez à la section Appliquer des identifiants sans webhook.

Appliquer des identifiants avec le webhook

Cette section explique comment configurer vos pods pour qu'ils lisent les identifiants mis à disposition par le webhook.

Ajouter le compte de service au pod

Pour utiliser Workload Identity avec une charge de travail, ajoutez le compte de service Kubernetes dans les champs suivants :

  • Pour un déploiement : spec.template.spec.serviceAccountName
  • Pour un pod : spec.serviceAccount

Le fichier manifeste de pod suivant lance une image CentOS de base et contient le champ spec.serviceAccount.

apiVersion: v1
kind: Pod
metadata:
  name: sample-centos-pod
  namespace: WORKLOAD_IDENTITY_NAMESPACE
spec:
  containers:
  - command:
    - /bin/bash
    - -ec
    - while :; do echo '.'; sleep 500 ; done
    image: amazon/aws-cli
    name: centos
  serviceAccount: KUBERNETES_SERVICE_ACCOUNT

Remplacez l'élément suivant :

  • WORKLOAD_IDENTITY_NAMESPACE : nom de l'espace de noms où les charges de travail sont exécutées
  • KUBERNETES_SERVICE_ACCOUNT : nom du compte de service Kubernetes que vous avez créé précédemment

Vérifier si les variables d'environnement sont définies pour les pods

Pour vérifier si les variables d'environnement ont été définies pour les pods, exécutez la commande suivante afin d'obtenir les informations sur le pod :

kubectl get pod --namespace WORKLOAD_IDENTITY_NAMESPACE POD_NAME -o yaml

Remplacez l'élément suivant :

  • WORKLOAD_IDENTITY_NAMESPACE : nom de l'espace de noms où les charges de travail sont exécutées
  • POD_NAME : nom du pod à vérifier

La sortie contient les valeurs des variables d'environnement dans spec.containers.command.env et le point d'installation du jeton AWS IAM. Voici un exemple de fichier manifeste de pod :

apiVersion: v1
kind: Pod
metadata:
  ...
spec:
  containers:
  - command:
    - /bin/bash
    - -ec
    - while :; do echo '.'; sleep 500 ; done
    env:
    - name: AWS_ROLE_ARN
      value: arn:aws:iam::1234567890:role/my-example-workload-role-1
    - name: AWS_WEB_IDENTITY_TOKEN_FILE
      value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token
    image: amazon/aws-cli
    imagePullPolicy: IfNotPresent
    name: centos
    resources: {}
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: my-k8s-serviceaccount-token-d4nz4
      readOnly: true
    - mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount
      name: aws-iam-token
      readOnly: true
  serviceAccount: my-k8s-serviceaccount
  serviceAccountName: my-k8s-serviceaccount
  volumes:
  - name: aws-iam-token
    projected:
      defaultMode: 420
      sources:
      - serviceAccountToken:
          audience: sts.amazonaws.com
          expirationSeconds: 86400
          path: token
  - name: my-k8s-serviceaccount-token-d4nz4
    secret:
      defaultMode: 420
      secretName: my-k8s-serviceaccount-token-d4nz4
   ...
status:
  ...

Appliquer des identifiants sans le webhook

Si vous ne déployez pas le webhook Workload Identity, procédez comme suit :

Créer un pod avec des identifiants pour Workload Identity

Pour créer un pod comprenant les identifiants nécessaires pour Workload Identity, procédez comme suit :

  1. Copiez le fichier manifeste de pod suivant dans un fichier nommé sample-pod-no-webhook.yaml. La configuration lance une image CentOS de base avec les identifiants nécessaires.

    apiVersion: v1
    kind: Pod
    metadata:
      name: sample-centos-pod-no-webhook
      namespace: WORKLOAD_IDENTITY_NAMESPACE
    spec:
      containers:
      - command:
        - /bin/bash
        - -ec
        - while :; do echo '.'; sleep 500 ; done
        image: centos:7
        name: centos
        env:
        - name: AWS_ROLE_ARN
          value: IAM_ROLE_ARN
        - name: AWS_WEB_IDENTITY_TOKEN_FILE
          value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token
        volumeMounts:
        - mountPath: /var/run/secrets/eks.amazonaws.com/serviceaccount
          name: aws-iam-token
          readOnly: true
      volumes:
      - name: aws-iam-token
        projected:
          defaultMode: 420
          sources:
          - serviceAccountToken:
              audience: sts.amazonaws.com
              expirationSeconds: 86400
              path: token
      serviceAccount: KUBERNETES_SERVICE_ACCOUNT
    

    Remplacez l'élément suivant :

    • WORKLOAD_IDENTITY_NAMESPACE : nom de l'espace de noms où les charges de travail sont exécutées.
    • IAM_ROLE_ARN : ARN du rôle IAM attribué au pod. Exemple : arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess.
    • KUBERNETES_SERVICE_ACCOUNT : nom du compte de service Kubernetes que vous avez créé précédemment.
  2. Appliquez le fichier manifeste de pod à votre cluster à l'aide de kubectl :

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl apply -f sample-pod-no-webhook.yaml
    

Vérifier si les pods peuvent accéder aux ressources AWS

La procédure suivante explique comment vérifier si le pod a reçu les identifiants nécessaires pour que Workload Identity fonctionne.

Pour terminer la procédure, vous devez disposer des éléments suivants :

  • Accès de l'interface système bash au conteneur ; la plupart des images de production n'ont pas d'interface système. L'exemple suivant montre comment utiliser le pod spécifié dans la section précédente pour accéder à AWS S3.

  • Votre pod doit disposer d'un accès sortant à Internet pour télécharger l'interface de ligne de commande AWS.

Pour vérifier si le pod peut accéder à un bucket S3, procédez comme suit :

  1. Utilisez kubectl exec pour lancer une interface système bash interactive sur le pod sample-centos-pod-no-webhook :

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl exec -it --namespace ${WORKLOAD_NAMESPACE} sample-centos-pod-no-webhook -- bash
    

    Votre terminal ouvre l'interface système bash sur le pod.

  2. Vérifiez les autorisations et les identifiants AWS IAM à l'aide de l'outil aws :

    aws sts assume-role-with-web-identity \
     --role-arn ${AWS_ROLE_ARN} \
     --role-session-name mh9test \
     --web-identity-token file:///var/run/secrets/eks.amazonaws.com/serviceaccount/token \
     --duration-seconds 1000
    

    L'outil aws imprime des informations d'identification semblables à celles-ci :

    {
        "AssumedRoleUser": {
            "AssumedRoleId": "AROAR2ZZZLEXVSDCDJ37N:mh9test",
            "Arn": "arn:aws:sts::126285863215:assumed-role/my-example-workload-role-1/mh9test"
        },
        "Audience": "sts.amazonaws.com",
        "Provider": "arn:aws:iam::126285863215:oidc-provider/storage.googleapis.com/gke-issuer-cec6c353",
        "SubjectFromWebIdentityToken": "system:serviceaccount:default:my-s3-reader-ksa",
        "Credentials": {
            "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
            "SessionToken": "MY_TOKEN",
            "Expiration": "2020-08-14T22:46:36Z",
            "AccessKeyId": "AKIAIOSFODNN7EXAMPLE"
        }
    }
    

    Si le message suivant s'affiche, vérifiez que le bucket est accessible au public : An error occurred (InvalidIdentityToken) when calling the AssumeRoleWithWebIdentity operation: Couldn't retrieve verification key from your identity provider, please reference AssumeRoleWithWebIdentity documentation for requirements

Mettre à niveau le webhook

Si vous avez créé un cluster Kubernetes 1.18 ou version antérieure avec Workload Identity activé et la version du webhook Workload Identity release-0.2.2-gke.0, vous devez mettre à niveau le webhook avant de passer à Kubernetes 1.19.

Pour mettre à niveau le webhook, procédez comme suit :

  1. Vérifiez que le webhook est installé en exécutant les commandes suivantes :

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl get MutatingWebhookConfiguration
    

    Si le webhook est déployé sur le cluster, la sortie comprend les éléments suivants :

    NAME                   WEBHOOKS   AGE
    pod-identity-webhook   1          11m
    

    Si le webhook n'est pas déployé sur votre cluster, vous pouvez ignorer les étapes suivantes.

  2. Si vous avez enregistré le fichier aws-webhook.yaml, vous pouvez supprimer le fichier manifeste. Si ce fichier n'est pas disponible, vous pouvez supprimer les composants du webhook manuellement. Sélectionnez un fichier ou des composants ci-dessous.

    Fichier

    Si vous disposez toujours du fichier aws-webhook.yaml, exécutez la commande suivante pour supprimer le webhook :

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl delete -f aws-webhook.yaml
    

    Composants

    Pour supprimer manuellement les composants du webhook, exécutez les commandes suivantes :

    env HTTPS_PROXY=http://localhost:8118 \
       kubectl delete namespace WEBHOOK_NAMESPACE
    env HTTPS_PROXY=http://localhost:8118 \
       kubectl delete clusterrole pod-identity-webhook
    env HTTPS_PROXY=http://localhost:8118 \
       kubectl delete clusterrolebinding pod-identity-webhook
    env HTTPS_PROXY=http://localhost:8118 \
       kubectl delete mutatingwebhookconfiguration pod-identity-webhook
    

    Remplacez WEBHOOK_NAMESPACE par l'espace de noms dans lequel vous avez installé le webhook Workload Identity. Par exemple, workload-identity-webhook.

  3. Vérifiez si vous avez des requêtes de signature de certificat (CSR, Certificate Signing Request) restantes en exécutant la commande suivante :

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl get csr |grep pod-identity-webhook
    

    Si le résultat est vide, passez à l'étape suivante. S'il existe d'autres CSR, la commande kubectl répertorie les CSR existantes. Pour supprimer les CSR, exécutez la commande suivante :

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl delete csr $(kubectl get csr -o \
      jsonpath="{.items[?(@.spec.username==\"system:serviceaccount:WEBHOOK_NAMESPACE:pod-identity-webhook\")].metadata.name}")
    

    Remplacez WEBHOOK_NAMESPACE par l'espace de noms dans lequel vous avez installé le webhook Workload Identity. Par exemple, workload-identity-webhook.

  4. Suivez les étapes de la section Créer le webhook pour déployer la nouvelle version du webhook.

    Après avoir déployé la nouvelle version du webhook, vous devez redémarrer les pods qui l'utilisent. Vous pouvez redémarrer vos pods en mettant à niveau un cluster d'utilisateur.

Nettoyer

Cette section explique comment supprimer les ressources créées précédemment dans ce document.

Nettoyer le compte de service et son rôle IAM associé

Pour supprimer le compte de service et son rôle IAM associé, procédez comme suit :

  1. Nettoyez le compte de service :

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl delete sa KUBERNETES_SERVICE_ACCOUNT --namespace WORKLOAD_IDENTITY_NAMESPACE
    

    Remplacez l'élément suivant :

    • KUBERNETES_SERVICE_ACCOUNT : nom du nouveau compte de service Kubernetes
    • WORKLOAD_IDENTITY_NAMESPACE : nom de l'espace de noms où les charges de travail sont exécutées
  2. Nettoyez le rôle IAM AWS. Sélectionnez l'une des options suivantes :

    • Supprimez le rôle AWS IAM à l'aide de la console AWS.

    • Supprimez le rôle à l'aide de l'outil de ligne de commande AWS à l'aide des commandes suivantes :

      aws iam  detach-role-policy \
        --role-name=${AWS_ROLE_NAME} \
        --policy-arn=${AWS_POLICY}
      aws iam delete-role --role-name=${AWS_ROLE_NAME}
      

Supprimer votre cluster d'utilisateur

Pour supprimer votre cluster d'utilisateur, suivez la procédure décrite dans la section Désinstaller GKE sur AWS.

Nettoyer le fournisseur AWS OIDC

Une fois le cluster d'utilisateur supprimé, annulez l'enregistrement du fournisseur OIDC et supprimez-le sur AWS à l'aide de la commande shell bash suivante ou de l'interface utilisateur Web AWS.

  1. À partir de votre répertoire anthos-aws, utilisez anthos-gke pour basculer vers le contexte de votre service de gestion.

    cd anthos-aws
    anthos-gke aws management get-credentials

  2. Supprimez le rôle à l'aide de l'outil de ligne de commande AWS avec les commandes suivantes :

    CLUSTER_ID=$(env HTTPS_PROXY=http://localhost:8118 \
      kubectl get awscluster ${CLUSTER_NAME} -o jsonpath='{.status.clusterID}')
    
    PROVIDER_ARN=$(aws iam list-open-id-connect-providers  \
    | jq '.OpenIDConnectProviderList' \
    | jq ".[] | select(.Arn |  contains(\"${CLUSTER_ID}\"))"   \
    | jq  '.Arn' | tr -d '"')
    
    aws iam delete-open-id-connect-provider \
      --open-id-connect-provider-arn=${PROVIDER_ARN}
    

    Vous recevez une confirmation de la suppression du fournisseur AWS OIDC.

Étape suivante