Не авторизован для выполнения sts:AssumeRoleWithWebIdentity- 403
Я пытался запустить модуль external-dns, используя руководство, предоставленное группой k8s-sig. Я следил за каждым шагом руководства и получаю следующую ошибку.
time="2021-02-27T13:27:20Z" level=error msg="records retrieval failed: failed to list hosted zones: WebIdentityErr: failed to retrieve credentials\ncaused by: AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentity\n\tstatus code: 403, request id: 87a3ca86-ceb0-47be-8f90-25d0c2de9f48"
Я создал политику AWS IAM с помощью Terraform, и она была успешно создана. За исключением роли IAM для учетной записи службы, для которой я использовал
Но потом я получил эту статью, в которой говорится, что создание политики AWS IAM с использованием awscli устранит эту ошибку. Поэтому я удалил политику, созданную с помощью Terraform, и воссоздал ее с помощью awscli. Тем не менее, он выдает ту же ошибку.
Ниже мой внешний yaml-файл dns.
apiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
# If you're using Amazon EKS with IAM Roles for Service Accounts, specify the following annotation.
# Otherwise, you may safely omit it.
annotations:
# Substitute your account ID and IAM service role name below.
eks.amazonaws.com/role-arn: arn:aws:iam::268xxxxxxx:role/eksctl-ats-Eks1-addon-iamserviceaccoun-Role1-WMLL93xxxx
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: external-dns
rules:
- apiGroups: [""]
resources: ["services","endpoints","pods"]
verbs: ["get","watch","list"]
- apiGroups: ["extensions","networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get","watch","list"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["list","watch"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: external-dns-viewer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: external-dns
subjects:
- kind: ServiceAccount
name: external-dns
namespace: default
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: external-dns
template:
metadata:
labels:
app: external-dns
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: k8s.gcr.io/external-dns/external-dns:v0.7.6
args:
- --source=service
- --source=ingress
- --domain-filter=xyz.com # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones
- --provider=aws
- --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization
- --aws-zone-type=public # only look at public hosted zones (valid values are public, private or no value for both)
- --registry=txt
- --txt-owner-id=Z0471542U7WSPZxxxx
securityContext:
fsGroup: 65534 # For ExternalDNS to be able to read Kubernetes and AWS token files
Я чешу затылок, поскольку нигде в сети нет правильного решения этой ошибки. Надеюсь найти решение этой проблемы на этом форуме.
Конечный результат должен отображаться примерно так, как показано ниже, и заполнять записи в размещенной зоне.
time="2020-05-05T02:57:31Z" level=info msg="All records are already up to date"
9 ответов
Я тоже боролся с этой ошибкой.
Проблема заключалась в определении доверительных отношений.
В некоторых официальных руководствах по AWS (например, здесь ) вы можете увидеть следующую настройку:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::${AWS_ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"${OIDC_PROVIDER}:sub": "system:serviceaccount:<my-namespace>:<my-service-account>"
}
}
}
]
}
Вариант 1 на отказ
Моя проблема заключалась в том, что я указал неверное значение для
my-service-account
в конце
${OIDC_PROVIDER}:sub
в
Condition
часть.
Вариант 2 на отказ
После предыдущего исправления - я все еще столкнулся с той же ошибкой - она была решена, следуя этому руководству по aws, в котором показан результат использования eksctl с помощью следующей команды:
eksctl create iamserviceaccount \
--name my-serviceaccount \
--namespace <your-ns> \
--cluster <your-cluster-name> \
--attach-policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
--approve
Когда вы посмотрите на вывод на вкладке доверительных отношений в веб-консоли AWS, вы увидите, что было добавлено дополнительное условие с постфиксом
:aud
и ценность
sts.amazonaws.com
:
Так что это нужно добавить после
"${OIDC_PROVIDER}:sub"
условие.
Мне удалось получить помощь от Kubernetes Slack (привет @Rob Del), и это то, что мы придумали. В k8s rbac из статьи нет ничего плохого, проблема в том, как написана роль IAM. Я использую Terraform v0.12.24, но считаю, что что-то похожее на следующий .tf должно работать для Terraform v0.14:
data "aws_caller_identity" "current" {}
resource "aws_iam_role" "external_dns_role" {
name = "external-dns"
assume_role_policy = jsonencode({
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": format(
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:%s",
replace(
"${aws_eks_cluster.<YOUR_CLUSTER_NAME>.identity[0].oidc[0].issuer}",
"https://",
"oidc-provider/"
)
)
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
format(
"%s:sub",
trimprefix(
"${aws_eks_cluster.<YOUR_CLUSTER_NAME>.identity[0].oidc[0].issuer}",
"https://"
)
) : "system:serviceaccount:default:external-dns"
}
}
}
]
})
}
Приведенный выше .tf предполагает, что вы создали свой кластер eks с помощью terraform и используете манифест rbac из учебника external-dns .
Подобно тому, что описал @Rot-man, у меня был неправильный префикс для ${OIDC_PROVIDER}. Я включил префикс arn, который мне нужно было удалить, поэтому заменил:
"arn:aws:iam::123456789100:oidc-provider/oidc.eks.eu-region-1.amazonaws.com/id/5942D3B4F3E74660A6688F6D05FE40C5:sub": "system:serviceaccount:kube-system:ebs-csi-controller-sa"
с:
"oidc.eks.eu-region-1.amazonaws.com/id/5942D3B4F3E74660A6688F6D05FE40C5:sub": "system:serviceaccount:kube-system:ebs-csi-controller-sa"
в итоге:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::123456789100:oidc-provider/oidc.eks.eu-region-1.amazonaws.com/id/5942D3B4F3E74660A6688F6D05FE40C5"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"oidc.eks.eu-region-1.amazonaws.com/id/5942D3B4F3E74660A6688F6D05FE40C5:sub": "system:serviceaccount:kube-system:ebs-csi-controller-sa",
"oidc.eks.eu-region-1.amazonaws.com/id/5942D3B4F3E74660A6688F6D05FE40C5:aud": "sts.amazonaws.com"
}
}
}
]
}
Значения идентификатора учетной записи, региона и uuid в приведенных выше примерах являются поддельными, поэтому замените их собственными.
Это также может произойти, если у вас есть опечатка в роли, которую вы пытаетесь взять на себя с помощью учетной записи службы, т. е. имя роли в аннотации не соответствует имени роли в AWS IAM.
Например, если в вашей учетной записи службы была аннотация
eks.amazonaws.com/role-arn: arn:aws:iam::12345678:role/external-dns-service-account-oidc-role
Однако реальная роль в AWS принадлежала ARN.
eks.amazonaws.com/role-arn: arn:aws:iam::12345678:role/external-dns-service-account
Вы можете столкнуться с этой проблемой
Для меня проблема заключалась в том, что доверительные отношения были (правильно) настроены с использованием одного раздела , тогда как ServiceAccount был аннотирован с другим разделом, например:
...
"Principal": {
"Federated": "arn:aws-us-gov:iam::${AWS_ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}"
},
...
kind: ServiceAccount
metadata:
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::{{ .Values.aws.account }}:role/{{ .Values.aws.roleName }}
Уведомлениеarn:aws:iam
противarn:aws-us-gov:iam
Здесь у меня есть несколько возможностей.
Прежде всего, связан ли с вашим кластером поставщик OIDC? IRSA не будет работать без него.
Вы можете проверить это в консоли AWS или через интерфейс командной строки:
aws eks describe-cluster --name {name} --query "cluster.identity.oidc.issuer"
Первый
Удалить
iamserviceaccount
, воссоздайте его, удалите определение из вашего Manfiest ExternalDNS (весь первый раздел) и повторно примените его.
eksctl delete iamserviceaccount --name {name} --namespace {namespace} --cluster {cluster}
eksctl create iamserviceaccount --name {name} --namespace {namespace} --cluster
{cluster} --attach-policy-arn {policy-arn} --approve --override-existing-serviceaccounts
kubectl apply -n {namespace} -f {your-externaldns-manifest.yaml}
Возможно, возник конфликт, поскольку вы перезаписали то, что создали с помощью
eksctl createiamserviceaccount
также указав
ServiceAccount
в вашем ExternalDNS manfiest.
Второй
Обновите свой кластер до v1.19 (если его еще нет):
eksctl upgrade cluster --name {name}
покажет, что будет сделано;
eksctl upgrade cluster --name {name} --approve
сделаю это
В третьих
Некоторая документация предполагает, что помимо настройки
securityContext.fsGroup: 65534
, вам также необходимо установить
securityContext.runAsUser: 0
.
В нашем случае эта проблема возникла при использовании модуля Terraform для создания кластера eks и eksctl для создания iamserviceaccount для контроллера aws-load-balancer. Все работает отлично с первого раза. Но если вы выполняете уничтожение терраформ, вам нужно выполнить некоторую очистку, например удалить сценарий CloudFormation, созданный eksctl. Каким-то образом ситуация пересеклась, и CloudTrail передавал роль ресурса, которая больше не действовала. Поэтому проверьте аннотацию учетной записи службы, чтобы убедиться, что она действительна, и при необходимости обновите ее. Затем в моем случае я удалил и повторно развернул aws-load-balancer-controller
%> kubectl describe serviceaccount aws-load-balancer-controller -n kube-system
Name: aws-load-balancer-controller
Namespace: kube-system
Labels: app.kubernetes.io/managed-by=eksctl
Annotations: eks.amazonaws.com/role-arn: arn:aws:iam::212222224610:role/eksctl-ch-test-addon-iamserviceaccou-Role1-JQL4R3JM7I1A
Image pull secrets: <none>
Mountable secrets: aws-load-balancer-controller-token-b8hw7
Tokens: aws-load-balancer-controller-token-b8hw7
Events: <none>
%>
%> kubectl annotate --overwrite serviceaccount aws-load-balancer-controller eks.amazonaws.com/role-arn='arn:aws:iam::212222224610:role/eksctl-ch-test-addon-iamserviceaccou-Role1-17A92GGXZRY6O' -n kube-system
В моем случае я смог подключить роль oidc с политикой разрешений route53, и это устранило ошибку.
https://medium.com/swlh/amazon-eks-setup-external-dns-with-oidc-provider-and-kube2iam-f2487c77b2a1
а затем с учетной записью службы external-dns, используемой вместо роли кластера.
annotations:
# # Substitute your account ID and IAM service role name below.
eks.amazonaws.com/role-arn: arn:aws:iam::<account>:role/external-dns-service-account-oidc-role
Я боролся с аналогичной проблемой после выполнения предложенной настройкиздесь
В журналах развертывания я получил исключение, указанное ниже.
time="2021-05-10T06:40:17Z" level=error msg="records retrieval failed: failed to list hosted zones: WebIdentityErr: failed to retrieve credentials\ncaused by: AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentity\n\tstatus code: 403, request id: 3fda6c69-2a0a-4bc9-b478-521b5131af9b"
time="2021-05-10T06:41:20Z" level=error msg="records retrieval failed: failed to list hosted zones: WebIdentityErr: failed to retrieve credentials\ncaused by: AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentity\n\tstatus code: 403, request id: 7d3e07a2-c514-44fa-8e79-d49314d9adb6"
В моем случае это была проблема с неправильным именем учетной записи службы, сопоставленным с новой созданной ролью.
Вот пошаговый подход, чтобы сделать это без особых проблем.
- Создайте политику IAM
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "route53:ChangeResourceRecordSets" ], "Resource": [ "arn:aws:route53:::hostedzone/*" ] }, { "Effect": "Allow", "Action": [ "route53:ListHostedZones", "route53:ListResourceRecordSets" ], "Resource": [ "*" ] } ] }
- Создайте роль IAM и учетную запись службы для кластера EKS.
eksctl create iamserviceaccount \ --name external-dns-sa-eks \ --namespace default \ --cluster aecops-grpc-test \ --attach-policy-arn arn:aws:iam::xxxxxxxx:policy/external-dns-policy-eks \ --approve --override-existing-serviceaccounts
- Создана новая размещенная зона.
aws route53 create-hosted-zone --name " hosted.domain.com. " --caller-reference "grpc-endpoint-external-dns-test - $ (date +% s)"
- Разверните ExternalDNS после создания роли кластера и привязки роли кластера к ранее созданной учетной записи службы.
--- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRole metadata: name: external-dns rules: - apiGroups: [""] resources: ["services","endpoints","pods"] verbs: ["get","watch","list"] - apiGroups: ["extensions","networking.k8s.io"] resources: ["ingresses"] verbs: ["get","watch","list"] - apiGroups: [""] resources: ["nodes"] verbs: ["list","watch"] --- apiVersion: rbac.authorization.k8s.io/v1beta1 kind: ClusterRoleBinding metadata: name: external-dns-viewer roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: external-dns subjects: - kind: ServiceAccount name: external-dns-sa-eks namespace: default --- apiVersion: apps/v1 kind: Deployment metadata: name: external-dns spec: strategy: type: Recreate selector: matchLabels: app: external-dns template: metadata: labels: app: external-dns # If you're using kiam or kube2iam, specify the following annotation. # Otherwise, you may safely omit it. annotations: iam.amazonaws.com/role: arn:aws:iam::***********:role/eksctl-eks-cluster-name-addon-iamserviceacco-Role1-156KP94SN7D7 spec: serviceAccountName: external-dns-sa-eks containers: - name: external-dns image: k8s.gcr.io/external-dns/external-dns:v0.7.6 args: - --source=service - --source=ingress - --domain-filter=hosted.domain.com. # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones - --provider=aws - --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization - --aws-zone-type=public # only look at public hosted zones (valid values are public, private or no value for both) - --registry=txt - --txt-owner-id=my-hostedzone-identifier securityContext: fsGroup: 65534 # For ExternalDNS to be able to read Kubernetes and AWS token files
- Обновите ресурс Ingress, указав доменное имя, и повторно примените манифест.
Для входящих объектов ExternalDNS создаст DNS-запись на основе хоста, указанного для входящего объекта.
- host: myapp.hosted.domain.com
- Подтвердите новые созданные записи.
BASH-3.2$ aws route53 list-resource-record-sets --output json --hosted-zone-id "/hostedzone/Z065*********" --query "ResourceRecordSets[?Name == 'hosted.domain.com..']|[?Type == 'A']" [ { "Name": "myapp.hosted.domain.com..", "Type": "A", "AliasTarget": { "HostedZoneId": "ZCT6F*******", "DNSName": "****************.elb.ap-southeast-2.amazonaws.com.", "EvaluateTargetHealth": true } } ]