Как получить токен aws-iam для доступа к S3 с помощью IRSA?

#amazon-s3 #kubernetes #terraform #openid-connect #k8s-serviceaccount

Вопрос:

Я создал роль IRSA в terraform, чтобы связанная учетная запись службы могла использоваться заданием K8s для доступа к корзине S3, но я продолжаю получать AccessDenied сообщение об ошибке в задании.

Я впервые включил IRSA в нашем кластере EKS с enable_irsa = true помощью нашего eks модуля.

Затем я создал простую aws_iam_policy , как:

 resource "aws_iam_policy" "eks_s3_access_policy" {
  name = "eks_s3_access_policy"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = [
          "s3:*",
        ]
        Effect   = "Allow"
        Resource = "arn:aws:s3:::*"
      },
    ]
  })
}
 

и еще iam-assumable-role-with-oidc :

 module "iam_assumable_role_with_oidc_for_s3_access" {
  source  = "terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc"
  version = "~> 3.0"

  create_role = true
  role_name = "eks-s3-access"
  role_description = "Role to access s3 bucket"
  tags = { Role = "eks_s3_access_policy" }
  provider_url = replace(module.eks.cluster_oidc_issuer_url, "https://", "")
  role_policy_arns = [aws_iam_policy.eks_s3_access_policy.arn]
  number_of_role_policy_arns = 1
  oidc_fully_qualified_subjects = ["system:serviceaccount:default:my-user"]
}
 

Я создал учетную запись службы K8s, используя шлем, подобный:

 Name:                my-user
Namespace:           default
Labels:              app.kubernetes.io/managed-by=Helm
Annotations:         eks.amazonaws.com/role-arn: arn:aws:iam::111111:role/eks-s3-access
                     meta.helm.sh/release-name: XXXX
                     meta.helm.sh/release-namespace: default
Image pull secrets:  <none>
Mountable secrets:   my-user-token-kwwpq
Tokens:              my-user-token-kwwpq
Events:              <none>
 

Наконец, задания создаются с помощью API K8s из шаблона задания:

 apiVersion: batch/v1
kind: Job
metadata:
  name: job
  namespace: default
spec:
  template:
  spec:
    serviceAccountName: my-user
    containers:
    - name: {{ .Chart.Name }}
      env:
      - name: AWS_ROLE_ARN
        value: arn:aws:iam::746181457053:role/eks-s3-access
      - 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
 

Однако, когда задание пытается получить указанные учетные данные, указанного токена там нет:

 2021-08-03 18:02:41  Refreshing temporary credentials failed during mandatory refresh period.
Traceback (most recent call last):
  File "/usr/local/lib/python3.7/site-packages/aiobotocore/credentials.py", line 291, in _protected_refresh
    metadata = await self._refresh_using()
  File "/usr/local/lib/python3.7/site-packages/aiobotocore/credentials.py", line 345, in fetch_credentials
    return await self._get_cached_credentials()
  File "/usr/local/lib/python3.7/site-packages/aiobotocore/credentials.py", line 355, in _get_cached_credentials
    response = await self._get_credentials()
  File "/usr/local/lib/python3.7/site-packages/aiobotocore/credentials.py", line 410, in _get_credentials
    kwargs = self._assume_role_kwargs()
  File "/usr/local/lib/python3.7/site-packages/aiobotocore/credentials.py", line 420, in _assume_role_kwargs
    identity_token = self._web_identity_token_loader()
  File "/usr/local/lib/python3.7/site-packages/botocore/utils.py", line 2365, in __call__
    with self._open(self._web_identity_token_path) as token_file:
FileNotFoundError: [Errno 2] No such file or directory: '/var/run/secrets/eks.amazonaws.com/serviceaccount/token'
 

Из того, что описано в https://aws.amazon.com/blogs/opensource/introducing-fine-grained-iam-roles-service-accounts/ веб-крючок обычно создает эти учетные данные при создании модуля. Однако, поскольку мы создаем новое задание k8s по запросу в кластере k8s, я подозреваю, что webhook не создает никаких таких учетных данных.

Как я могу запросить правильные учетные данные для создания в кластере K8s? Есть ли способ создать экземпляр webhook из кластера?

Ответ №1:

Есть пара вещей, которые могут привести к этому сбою.

  • Проверьте все настройки для роли IRSA. Для настройки доверительных отношений проверьте правильность имени пространства имен и имени учетной записи службы. Только в том случае, если эти параметры соответствуют роли, ее можно принять.
  • Во время работы модуля попытайтесь получить доступ к модулю с помощью оболочки. Проверьте содержимое переменных среды «AWS_*». Проверьте, указывает ли AWS_ROLE_ARN на правильную роль. Проверьте, находится ли файл, на который указывает AWS_WEB_IDENTITY_TOKEN_FILE, на своем месте и читаем. Просто попробуйте выполнить а cat на файле, чтобы увидеть, читаем ли он.
  • Если вы запускаете свой модуль без root (что рекомендуется по соображениям безопасности), убедитесь, что у пользователя, который запускает модуль, есть доступ к файлу. Если нет, измените контекст безопасности для модуля. Может fsGroup быть, здесь может помочь настройка. https://kubernetes.io/docs/reference/kubernetes-api/workload-resources/pod-v1/#security-context
  • Убедитесь, что SDK, который использует ваш pos, поддерживает IRSA. Если вы используете более старые SDK, IRSA может не поддерживаться. Ознакомьтесь с документацией IRSA для поддерживаемых версий SDK. https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-minimum-sdk.html

Комментарии:

1. Спасибо за все рекомендации: Я проверил доверительные отношения и убедился, что пространство имен и имя учетной записи службы соответствуют значениям в роли. Я вошел в модуль с помощью оболочки и проверил, что AWS_ROLE_ARN является arn указанной выше роли IRSA. Однако файл, на который указывает автор AWS_WEB_IDENTITY_TOKEN_FILE , отсутствует-похоже, это и есть основная причина. Я настроил громкость и крепление тома для этого токена вручную (выше), но, похоже, проецируемый источник никогда не создается… Я не уверен, как заставить AWS создать этот токен. Это, кажется, недостающий шаг.

2. Интересно, что, когда я создаю задание вручную с помощью обновления руля, модуль имеет правильные аннотации и содержит правильный файл токенов, который позволяет заданию работать правильно. ОДНАКО, когда я создаю задание с сервера в кластере (который используется для создания новых рабочих заданий), аннотации присутствуют, но файл маркера ОТСУТСТВУЕТ. Это заставляет меня думать, что проблема связана с проблемой разрешений для пользователя, который создает задание, возможно?

3. Я обнаружил проблему: добавление тома aws-iam-token в задание вручную до запуска веб-крючка привело к тому, что том не был создан веб-крючком. Следовательно, на смонтированном диске не было файла маркера.

4. Когда я использовал IRSA, я никогда не монтировал том для этого. Файл автоматически оказался на месте.