Comment résoudre le problème d'un fournisseur OIDC et d'un IRSA dans Amazon EKS ?

Date de la dernière mise à jour : 15/11/2021

Mes pods ne peuvent pas utiliser les autorisations du rôle IAM avec le jeton de compte Amazon Elastic Kubernetes Service (Amazon EKS).

Brève description

Pour résoudre les problèmes liés au fournisseur OpenID Connect (OIDC) et aux rôles IAM pour les comptes de service (IRSA) dans Amazon EKS, suivez les étapes décrites dans l'une des sections suivantes :

  • Vérifiez si vous avez un fournisseur IAM OIDC existant pour votre cluster
  • Vérifiez si votre rôle IAM a une politique IAM nécessaire attachée avec les autorisations requises
  • Vérifiez que les relations d'approbation du rôle IAM sont correctement définies
  • Vérifiez si vous avez créé un compte de service
  • Vérifiez que le compte de service possède les annotations de rôle IAM correctes
  • Vérifiez que vous avez correctement spécifié le serviceAccountName dans votre pod
  • Vérifiez les variables d'environnement et les autorisations
  • Vérifiez que l'application utilise un kit SDK AWS pris en charge
  • Vérifiez l'utilisateur et le groupe du pod
  • Recréez les pods
  • Vérifiez que l'audience est correcte
  • Vérifiez que vous avez configuré la bonne empreinte numérique
  • Pour la région AWS Chine, vérifiez la variable d'environnement AWS_DEFAULT_REGION

Solution

Vérifiez si vous avez un fournisseur IAM OIDC existant pour votre cluster

Si un fournisseur existe déjà, vous recevez une erreur.

Par exemple :

WebIdentityErr: failed to retrieve credentials\ncaused by: InvalidIdentityToken: No OpenIDConnect provider found in your account 
for https://oidc.eks.eu-west-1.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E\n\tstatus code: 400

1.    Vérifiez l'URL du fournisseur OIDC de votre cluster :

$ aws eks describe-cluster --name cluster_name --query "cluster.identity.oidc.issuer" --output text

Exemple de sortie :

https://oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E

2.    Répertoriez les fournisseurs IAM OIDC de votre compte. Remplacez EXAMPLED539D4633E53DE1B716D3041E (inclure < >) par la valeur retournée par la commande précédente :

aws iam list-open-id-connect-providers | grep EXAMPLED539D4633E53DE1B716D3041E

Exemple de sortie :

"Arn": "arn:aws:iam::111122223333:oidc-provider/oidc.eks.us-west-2.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E"

Si la commande précédente renvoie un résultat, alors vous avez déjà un fournisseur pour votre cluster. Si la commande ne renvoie pas de résultat, vous devez créer un fournisseur IAM OIDC. Consultez Créer un fournisseur OIDC IAM pour votre cluster.

Vérifiez si votre rôle IAM a une politique IAM nécessaire attachée avec les autorisations requises

1.    Ouvrez la console IAM.

2.    Dans le volet de navigation, choisissez Rôles.

3.    Choisissez le rôle que vous souhaitez contrôler.

4.    Sous l'onglet Autorisations, vérifiez si la politique requise est associée à ce rôle.

Vérifiez que les relations d'approbation du rôle IAM sont correctement définies

Avec la console de gestion AWS :

1.    Ouvrez la console IAM.

2.    Dans le volet de navigation, choisissez Rôles.

3.    Choisissez le rôle que vous souhaitez vérifier.

4.    Choisissez l'onglet Relations d'approbation pour vérifier que le format de votre politique correspond au format de la politique JSON suivante :

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E:sub": "system:serviceaccount:SERVICE_ACCOUNT_NAMESPACE:SERVICE_ACCOUNT_NAME",
          "oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E:aud": "sts.amazonaws.com"
        }
      }
    }
  ]
}

Avec l'AWS CLI :

Pour vérifier les relations d'approbation, exécutez la commande suivante avec le nom de votre rôle :

$ aws iam get-role --role-name EKS-IRSA

Remarque : remplacez EKS-IRSA par le nom de votre rôle IAM.

Dans le JSON de sortie, recherchez la section AssumeRolePolicyDocument.

Exemple de sortie :

{
    "Role": {
        "Path": "/",
        "RoleName": "EKS-IRSA",
        "RoleId": "AROAQ55NEXAMPLELOEISVX",
        "Arn": "arn:aws:iam::ACCOUNT_ID:role/EKS-IRSA",
        "CreateDate": "2021-04-22T06:39:21+00:00",
        "AssumeRolePolicyDocument": {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Federated": "arn:aws:iam::ACCOUNT_ID:oidc-provider/oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E"
                    },
                    "Action": "sts:AssumeRoleWithWebIdentity",
                    "Condition": {
                        "StringEquals": {
                            "oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E:aud": "sts.amazonaws.com",
                            "oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E:sub": "system:serviceaccount:SERVICE_ACCOUNT_NAMESPACE:SERVICE_ACCOUNT_NAME"
                        }
                    }
                }
            ]
        },
        "MaxSessionDuration": 3600,
        "RoleLastUsed": {
            "LastUsedDate": "2021-04-22T07:01:15+00:00",
            "Region": "AWS_REGION"
        }
    }
}

Remarque : vérifiez que vous avez spécifié la région AWS, le nom du compte de service Kubernetes et l'espace de noms Kubernetes corrects.

Vérifiez si vous avez créé un compte de service

Utilisez la commande suivante :

$ kubectl get sa -n YOUR_NAMESPACE

Remarque : remplacez YOUR_NAMESPACE par votre espace de noms Kubernetes.

Exemple de sortie :

NAME      SECRETS   AGE
default   1         28d
irsa      1         66m

Si vous ne disposez pas d'un compte de service, consultez Configuration des comptes de service pour les pods .

Vérifiez que le compte de service possède les annotations de rôle IAM correctes

Utilisez la commande suivante :

$ kubectl describe sa irsa -n YOUR_NAMESPACE

Remarque : remplacez irsa par le nom de votre compte de service Kubernetes. Remplacez YOUR_NAMESPACE par votre espace de noms Kubernetes.

Exemple de sortie :

Name:                irsa
Namespace:           default
Labels:              none
Annotations:         eks.amazonaws.com/role-arn: arn:aws:iam::ACCOUNT_ID:role/IAM_ROLE_NAME
Image pull secrets:  none
Mountable secrets:   irsa-token-v5rtc
Tokens:              irsa-token-v5rtc
Events:              none

Vérifiez que vous avez correctement spécifié le serviceAccountName dans votre pod

Utilisez la commande suivante :

$ kubectl get pod POD_NAME  -o yaml -n YOUR_NAMESPACE| grep -i serviceAccountName:

Remarque : remplacez POD_NAME et YOUR_NAMESPACE par votre pod et votre espace de noms Kubernetes.

Exemple de sortie :

serviceAccountName: irsa

Vérifiez les variables d'environnement et les autorisations

Recherchez AWS_IAM_ROLE_ARN et AWS_WEB_IDENTITY_TOKEN_FILE dans les variables d'environnement du pod :

$ kubectl -n YOUR_NAMESPACE exec -it POD_NAME -- env | grep AWS

Exemple de sortie :

AWS_REGION=ap-southeast-2
AWS_ROLE_ARN=arn:aws:iam::111122223333:role/EKS-IRSA
AWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount/token
AWS_DEFAULT_REGION=ap-southeast-2

Vérifiez que l'application utilise un kit SDK AWS pris en charge

La version du SDK doit être supérieure ou égale aux valeurs suivantes :

Java (Version 2) — 2.10.11
Java — 1.11.704
Go — 1.23.13
Python (Boto3) — 1.9.220
Python (botocore) — 1.12.200
AWS CLI — 1.16.232
Node — 3.15.0
Ruby — 2.11.345
C++ — 1.7.174
.NET — 3.3.659.1
PHP — 3.110.7

Pour vérifier la dernière version du kit SDK pris en charge, consultez Utilisation d'un kit SDK AWS pris en charge.

Vérifiez l'utilisateur et le groupe du pod

Utilisez la commande suivante :

$ kubectl exec -it POD_NAME -- id
uid=0(root) gid=0(root) groups=0(root)

Remarque : par défaut, seuls les conteneurs qui s'exécutent en tant qu'utilisateur root disposent des autorisations de système de fichiers appropriées pour lire le fichier de jeton d'identité Web.

Si vos conteneurs ne s'exécutent pas en tant qu'utilisateur root, vous pouvez recevoir les erreurs suivantes :

Error: PermissionError: [Errno 13] Permission denied: ‘/var/run/secrets/eks.amazonaws.com/serviceaccount/token

Ou:

WebIdentityErr: failed fetching WebIdentity token: \ncaused by: WebIdentityErr: unable to read file at /var/run/secrets/eks.amazonaws.com/serviceaccount/token\ncaused by: open /var/run/secrets/eks.amazonaws.com/serviceaccount/token: permission denied

Pour fournir les autorisations de système de fichiers appropriées, assurez-vous que vos conteneurs s'exécutent en tant qu'utilisateur root. Pour les clusters 1.18 ou inférieurs, fournissez le contexte de sécurité suivant pour les conteneurs de votre manifeste :

apiVersion: apps/v1
kind: Deployment
metadata:
 name: my-app
spec:
 template:
    metadata:
      labels:
        app: my-app
    spec:
      serviceAccountName: my-app
      containers:
      - name: my-app
        image: my-app:latest
      securityContext:
        fsGroup: 1337
...

Remarque : l'ID de fsGroup est arbitraire. Vous pouvez choisir n'importe quel ID de groupe valide. Le paramètre de contexte de sécurité précédent n'est pas requis pour les clusters 1.19 ou ultérieurs.

Recréez les pods

Si vous avez créé des pods avant d'appliquer IRSA, recréez les pods.

Exemple de commande :

$ kubectl rollout restart deploy nginx

Exemple de sortie :

deployment.apps/nginx restarted

Pour les déploiements de daemonsets ou de statefulsets, vous pouvez utiliser la commande suivante :

$ kubectl rollout redémarrer déployer DEPLOYMENT_NAME

Si vous n'avez créé qu'un seul pod, vous devez alors supprimer le pod et le recréer.

Exemple de commande pour supprimer :

$ kubectl delete pod POD_NAME

Exemple de commande pour recréer :

$ kubectl apply -f SPEC_FILE

Remarque : remplacez SPEC_FILE par le chemin et le nom de votre fichier manifeste Kubernetes.

Vérifiez que l'audience est correcte

Si vous avez créé le fournisseur OIDC avec une audience incorrecte, vous recevez l'erreur suivante :

Error - An error occurred (InvalidIdentityToken) when calling the AssumeRoleWithWebIdentity operation: Incorrect token audience

Vérifiez le fournisseur d'identité IAM pour votre cluster. Votre ClientIDList est sts.amazonaws.com :

$ aws iam get-open-id-connect-provider --open-id-connect-provider-arn arn:aws:iam::ACCOUNT_ID:oidc-provider/oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E

Exemple de sortie :

{
    "Url": "oidc.eks.AWS_REGION.amazonaws.com/id/EXAMPLED539D4633E53DE1B716D3041E",
    "ClientIDList": [
        "sts.amazonaws.com"
    ],
    "ThumbprintList": [
        "9e99a48a9960b14926bb7f3b02e22da2b0ab7280"
    ],
    "CreateDate": "2021-01-21T04:29:09.788000+00:00",
    "Tags": []
}

Vérifiez que vous avez configuré la bonne empreinte numérique

Si l'empreinte numérique configurée dans l'OIDC IAM n'est pas correcte, vous pouvez recevoir l'erreur suivante :

failed to retrieve credentials caused by: InvalidIdentityToken: OpenIDConnect provider's HTTPS certificate doesn't match configured thumbprint

Pour configurer automatiquement l'empreinte numérique correcte, utilisez eksctl ou la console de gestion AWS pour créer le fournisseur d'identité IAM. Pour connaître les autres moyens d'obtenir une empreinte numérique, consultez Obtention de l'empreinte numérique d'un fournisseur d'identité OpenID Connect.

Pour la région AWS Chine, vérifiez la variable d'environnement AWS_DEFAULT_REGION

Si vous utilisez IRSA pour un pod ou un daemonset qui est déployé sur un cluster dans la région AWS China, définissez la variable d'environnement AWS_DEFAULT_REGION dans la spécification du pod. Si vous ne le faites pas, le pod ou le daemonset peut recevoir l'erreur suivante :

An error occurred (InvalidClientTokenId) when calling the GetCallerIdentity operation: The security token included in the request is invalid

Utilisez l'exemple suivant pour ajouter la variable d'environnement AWS_DEFAULT_REGION à la spécification de votre pod ou daemonset :

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  template:
    metadata:
      labels:
        app: my-app
    spec:
      serviceAccountName: my-app
      containers:
      - name: my-app
        image: my-app:latest
        env:
        - name: AWS_DEFAULT_REGION
          value: "AWS_REGION"
...

Cet article vous a-t-il été utile ?


Besoin d'aide pour une question technique ou de facturation ?