
Инструмент для использования учетных данных AWS IAM для аутентификации в кластере Kubernetes
Инструмент для использования учетных данных AWS IAM для аутентификации в кластере Kubernetes. Первоначальная работа над этим инструментом велась компанией Heptio. Проект получает вклад от многих инженеров сообщества и в настоящее время поддерживается Heptio и инженерами Amazon EKS OSS.
Если вы администратор, запускающий кластер Kubernetes в AWS, вам уже нужно управлять учетными данными AWS IAM для подготовки и обновления кластера. Используя AWS IAM Authenticator for Kubernetes, вы избегаете необходимости управлять отдельными учетными данными для доступа к Kubernetes. AWS IAM также предоставляет ряд полезных свойств, таких как независимый аудиторский след (через CloudTrail) и принудительное использование 2FA/MFA.
Если вы создаете установщик Kubernetes на AWS, AWS IAM Authenticator for Kubernetes может упростить ваш процесс начальной загрузки.
Вам не нужно будет каким-либо образом безопасно извлекать исходные учетные данные администратора из только что установленного кластера.
Вместо этого вы можете создать выделенную роль KubernetesAdmin на этапе подготовки кластера и настроить Authenticator для разрешения входа администраторов кластера.
Предположим, у вас есть кластер, работающий в AWS, и вы хотите добавить поддержку AWS IAM Authenticator for Kubernetes. Для этого вам необходимо:
Сначала вам необходимо создать одну или несколько ролей IAM, которые будут сопоставлены с пользователями/группами внутри вашего кластера Kubernetes. Проще всего сделать это, войдя в AWS Console:
Это создаст роль IAM без разрешений, которую смогут принимать авторизованные пользователи/роли в вашем аккаунте. Запомните Amazon Resource Name (ARN) вашей роли — он понадобится вам ниже.
Вы также можете сделать это одним шагом с помощью AWS CLI вместо AWS Console:```sh
ACCOUNT_ID=$(aws sts get-caller-identity --output text --query 'Account')
POLICY=$(echo -n '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::'; echo -n "$ACCOUNT_ID"; echo -n ':root"},"Action":"sts:AssumeRole","Condition":{}}]}')
aws iam create-role
--role-name KubernetesAdmin
--description "Kubernetes administrator role (for AWS IAM Authenticator for Kubernetes)."
--assume-role-policy-document "$POLICY"
--output text
--query 'Role.Arn'
Вы можете также пропустить этот шаг и использовать:
- Существующую роль (например, роль кросс-аккаунтного доступа).
- Пользователя IAM (см. `mapUsers` ниже).
- EC2-инстанс или федеративную роль (см. `mapRoles` ниже).
### 2. Запуск сервера
Сервер предназначен для запуска на каждом из ваших мастер-узлов в виде DaemonSet с сетевым доступом хоста, чтобы он мог открыть локальный порт localhost.
Пример конфигурации ConfigMap и DaemonSet см. в [`deploy/example.yaml`](https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/HEAD/deploy/example.yaml).
Перед применением обновите эти значения для вашего кластера:
- Замените плейсхолдеры IAM ARN (`arn:aws:iam::000000000000:...`) в `config.yaml`.
- Установите `clusterID` на уникальное значение для вашего кластера.
- Проверьте, что правила планирования DaemonSet соответствуют меткам/taints ваших control-plane узлов.
Затем разверните его:```sh
kubectl apply -f deploy/example.yaml
kubectl -n kube-system rollout status daemonset/aws-iam-authenticator
kubectl -n kube-system get pods -l k8s-app=aws-iam-authenticator
Когда под запущен на узле control-plane, aws-iam-authenticator server создаст webhook kubeconfig на хосте по пути /etc/kubernetes/aws-iam-authenticator/kubeconfig.yaml (или по пути, заданному через --generate-kubeconfig).
Если вы создаёте автоматический установщик, вы также можете легко предварительно сгенерировать сертификат, ключ и файлы webhook kubeconfig с помощью aws-iam-authenticator init.
Эта команда сгенерирует файлы и разместит их в настроенных выходных каталогах.
Вы можете запустить её на каждом master-узле перед запуском API-сервера. Вы также можете сгенерировать их до подготовки master-узлов и установить их в соответствующих путях хоста.
Если вы не сгенерируете файлы заранее, aws-iam-authenticator server создаст их по требованию.
Это работает, но требует перезапуска Kubernetes API-сервера после установки.
API Kubernetes интегрируется с AWS IAM Authenticator for Kubernetes с помощью webhook-аутентификации по токену.
При запуске aws-iam-authenticator server будет создан файл конфигурации webhook и сохранён в файловой системе хоста.
Вам нужно добавить один дополнительный флаг в конфигурацию вашего API-сервера:```
--authentication-token-webhook-config-file=/etc/kubernetes/aws-iam-authenticator/kubeconfig.yaml
На многих кластерах сервер API запускается как статический под.
Вы можете добавить флаг в `/etc/kubernetes/manifests/kube-apiserver.yaml`.
Убедитесь, что каталог хоста `/etc/kubernetes/aws-iam-authenticator/` смонтирован в под вашего сервера API.
Возможно, вам также потребуется перезапустить демон kubelet на главном узле, чтобы применить обновлённое определение статического пода:```
systemctl restart kubelet.service
По умолчанию сервер берёт сопоставления исключительно из полей mapUsers и mapRoles своего конфигурационного файла. Подробности см. в разделе Полный формат конфигурации ниже.
С помощью флага --backend-mode можно настроить сервер на получение сопоставлений из двух дополнительных бэкендов: ConfigMap в стиле EKS (--backend-mode=EKSConfigMap) или пользовательских ресурсов IAMIdentityMapping (--backend-mode=CRD). Бэкенд по умолчанию — конфигурационный файл сервера, смонтированный подом сервера, — соответствует значению --backend-mode=MountedFile.
Вы можете передать список этих бэкендов через запятую, чтобы сервер искал сопоставления в них по порядку. Например, с --backend-mode=EKSConfigMap,MountedFile сервер сначала будет искать сопоставления в ConfigMap в стиле EKS, а затем, если не найдёт сопоставление для указанной роли/пользователя IAM, — в конфигурационном файле сервера. Если сопоставление для одной и той же роли/пользователя IAM существует в нескольких бэкендах, сервер использует сопоставление из бэкенда, который идёт первым в списке, разделённом запятыми. В этом примере, если сопоставление найдено в EKS ConfigMap, оно будет использовано независимо от того, существует ли дублирующее или конфликтующее сопоставление в конфигурационном файле сервера.
Обратите внимание: при указании одного бэкенда сервер будет только брать сопоставления из него и игнорировать остальные, даже если они существуют. Например, с --backend-mode=CRD сервер будет только брать сопоставления из IAMIdentityMappings и игнорировать смонтированный файл и EKS ConfigMap.
MountedFileЭто бэкенд сопоставлений по умолчанию, и его достаточно для большинства пользователей. Подробности см. в разделе Полный формат конфигурации ниже.
CRD (альфа)Этот бэкенд представляет каждое сопоставление IAM как IAMIdentityMapping — пользовательский ресурс Kubernetes. Такой подход позволяет поддерживать сопоставления нативно для Kubernetes с помощью kubectl или API. Кроме того, синтаксические ошибки (например, в YAML с неправильными отступами) легче выявляются и не повлияют на все сопоставления.
Чтобы настроить CRD IAMIdentityMapping, сначала нужно выполнить apply манифеста CRD:```
kubectl apply -f deploy/iamidentitymapping.yaml
После развёртывания CRD вы можете создавать пользовательские ресурсы, которые моделируют ваши
IAM-идентичности. См.
[`./deploy/example-iamidentitymapping.yaml`](https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/HEAD/deploy/example-iamidentitymapping.yaml):```
---
apiVersion: iamauthenticator.k8s.aws/v1alpha1
kind: IAMIdentityMapping
metadata:
name: kubernetes-admin
spec:
# Arn of the User or Role to be allowed to authenticate
arn: arn:aws:iam::XXXXXXXXXXXX:user/KubernetesAdmin
# Username that Kubernetes will see the user as, this is useful for setting
# up allowed specific permissions for different users
username: kubernetes-admin
# Groups to be attached to your users/roles. For example `system:masters` to
# create cluster admin, or `system:nodes`, `system:bootstrappers` for nodes to
# access the API server.
groups:
- system:masters
EKSConfigMapConfigMap kube-system/aws-auth в стиле EKS используется в качестве бэкенда.
Ожидается, что ConfigMap имеет точно такой же формат, как в кластерах EKS:
https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html. Это
полезно, если вы мигрируете с/на EKS и хотите сохранить свои сопоставления, или
запускаете EKS вместе с другими кластерами AWS и хотите иметь одинаковые
сопоставления в каждом из них.
DynamicFileЛокальный файл, указанный в cfg.dynamicfilepath, может служить бэкендом. Ожидается, что содержимое файла имеет точно такой же формат, как и EKSConfigMap. При каждом изменении содержимого этого файла аутентификатор автоматически перезагружает его. Это обеспечивает большую гибкость при управлении сопоставлениями ARN.
Смотрите https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/master/hack/dev/authenticator_with_dynamicfile_mode.yaml о том, как настроить режим DynamicFile.
Выполните make e2e RUNNER=kind, чтобы поиграть с kind-кластером с включённым режимом DynamicFile.
aws-iam-authenticator может поддерживать зарезервированный префикс для имени пользователя k8s. Если зарезервированный префикс задан, то имя пользователя с зарезервированным префиксом не будет аутентифицировано с ошибкой "username must not begin with with the following prefixes:".
Смотрите https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/master/hack/dev/authenticator_with_dynamicfile_mode.yaml о том, как настроить зарезервированный префикс.
Наконец, когда сервер настроен, вам потребуется аутентифицироваться.
Вам по-прежнему понадобится kubeconfig, содержащий публичные данные о вашем кластере (сертификат CA кластера, адрес конечной точки).
Однако раздел users вашей конфигурации должен включать раздел exec (обратитесь к документации по credential plugin):```yaml
users:
Это означает, что `kubeconfig` — это полностью открытые данные, и его можно распространять среди всех пользователей Authenticator.
Возможно, имеет смысл загрузить его в доверенное публичное место, например в AWS S3.
Убедитесь, что у вас установлен бинарный файл `aws-iam-authenticator`.
Установить его можно с помощью `go install sigs.k8s.io/aws-iam-authenticator/cmd/aws-iam-authenticator@latest`.
Для аутентификации выполните `kubectl --kubeconfig /path/to/kubeconfig" [...]`.
kubectl выполнит `exec` бинарного файла `aws-iam-authenticator` с параметрами, указанными в вашем kubeconfig, который сгенерирует токен и передаст его серверу API.
Токен действителен в течение 15 минут (минимальное значение, разрешённое AWS) и может использоваться повторно несколько раз.
Вы также можете указать имя сеанса при генерации токена, включив параметр `--session-name or -s`. Этот параметр нельзя использовать вместе с `--forward-session-name`.
Вы также можете опустить `-r ROLE_ARN`, чтобы подписать токен с использованием ваших существующих учётных данных, не принимая выделенную роль.
Это полезно, если вы хотите аутентифицироваться напрямую как пользователь IAM или с использованием роли инстанса EC2 или федеративной роли.
## Использование Kops
Кластеры, управляемые [Kops](https://github.com/kubernetes/kops), могут быть настроены на использование Authenticator. Инструкции по использованию см. в [документации Kops](https://kops.sigs.k8s.io/authentication/#aws-iam-authenticator).
## Как это работает?
Он работает через конечную точку API AWS [`sts:GetCallerIdentity`](https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html).
Эта конечная точка возвращает информацию о любых учётных данных AWS IAM, которые вы используете для подключения к ней.
#### Клиентская сторона (`aws-iam-authenticator token`)
Мы используем этот API несколько необычным образом: клиент Authenticator генерирует и предварительно подписывает запрос к конечной точке.
Мы сериализуем этот запрос в токен, который может пройти через систему аутентификации Kubernetes.
#### Серверная сторона (`aws-iam-authenticator server`)
Токен передаётся через сервер API Kubernetes на конечную точку `/authenticate` сервера Authenticator через конфигурацию вебхука.
Сервер Authenticator проверяет все параметры предварительно подписанного запроса, чтобы убедиться, что ничего не выглядит подозрительно.
Затем он отправляет запрос на настоящий сервер `https://sts.amazonaws.com`, который проверяет HMAC-подпись клиента и возвращает информацию о пользователе.
Теперь, когда сервер знает AWS-идентичность клиента, он преобразует эту идентичность в пользователя Kubernetes и группы с помощью простого статического сопоставления.
Этот механизм заимствован с некоторыми изменениями из [Vault](https://www.vaultproject.io/docs/auth/aws.html#iam-auth-method).
## Что такое идентификатор кластера?
Идентификатор кластера Authenticator — это уникальный идентификатор для каждого кластера, который предотвращает определённые атаки повторного воспроизведения.
В частности, он не позволяет одному серверу Authenticator (например, в среде разработки) использовать токен клиента для аутентификации на другом сервере Authenticator в другом кластере.
Идентификатор кластера действительно должен быть уникальным для каждого кластера, но ему не обязательно быть секретом.
Некоторые удачные варианты:
- Случайный ID, например из `openssl rand 16 -hex`
- Доменное имя вашего сервера API Kubernetes
[Документация Vault](https://www.vaultproject.io/docs/auth/aws.html#iam-auth-method) также объясняет эту атаку (см. `X-Vault-AWS-IAM-Server-ID`).
## Указание учётных данных и использование профилей AWS
Учётные данные для использования с `aws-iam-authenticator` можно указать любым из методов, доступных в
[AWS SDK for Go](https://docs.aws.amazon.com/sdk-for-go/v1/developer-guide/configuring-sdk.html#specifying-credentials).
Это включает указание учётных данных AWS с помощью переменных окружения или использование файла учётных данных.
AWS [именованные профили](https://docs.aws.amazon.com/cli/latest/userguide/cli-multiple-profiles.html) поддерживаются `aws-iam-authenticator`
через переменную окружения `AWS_PROFILE`. Например, для аутентификации с учётными данными, указанными в профиле _dev_, переменная `AWS_PROFILE` может
быть экспортирована или задана явно (например, `AWS_PROFILE=dev kubectl get all`). Если `AWS_PROFILE` не задан, используется профиль _default_.
`AWS_PROFILE` также можно указать непосредственно в файле kubeconfig
[в рамках потока `exec`](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#configuration). Например, чтобы указать,
что `aws-iam-authenticator` всегда должен использовать учётные данные из именованного профиля _dev_, ваш kubeconfig должен включать ключ `env`,
который задаёт профиль:```yaml
apiVersion: v1
clusters:
- cluster:
server: ${server}
certificate-authority-data: ${cert}
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: aws
name: aws
current-context: aws
kind: Config
preferences: {}
users:
- name: aws
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
command: aws-iam-authenticator
env:
- name: "AWS_PROFILE"
value: "dev"
args:
- "token"
- "-i"
- "mycluster"
Этот метод позволяет использовать соответствующий профиль неявно. Обратите внимание, что любые переменные окружения, установленные в рамках потока exec, будут иметь приоритет над теми, что уже заданы в вашем окружении.
Федеративные пользователи AWS часто имеют «значимый» атрибут, сопоставленный с их предполагаемой ролью, например адрес электронной почты, через конфигурацию AWS учётной записи. Эти предполагаемые сеансы имеют несколько частей, role id и caller-specified-role-name. По умолчанию, когда федеративный пользователь использует опцию --role инструмента aws-iam-authenticator для принятия новой роли, caller-specified-role-name будет преобразован в случайный токен, а role id будет перенесён во вновь принятую роль.
Использование aws-iam-authenticator token ... --forward-session-name сопоставит исходный атрибут caller-specified-role-name с новым предполагаемым сеансом STS. Это может быть полезно для быстрой попытки связать «кто выполнил действие X в кластере K8».
Обратите внимание, это не следует считать окончательным, и это необходимо перекрёстно сверять через role id (который остаётся неизменным) с журналами CloudTrail, поскольку пользователь потенциально может изменить это на стороне клиента.
Возможно отправлять запросы к Kubernetes API из клиента, находящегося вне кластера, будь то с использованием чистого Kubernetes REST API или одного из языковых Kubernetes клиентов (например, Python). Для этого необходимо создать bearer-токен, который включается в запрос к API. Этот bearer-токен требует добавить строку k8s-aws-v1. с base64-закодированной строкой подписанного HTTP-запроса к STS GetCallerIdentity Query API. Затем он отправляется в заголовке Authorization запроса. Стоит отметить, что IAM Authenticator намеренно опускает base64-заполнение, чтобы избежать любых символов =, тем самым гарантируя строку, безопасную для использования в URL. Ниже приведён пример на Python, как этот токен должен быть сконструирован:```python
import base64
import boto3
import re
from botocore.signers import RequestSigner
def get_bearer_token(cluster_id, region): STS_TOKEN_EXPIRES_IN = 60 session = boto3.session.Session()
client = session.client('sts', region_name=region)
service_id = client.meta.service_model.service_id
signer = RequestSigner(
service_id,
region,
'sts',
'v4',
session.get_credentials(),
session.events
)
params = {
'method': 'GET',
'url': 'https://sts.{}.amazonaws.com/?Action=GetCallerIdentity&Version=2011-06-15'.format(region),
'body': {},
'headers': {
'x-k8s-aws-id': cluster_id
},
'context': {}
}
signed_url = signer.generate_presigned_url(
params,
region_name=region,
expires_in=STS_TOKEN_EXPIRES_IN,
operation_name=''
)
base64_url = base64.urlsafe_b64encode(signed_url.encode('utf-8')).decode('utf-8')
# remove any base64 encoding padding:
return 'k8s-aws-v1.' + re.sub(r'=*', '', base64_url)
headers = {'Authorization': 'Bearer ' + get_bearer_token('my_cluster', 'us-east-1')}
## Устранение неполадок
Если ваш клиент завершается с ошибкой, подобной `could not get token: AccessDenied [...]`, вы можете попробовать принять роль напрямую с помощью AWS CLI:```sh
# AWS CLI version of `aws-iam-authenticator token -r arn:aws:iam::ACCOUNT:role/ROLE`:
$ aws sts assume-role --role-arn arn:aws:iam::ACCOUNT:role/ROLE --role-session-name test
If that fails, there are a few possible problems to check for:
Make sure your base AWS credentials are available in your shell (aws sts get-caller-identity can help troubleshoot this).
Make sure the target role allows your source account access (in the role trust policy).
Make sure your source principal (user/role/group) has an IAM policy that allows sts:AssumeRole for the target role.
Make sure you don't have any explicit deny policies attached to your user, group, or in AWS Organizations that would prevent the sts:AssumeRole.
Try simulating the sts:AssumeRole call in the Policy Simulator.
The client and server have the same configuration format. They can share the same exact configuration file, since there are no secrets stored in the configuration.```yaml
clusterID: my-dev-cluster.example.com
aws-iam-authenticator tokendefaultRole: arn:aws:iam::000000000000:role/KubernetesAdmin
server:
port: 21362 # (default)
stateDir: /var/aws-iam-authenticator # (default)
path where a generated webhook kubeconfig will be stored.generateKubeconfig: /etc/kubernetes/aws-iam-authenticator.kubeconfig # (default)
ec2DescribeInstancesRoleARN: arn:aws:iam::000000000000:role/DescribeInstancesRole
scrubbedAccounts:
@ characters- characters.mapRoles:
mapUsers:
mapAccounts:
backendMode:
## Разработка
См. страницу [разработка](https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/HEAD/docs/development.md).
## Сообщество, обсуждение, вклад и поддержка
Узнайте, как взаимодействовать с сообществом Kubernetes, на [странице сообщества](http://kubernetes.io/community/).
Вы можете связаться с сопровождающими этого проекта:
- [Slack](https://kubernetes.slack.com/messages/sig-aws)
- [Список рассылки](https://groups.google.com/forum/#!forum/kubernetes-sig-aws)
### Кодекс поведения
Участие в сообществе Kubernetes регулируется [Кодексом поведения Kubernetes](https://github.com/kubernetes-sigs/aws-iam-authenticator/blob/HEAD/code-of-conduct.md).