Amazon EKS с поставщиком OIDC, роли IAM для учетных записей сервисов Kubernetes

Amazon EKS с поставщиком OIDC, роли IAM для учетных записей сервисов Kubernetes

by moiseevrus

Обзор

В последнем выпуске EKS (1.13 и 1.14) плоскость управления AWS Kubernetes поддерживает роли IAM для учетных записей служб. Эта функция позволяет нам связать роль IAM с учетной записью службы Kubernetes. Теперь мы можем предоставить временные учетные данные, а затем предоставить разрешения AWS для контейнеров в любом модуле, который использует эту учетную запись службы. Кроме того, нам больше не нужно предоставлять расширенные разрешения роли IAM рабочего узла, чтобы модули на этом узле могли вызывать API AWS.

Преимущества

Функция ролей IAM для учетных записей служб предоставляет следующие преимущества:

  • Наименьшие привилегии . Благодаря использованию ролей IAM для сервисных учетных записей вам больше не нужно предоставлять расширенные разрешения роли IAM рабочего узла, чтобы модули на этом узле могли вызывать API AWS. Вы можете ограничить разрешения IAM для учетной записи службы, и только модули, использующие эту учетную запись службы, имеют доступ к этим разрешениям.
  • Изоляция учетных данных . Контейнер может извлекать учетные данные только для той роли IAM, которая связана с учетной записью службы, которой он принадлежит. Контейнер никогда не имеет доступа к учетным данным, предназначенным для другого контейнера, принадлежащего другому поду.
  • Возможность аудита . Доступ и ведение журнала событий доступны через CloudTrail, чтобы помочь обеспечить ретроспективный аудит.

Технический обзор ролей IAM для учетных записей служб

AWS IAM поддерживает федеративные удостоверения с использованием OIDC. Эта функция позволяет нам аутентифицировать вызовы API AWS с помощью поддерживаемых поставщиков удостоверений и получать действительный веб-токен OIDC JSON (JWT). Вы можете передать этот токен в AssumeRoleWithWebIdentityоперацию AWS STS API и получить учетные данные временной роли IAM. Такие учетные данные можно использовать для связи с такими сервисами, как Amazon S3 и DynamoDB.

Внедрение и настройка

С помощью terraform я создал кластер EKS и провайдера OIDC:

### Backend and provider config for reference
terraform {
  required_version = "~> 0.12.12"backend "remote" {
    hostname = "app.terraform.io"
  }
}provider "aws" {
  assume_role {
    role_arn     = var.assume_role_arn
    session_name = "EKS_deployment_session_${var.tags["Environment"]}"
  }version = "~> 2.28.1"
  region  = var.region
}### EKS cluster config
resource "aws_eks_cluster" "cluster" {
  enabled_cluster_log_types = ["api", "audit", "authenticator", "controllerManager", "scheduler"]
  name                      = "${var.tags["ServiceType"]}-${var.tags["Environment"]}"
  role_arn                  = aws_iam_role.cluster.arn
  version                   = "1.14"vpc_config {
    subnet_ids              = flatten([module.vpc.public_subnets, module.vpc.private_subnets])
    security_group_ids      = [aws_security_group.cluster.id]
    endpoint_private_access = "true"
    endpoint_public_access  = "true"
  }
}### OIDC config
resource "aws_iam_openid_connect_provider" "cluster" {
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = []
  url             = aws_eks_cluster.cluster.identity.0.oidc.0.issuer
}
  1. Внешний источник данных Terrafor
### External cli kubergrunt
data "external" "thumb" {
  program = ["kubergrunt", "eks", "oidc-thumbprint", "--issuer-url", aws_eks_cluster.cluster.identity.0.oidc.0.issuer]
}### OIDC config
resource "aws_iam_openid_connect_provider" "cluster" {
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = [data.external.thumb.result.thumbprint]
  url             = aws_eks_cluster.cluster.identity.0.oidc.0.issuer
}

#!/bin/bashTHUMBPRINT=$(echo | openssl s_client -servername oidc.eks.${1}.amazonaws.com -showcerts -connect oidc.eks.${1}.amazonaws.com:443 2>&- | tac | sed -n '/-----END CERTIFICATE-----/,/-----BEGIN CERTIFICATE-----/p; /-----BEGIN CERTIFICATE-----/q' | tac | openssl x509 -fingerprint -noout | sed 's/://g' | awk -F= '{print tolower($2)}')
THUMBPRINT_JSON="{\"thumbprint\": \"${THUMBPRINT}\"}"
echo ${THUMBPRINT_JSON}
data "aws_region" "current" {}# Fetch OIDC provider thumbprint for root CA
data "external" "thumbprint" {
  program = ["./oidc-thumbprint.sh", data.aws_region.current.name]
}resource "aws_iam_openid_connect_provider" "cluster" {
  client_id_list  = ["sts.amazonaws.com"]
  thumbprint_list = concat([data.external.thumbprint.result.thumbprint], var.oidc_thumbprint_list)
  url             = aws_eks_cluster.cluster.identity.0.oidc.0.issuer
}
  • Прежде чем вы сможете получить отпечаток для OIDC IdP, вам необходимо установить OpenSSL cli.
  • Начните с URL-адреса поставщика удостоверений OIDC (например, https://server.example.com). Этот URL-адрес доступен, если щелкнуть кластер EKS в консоли AWS, а затем добавить /.well-known/openid-configuration, чтобы сформировать URL-адрес для документа конфигурации поставщика удостоверений, например следующий: Открыть этот URL-адрес в Интернете браузере, заменив его именем сервера вашего IdP.https://server.example.com/.well-known/openid-configuration
    server.example.com
  • В ответе в браузере найдите «jwks_uri». Скопируйте полное доменное имя URL. Не включайте https://путь или любой другой путь после домена верхнего уровня. То, что вам нужно, может выглядеть так:
    server.example.com/sadasdasd/keys
  • Используйте инструмент командной строки OpenSSL для выполнения следующей команды, которая использует пример вывода выше
openssl s_client -servername server.example.com/sadasdasd/keys -showcerts -connect server.example.com:443/sadasdasd/keysFor some people the following command will also work:openssl s_client -servername server.example.com -showcerts -connect server.example.com:443
  • В командном окне прокручивайте вверх, пока не увидите сертификат. Если вы видите более одного сертификата, найдите последний отображаемый сертификат (в нижней части вывода команды). Это будет сертификат корневого центра сертификации в цепочке центров сертификации. Скопируйте сертификат (включая строки -----BEGIN CERTIFICATE-----и -----END CERTIFICATE-----) и вставьте его в текстовый файл. Затем сохраните файл под именем ca_root.crt . Затем выполните следующее:
openssl x509 -in ca_root.crt -fingerprint -noout
# the above line will output something like:
# SHA1 Fingerprint=9E:99:A4:8A:99:60:B1:49:26:BB:7F:3B:02:E2:2D:A2:B0:AB:72:80# Remove the colon characters (:) from this string to produce the final thumbprint, like this:
echo -n "9E:99:A4:8A:99:60:B1:49:26:BB:7F:3B:02:E2:2D:A2:B0:AB:72:80" | sed 's|:||g'# Final output
9E99A48A9960B14926BB7F3B02E22DA2B0AB7280
### OIDC config
resource "aws_iam_openid_connect_provider" "cluster" {
client_id_list = ["sts.amazonaws.com"]
thumbprint_list = ["9E99A48A9960B14926BB7F3B02E22DA2B0AB7280"]
url = aws_eks_cluster.cluster.identity.0.oidc.0.issuer
}
data "tls_certificate" "cluster" {
  url = aws_eks_cluster.cluster.identity.0.oidc.0.issuer
}resource "aws_iam_openid_connect_provider" "cluster" {
  client_id_list = ["sts.amazonaws.com"]
  thumbprint_list = concat([data.tls_certificate.cluster.certificates.0.sha1_fingerprint], var.oidc_thumbprint_list)
  url = aws_eks_cluster.cluster.identity.0.oidc.0.issuer
}

Ограничение доступа к учетным данным профиля инстанса Amazon EC2

Перед созданием фактического примера и обновлением нашей учетной записи службы нам необходимо отключить доступ к учетным данным профиля экземпляра Amazon EC2. По умолчанию контейнеры, работающие на ваших рабочих узлах, не защищены от доступа к учетным данным, которые предоставляются в профиль экземпляра рабочего узла через сервер метаданных экземпляра Amazon EC2.

# commands block ALL containers from using the instance profile credentials
yum install -y iptables-services
iptables --insert FORWARD 1 --in-interface eni+ --destination 169.254.169.254/32 --jump DROP
iptables-save | tee /etc/sysconfig/iptables 
systemctl enable --now iptables

Настройте роль IAM и используйте ее для Amazon VPC CNI.

Подключаемый модуль Amazon VPC CNI для Kubernetes — это сетевой подключаемый модуль для организации сетей модулей в кластерах Amazon EKS. Плагин CNI отвечает за выделение IP-адресов VPC узлам Kubernetes и настройку необходимой сети для модулей на каждом узле. Плагину требуются разрешения IAM, предоставляемые управляемой политикой AWS AmazonEKS_CNI_Policy, для совершения вызовов API AWS от вашего имени. По умолчанию эта политика привязана к роли IAM вашего рабочего узла. Опять же, в этом случае я использую Terraform для создания роли IAM.

  1. IAM предполагает ролевую политику
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "${OIDC_ARN}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"${OIDC_URL}:sub": "system:serviceaccount:${NAMESPACE}:${SA_NAME}"
}
}
}
]
}
resource "aws_iam_role" "aws_node" {
  name = "${var.tags["ServiceType"]}-${var.tags["Environment"]}-aws-node"assume_role_policy =  templatefile("oidc_assume_role_policy.json", { OIDC_ARN = aws_iam_openid_connect_provider.cluster.arn, OIDC_URL = replace(aws_iam_openid_connect_provider.cluster.url, "https://", ""), NAMESPACE = "kube-system", SA_NAME = "aws-node" })tags = merge(
    var.tags,
    {
      "ServiceAccountName"      = "aws-node"
      "ServiceAccountNameSpace" = "kube-system"
    }
  )depends_on = [aws_iam_openid_connect_provider.cluster]
}resource "aws_iam_role_policy_attachment" "aws_node" {
  role       = aws_iam_role.aws_node.name
  policy_arn = "arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy"depends_on = [aws_iam_role.aws_node]
}
apiVersion: v1
kind: ServiceAccount
metadata:
name: aws-node
namespace: kube-system
apiVersion: v1
kind: ServiceAccount
metadata:
  name: aws-node
  namespace: kube-system
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::0123456789:role/eks-dev-aws-node
kubectl apply -f sa_aws_node.yaml
kubectl rollout restart -n kube-system daemonset.apps/aws-node
kubectl get -n kube-system daemonset.apps/aws-node --watch
kubectl exec -n kube-system aws-node-9rgzw env | grep AWS# Expected Output:
AWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount/token AWS_VPC_K8S_CNI_LOGLEVEL=DEBUG AWS_ROLE_ARN=arn:aws:iam::0123456789:role/eks-dev-aws-node

Вывод

Роли IAM для учетных записей служб — относительно новая функция, и многие надстройки Kubernetes могут ее не поддерживать (информация актуальна на 23.10.2019). Однако такая поддержка будет добавлена ​​относительно быстро и выпущена для общего пользования.

Статья является переводом marcincuber.medium.com

You may also like

Leave a Comment