咱們這裏使用的 AWS 徹底管理的 K8s 集羣 EKS,而且經過以下命令建立了 iamserviceaccount。html
eksctl create iamserviceaccount --name alice --namespace default \ --cluster eks --attach-policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \ --approve --override-existing-serviceaccounts
關於 IRSA 的一個架構圖大體以下:linux
在由 API Server 建立一個 pod 後,由 Self-hosted Kubernetes setup 所講,經過 CloudWatch 獲取到 API Server 的相關啓動參數:git
--service-account-key-file="[/etc/kubernetes/pki/sa.pub]" --service-account-signing-key-file=「」 --service-account-issuer="https://oidc.eks.us-east-1.amazonaws.com/id/900B62D5EA15DC82EC523AD824232853"
--service-account-key-file
是用來 verify token的;--service-account-issuer
對呀 JWT token 中的 iss claim。
service account token 是由 controller-manager 控制器簽署的,相關的私鑰在其啓動參數中,因此咱們查看其啓動參數以下:github
--service-account-private-key-file="/etc/kubernetes/pki/sa.key"
這裏的 sa.key
和sa.pub
是一對祕鑰對。web
在 token 簽署完成後,會觸發 eks-pod-identity-webhook
,這裏的 pod-identity-webhook
就相似於在 k8s 中的 Service account admission controller
,它是 apiserver 的一部分,由 eks-pod-identity-webhook
協助將相關的 Token 信息以 Projected Volume 的形式掛在到 Pod 中,並把 iam service account 中的 role-arn 和剛剛生成的 token 注入到 Pod 的環境變量AWS_WEB_IDENTITY_TOKEN_FILE
中。shell
我能夠經過查看 Pod 的 yaml 文件查看其相關信息:json
spec: containers: - command: - sh - -c - echo Hello Kubernetes! && sleep 360000 env: - name: AWS_ROLE_ARN value: arn:aws:iam::921283538843:role/eksctl-eks-addon-iamserviceaccount-default-a-Role1-SSGCB7DDESI5 - name: AWS_WEB_IDENTITY_TOKEN_FILE value: /var/run/secrets/eks.amazonaws.com/serviceaccount/token image: amazonlinux:latest imagePullPolicy: Always name: myapp resources: {} terminationMessagePath: /dev/termination-log terminationMessagePolicy: File volumeMounts: - mountPath: /var/run/secrets/kubernetes.io/serviceaccount name: alice-token-qlsjp readOnly: true - 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 - name: alice-token-qlsjp secret: defaultMode: 420 secretName: alice-token-qlsjp
能夠看到系統裏面掛載了兩個 token,api
/var/run/secrets/kubernetes.io/serviceaccount
:由 Service Account Admission Controller 建立,其屬於 Kubernetes 默認建立的 Token 配置文件。/var/run/secrets/eks.amazonaws.com/serviceaccount
:由 eks-pod-identity-webhook 協助掛載,在掛載的過程當中,向token注入了audience等參數,其中定義了 projected volume 的配置。EKS 已經幫助咱們建立好了 OIDC,經過自建 OIDC,咱們能夠了解到更多關於 OIDC 的信息,在這裏咱們是使用的最簡陋的 oidc provider 服務,只是提供了一個驗證的功能,能夠比喻爲咱們證書的頒發機構 CA。bash
在 EKS OIDC discovery 文件中,其最終將其放置於 /.well-known/openid-configuration 配置文件定義下列規範:服務器
{ "issuer": "https://oidc.eks.us-east-1.amazonaws.com/id/93BEE997ED0F1C1BA3BD6C8395BE0756", "jwks_uri": "https://oidc.eks.us-east-1.amazonaws.com/id/93BEE997ED0F1C1BA3BD6C8395BE0756/keys", "authorization_endpoint": "urn:kubernetes:programmatic_authorization", "response_types_supported": ["id_token"], "subject_types_supported": ["public"], "claims_supported": ["sub", "iss"], "id_token_signing_alg_values_supported": ["RS256"] }
以及 jwks_uri 描述 signing key 的信息,用於進行查詢驗證:
{ "keys": [{ "kty": "RSA", "e": "AQAB", "use": "sig", "kid": "22b7abf04dc344c44fb83499508a158d789d82d5", "alg": "RS256", "n": "qJj1vYyzD0CpEaU93PlPdroS_Xir23X6GdLptyCMFb5zVNoSvegTo8Bb0_zb-8-z_VYoUj-L-3q8sP6R3Hp03ozkBCKa-cQ3gtITFUuQ6UQr0oIQjeZ3etJCOt1GktXLjeYssGiW58ToiTFzqjoeqGzz2-75WS6nsFnxCyCLg-2xFq4ALFrI4fAnwKwaQKowJQDKuUA50Tqv9P9ctEclHDlVi7K3_3giyiToZtmNUn-4KpQNx-a-4I7avn8d67UybOFOdYFeDnyOe9E8Ajuis22v2CvRr7rHEFjyxVCPoT0NFqiXkQMApd-7A6Rs33kIt7STwVBWhjFT5F--BzgJfQ" }] }
經過自建過程,咱們能夠得知 oidc 的公鑰信息來自於上面的 sa.pub。
go run ./hack/self-hosted/main.go -key $PKCS_KEY | jq '.keys += [.keys[0]] | .keys[1].kid = ""' > keys.json
假如當這個 Pod 去訪問 aws s3 資源的時候,咱們發現能夠直接使用命令aws s3 ls
,由此可知,awscli 已經自動幫咱們請求了 assume-role-with-web-identity
,關於 awscli 爲何會自動請求這個接口,請參考awscli文檔。後續的資源請求會調用獲取的臨時憑證,臨時憑證的存儲位置爲 ~/.aws/cli/cache
。
咱們也可也手動去 sts 服務獲取臨時憑證,命令以下:
aws sts assume-role-with-web-identity --role-arn $AWS_ROLE_ARN --role-session-name alice --web-identity-token file://$AWS_WEB_IDENTITY_TOKEN_FILE
獲取的內容大體以下:
{ "Credentials": { "AccessKeyId": "ASIA5NAGHF6NZIPEBVGZ", "SecretAccessKey": "U5GXw/lcz0PTbHUPO+A7Rk4RbMAK9ISzdrYW9BeK", "SessionToken": "IQoJb3JpZ2luX2VjELL//////////wEaCXVzLWVhc3QtMSJIMEYCIQC7Myfzl1QvG87aAF8ZdrFACbiQbNrtzzuQfLf+QX6j4AIhAJtehbkrVMLuO7HWjzetrwkHBCGxttoGFCn8stAxfs/rKpsECCoQABoMOTIxMjgzNTM4ODQzIgxy22hqmCjadsTNf/0q+AN4hIfLXLrUtwVuysbDCuGKZByp/Ow2N/t4JaeVaN7F7qYFVMRjm2nltxc1UTsfOTlIigR6mdKqdHWX982bVlSzu95oocK4vOLcLOh4TCOTehFTnH8ghe0GMd4Pyydi5yjrSM08JRZ+ACw/7/NgZM+p8e1JWI2aLOWk66K3rTqWnKL0V2EM3d8MkVSpjRcv1Rk3j+DBnlnpD8AulTA8vxa3p2JM8jw+EHgsnFIpBoseWrOpVeY21XHkkxU8bSZCbuqWbVkrRPmNccr0Kc6MXb6jN4tXfB0/L0PjQiHqB1O74nx4f0mQGvrI8nJwAGHCRj++bOwuHG3j7CTZqrXXmzphECUKkGE0nr1zpT5CqjoZsM7e/LhDUxNznAwIpQ9AUAoi6ZMWP4wlpVOFWm/qNNZBFRX9hGb8DTLdFBgPhXB+scch52Kc/n+HYdW5sDj88eh5s9JjwR8Nst25gaVJKam++5hfIqz25PJXOXIQ51mDkY3SpvKVsa4ORXDVFJd6s+IXPpaSoqCkYfbsmXs6PVs1cnH1ZF89z2qmFalzed+QVRydQJv21j+C3wYB4foKZZpL5+qd9oXdtpBc5vHaqTbhEL9fhheCchOurTlgqLzY2PegVdzqzaCyZoL0jnEYSYXNWPGOJlIVz2cnYsW8xexh5rm1hGp7VckwsuS28AU63wF4DQFwtFbyU08QpLgBbVUpmmrG06A4Hb4ouLihGLm61LTX487gMADfoBpfMcOdLmOxKLKja1KAdtas4qHE0sovubGF5s/1ntVA44GPMIAWZlnAEf4N03YG6AbJzWxBdLZ4FZBCluLzQtm0Y2r61o92KdId5hDFF1wm/9NfH3xpi3TNW9IZbIWAan2ccoPorgZOZjqfMGqj9PDnGkVqeWX9jo6RoqFPTNigngf7FAx/kk1Q7l+eoD94P2VIKrfAAhTfGm1WPsA+1mOgzkRPGgKhbw+I+mmbloegJRY9Om8S", "Expiration": "2020-01-02T10:04:50Z" }, "SubjectFromWebIdentityToken": "system:serviceaccount:default:alice", "AssumedRoleUser": { "AssumedRoleId": "AROA5NAGHF6NZWI5VRGOR:alice", "Arn": "arn:aws:sts::921283538843:assumed-role/eksctl-eks-addon-iamserviceaccount-default-a-Role1-SSGCB7DDESI5/alice" }, "Provider": "arn:aws:iam::921283538843:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/93BEE997ED0F1C1BA3BD6C8395BE0756", "Audience": "sts.amazonaws.com" }
那麼 STS 如何與 OIDC Provider 進行驗證而且最終發佈 Secret Key 及 Access Key。
因爲 IAM Role 的設計也包含其餘Federation 驗證的機制。在前面使用 eksctl 建立的 iamserviceaccount
的時候,建立了一個 role arn:aws:iam::921283538843:role/eksctl-eks-addon-iamserviceaccount-default-a-Role1-SSGCB7DDESI5
的資源項目,例如:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Federated": "arn:aws:iam::921283538843:oidc-provider/oidc.eks.us-east-1.amazonaws.com/id/93BEE997ED0F1C1BA3BD6C8395BE0756" }, "Action": "sts:AssumeRoleWithWebIdentity", "Condition": { "StringEquals": { "oidc.eks.us-east-1.amazonaws.com/id/93BEE997ED0F1C1BA3BD6C8395BE0756:aud": "sts.amazonaws.com", "oidc.eks.us-east-1.amazonaws.com/id/93BEE997ED0F1C1BA3BD6C8395BE0756:sub": "system:serviceaccount:default:alice" } } } ] }
他信任這個 Federation 來源的用戶,只要是 token 可也經過 OIDC 的驗證,而且知足 Condition 便可,由於咱們知道,token 是由 controller-manager 經過 --service-account-private-key-file="/etc/kubernetes/pki/sa.key
簽署完成,而 OIDC 的 jwks_uri 裏面的驗證證書爲 sa.pub,這是一對祕鑰對,所以可也能夠信任 token,這是一個 json web token,咱們能夠查看其 Payload 結構信息以下:
{ "aud": [ "sts.amazonaws.com" ], "exp": 1578041687, "iat": 1577955287, "iss": "https://oidc.eks.us-east-1.amazonaws.com/id/93BEE997ED0F1C1BA3BD6C8395BE0756", "kubernetes.io": { "namespace": "default", "pod": { "name": "myapp", "uid": "873e92b0-2d3d-11ea-8820-0a64f353aa45" }, "serviceaccount": { "name": "alice", "uid": "7a58554d-2bb1-11ea-8820-0a64f353aa45" } }, "nbf": 1577955287, "sub": "system:serviceaccount:default:alice" }
一旦 Pod 與 STS 服務器節點發起 AssumeRoleWithWebIdentity 動做時,用戶端會帶入 WebIdentityToken 信息,其中 STS 會將該 Token 經由您配置的 OIDC Provider 上提供的憑證信息進行比對驗證 (keys.json),確認其您用戶端使用 Service Account Token 發起來源爲您的 OIDC Provider 所簽署識別其來源,而且,認證您在 Trust Relationship 的政策,以容許您的用戶端操做 AssumeRoleWithWebIdentity 動做而能夠獲取您對應 IAM Role 的臨時存取信息,最終返回對應的 AccessKeyID 及 SecretAccessKey 資訊,使您的用戶端可以再度使用該臨時金鑰訪問其餘 AWS 資源 (例如:S3 Bucket)
OAuth 2.0
OIDC
kube-apiserver :https://raw.githubusercontent.com/wangzan18/kubernetes-ha-binary/master/services/eks/kube-apiserver.service
kube-controller-manager:https://raw.githubusercontent.com/wangzan18/kubernetes-ha-binary/master/services/eks/kube-controller-manager.service
kube-scheduler:https://raw.githubusercontent.com/wangzan18/kubernetes-ha-binary/master/services/eks/kube-scheduler.service
參考文檔:
https://www.simpleorientedarchitecture.com/openid-connect-in-a-nutshell/
https://tools.ietf.org/html/rfc6749
https://openid.net/specs/openid-connect-core-1_0.html