使用谷歌工作空间向亚马逊 EKS 进行身份验证

简介

亚马逊弹性 Kubernetes 服务 ( Amazon EKS ) 让使用 Kubernetes 轻松部署、管理和扩展容器化应用程序。它原生支持 亚马逊云科技 身份和访问管理 ( 亚马逊云科技 IAM ) 用户和角色作为可以对集群进行身份验证的实体。我们的许多客户使用 Active Directory、OKTA、Google Workspace 等企业身份提供商 (IdP) 来管理组织中的身份。我们经常看到我们的客户将 Amazon EKS 集群身份验证与他们的企业 IdP 集成在一起,以使用现有身份。在这篇文章中,我们将介绍将亚马逊 EKS 身份验证与 Google Workspace (以前称为 G-suite)集成的方法。亚马逊 EKS 继续使用 亚马逊云科技 IAM 对组件进行身份验证,例如在使用谷歌工作空间集成时在亚马逊 EKS 工作节点上运行的 kubelet。

如今, 谷歌 OIDC ID 令牌中没有团体索赔信息。 为了克服这一限制,我们使用 Dex 从 Google 工作空间中提取群组信息。Dex 是 OpenID Connect (OIDC) 提供商,为外部 OAuth 提供商提供获取身份的连接器。在这种情况下,将使用谷歌工作空间连接器。

解决方案概述

High level solution overview

图 1:解决方案概述

先决条件

  • 亚马逊云科技 账户
    • 亚马逊 EKS 集群
      • 按照亚马逊 EKS 文档 中的指导创建新的亚马逊 EKS 集群。
  • 您的组织的有效域名系统 (DNS) 域名和 亚马逊云科技 Certificate Manager (ACM) 中导入的 SSL 证书 。在本演练中,我们将使用 e xample.com
    • 按照本 文档 中的说明在 ACM 中导入 SSL 证书。
    • 应向 dex.example.com 和 login.example.com 颁发 SSL 证书。或者,也可以使用通配符证书。
  • Google Workspace 帐户
    • 您必须拥有组织的 Google Workspace 帐户的管理员级别访问权限才能创建新项目,或者必须具有为现有项目创建和配置 OAuth 2.0 凭据的权限。
    • 一个或多个用户
      • 在这篇文章中,我们使用 adminuser1@example.com、readonlyuser1@example.com。
    • 一个或多个群组
      • 在这篇文章中,我们使用 admins@example.com 和 readonlygroup@example.com
  • eksctl — 一个用于创建和管理亚马逊 EKS 集群的简单 CLI 工具。
  • helm — 一款简化安装和管理 Kubernetes 应用程序的工具

草率排练

第 1 步:在谷歌云平台 (GCP) 中创建 OAuth 客户端 ID

要在亚马逊 EKS 中将 Google Workspace 配置为身份提供商,您必须先为您的谷歌云平台 (GCP) 项目配置 OAuth 2.0 证书。

  • GCP 控制台中创建新项目或打开现有项目 ,请参阅 G oogle 文档以 创建和管理项目
  • 配置 OAuth 同意屏幕
    • 导航到 API 和服务 OAuth 同意 屏幕
    • 用户 类型 选择 为 “ 内部”, 然后单击 “ 创建
    • 在 “应用程序注册” 屏幕中
      • 输入应用程序名称,例如: EKS SSO
      • 提供用户支持电子邮件、开发者联系信息,然后选择 “ 保存并继续
      • 验证 Google API 的 范围是否 列出了 电子邮件 个人资料 openid 范围,如下所示。然后选择 “ 保存并继续” 。单点登录只需要这些范围。
GCP Console – OAuth Consent

图 2:GCP 控制台 — OAuth 同意

  • 创建 OAuth 客户端 ID
    • 导航至 API 和服务 凭据 屏幕 在凭据屏幕
    • 上,选择 创建 凭, 然后选择 OAuth 客户端 ID。
GCP Console – Create Credentials

图 3:GCP 控制台-创建凭证

    • 选择 应用程序类型 作为 Web 应用程序。
    • 名称 框中,输入应用程序的名称(例如,EKS)。
    • 在 “ 授权重定向 URI ” 框中,输入 https://dex.example.com/callback
    • 选择 “ 创建 ” 查看 OAuth 客户端凭证。
GCP Console - OAuth Client ID

图 4:GCP 控制台 — OAuth 客户端 ID

  • 下载并保存 OAuth 客户端 ID 和客户端密钥以供日后使用。

第 2 步:在 Google 中设置服务帐号

我们使用 服务帐号 连接 到 Google Directory 应用程序编程接口 (API),并提取有关您的用户群组成员资格的信息。

  • 按照 Google 的说明创建具有全域授权的服务帐号
    • 服务帐号分配 API 范围 时, 选择 https://www.googleapis.com/auth/admin.directory.group.readonly 范围,不选择其他任何内容。如果您分配任何其他范围,则它将无法从 API 中获取信息。
    • 以 JSON 格式 (googleAuth.json) 创建凭证并将其保存以供日后使用。
GCP Console – Service Account

图 5:GCP 控制台-服务帐户

  • 启用 Admin SDK 来查看和管理用户和群组等资源。

步骤 3:安装 亚马逊云科技 负载均衡器控制器

亚马逊云科技 负载均衡器控制器 为 Kubernetes 集群 管理 亚马逊云科技 弹性负载均衡器。当您创建 Kubernetes 入口对象时,控制器会预置 亚马逊云科技 应用程序负载均衡 器 (ALB),当您创建负载均衡器类型的 Kubernetes 服务时,控制器会预置一个 亚马逊云科技 网络负载均衡器 (NLB)。

按照亚马逊 EKS 文档 中的说明安装 亚马逊云科技 负载均衡器控制器。

第 4 步:安装 ExternalDNS 插件

或者,你可以安装 ExternalDNS 插件,以与 DNS 提供商无关的方式通过 Kubernetes 资源动态管理 DNS 记录。在本演练中,我们将使用外部 DNS 集成与 Amazon Route 53 托管区域来自动为入口主机名创建 DNS 记录。

按照 说明 在 Amazon EKS 集群上安装外部 dns 插件。

步骤 5:安装和配置 Dex

添加 Dex helm 存储库并导出包含您的值的环境变量。

helm repo add dex https://charts.dexidp.io
helm repo update
export EKS_CLUSTER_NAME=eks-demo #replace with your EKS cluster name
export ADMIN_EMAIL=admin@example.com #replace with your admin email address
export DNS_DOMAIN=example.com #replace with your organization DNS Domain
export ACM_CERTIFICATE_ARN=<<replace with ACM Certificate ARN>>
export OAUTH_CLIENT_ID=<<replace with OAuth ClientID downloaded from Step 1>>
export OAUTH_CLIENT_SECRET=<<replace with OAuth Client secret downloaded from Step 1>>
export CLIENT_ID=random-id #Random client id used to authenticate with Dex
export CLIENT_SECRET=random-secret #Random client secret used to authenticate with Dex

创建 dex-values.yaml 并将粗体文本替换为自己的值。

cat << EOF > dex-values.yaml
ingress:
  enabled: true
  className: alb
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    service.beta.kubernetes.io/aws-load-balancer-type: "external"
    alb.ingress.kubernetes.io/certificate-arn: $AWS_CERTIFICATE_ARN
    alb.ingress.kubernetes.io/healthcheck-path: /healthz
    alb.ingress.kubernetes.io/group.name: dex
  hosts:
  - host: dex.${DNS_DOMAIN}
    paths:
    - path: /
      pathType: Prefix
config:
  issuer: https://dex.${DNS_DOMAIN}
  storage:
    type: kubernetes
    config:
      inCluster: true
  oauth2:
    responseTypes: ["code", "token", "id_token"]
    skipApprovalScreen: true

  connectors:
  - type: google
    id: google
    name: google
    config:
      clientID: $OAUTH_CLIENT_ID
      clientSecret: $OAUTH_CLIENT_SECRET
      redirectURI: https://dex.$DNS_DOMAIN/callback
      # Google does not support the OpenID Connect groups claim and only supports fetching a user's group membership with a service account.
      # This service account requires an authentication JSON file and the email of a Google Workspace admin to impersonate:
      serviceAccountFilePath: /tmp/oidc/googleAuth.json
      adminEmail: $ADMIN_EMAIL

  staticClients:
  - id: $CLIENT_ID
    secret: $CLIENT_SECRET
    name: $EKS_CLUSTER_NAME
    redirectURIs:
    - https://login.$DNS_DOMAIN/callback
EOF

运行以下命令安装 Dex 头盔图表:

helm install dex dex/dex --namespace dex --create-namespace --version 0.11.1 --values dex-values.yaml

使用步骤 2 中下载的 GoogleAuth.json 创建 k8s 密钥。

kubectl -n dex create secret generic dex-google-groups-json --from-file=googleAuth.json=googleAuth.json

如上述 dex-values.yaml 中所述,Dex OIDC 连接器期望谷歌服务帐号凭证位于 /tmp/oidc/ 路径中。 让我们更新 Dex k8s 部署资源,将 dex-google-groups-json 密钥作为卷装载。以下补丁文件基于 k8s 部署对象。

cat << EOF > dex-patch.yaml
spec:
  template:
    spec:
      containers:
      - name: dex
        volumeMounts:
        - mountPath: /tmp/oidc
          name: google-json
          readOnly: true
      volumes:
      - name: google-json
        secret:
          defaultMode: 420
          secretName: dex-google-groups-json
EOF

kubectl patch deployment dex -n dex --patch-file dex-patch.yaml

在继续下一步之前,验证 dex 部署已准备就绪

NAME	 READY 	UP-TO-DATE 	AVAILABLE 	AGE
dex 	1/1   		1          		1   17m

步骤 6:安装和配置 dex-k8s-身份验证器

dex-k8s-authenticator 是一款辅助网络应用程序,它与一个或多个 Dex 身份服务 通信,生成用于创建和修改 kubeconfig 的 kub ectl 命令。运行以下命令添加 dex-k8s-authenticator 头盔存储库:

helm repo add skm https://charts.sagikazarmark.dev
helm repo update
export EKS_API_ENDPOINT=$(aws eks describe-cluster \
--name $EKS_CLUSTER_NAME \
--query 'cluster.endpoint' \
--output text)

获取 Amazon EKS 集群的客户端证书数据:

aws eks describe-cluster \
--name $EKS_CLUSTER_NAME \
--query 'cluster.certificateAuthority' \
--output text | base64 -d

输出将类似于以下内容:

-----BEGIN CERTIFICATE-----
YOUR CLIENT CERTIFICATE DATA
-----END CERTIFICATE-----

为 dex-k8s-authenticator 创建值文件,并将粗体文本替换为自己的值。

cat << EOF > dex-k8s-authenticator.yaml 
config:
  clusters:
  - name: $EKS_CLUSTER_NAME
    short_description: $EKS_CLUSTER_NAME
    description: $EKS_CLUSTER_NAME
    issuer: https://dex.$DNS_DOMAIN
    client_id: $CLIENT_ID
    client_secret: $CLIENT_SECRET
    redirect_uri: https://login.$DNS_DOMAIN/callback
    k8s_master_uri: $EKS_API_ENDPOINT
    k8s_ca_pem: |
	  -----BEGIN CERTIFICATE-----
      YOUR CLIENT CERTIFICATE DATA
      -----END CERTIFICATE-----
ingress:
  enabled: true
  className: alb
  annotations:
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/target-type: ip
    service.beta.kubernetes.io/aws-load-balancer-type: "external"
    alb.ingress.kubernetes.io/certificate-arn: $AWS_CERTIFICATE_ARN
    alb.ingress.kubernetes.io/healthcheck-path: /healthz
    alb.ingress.kubernetes.io/group.name: dex
  hosts:
  - host: login.$DNS_DOMAIN
    paths:
    - path: /
      pathType: Prefix
EOF

运行以下命令安装 dex-k8s-authenticator 头盔图:

helm install dex-k8s-authenticator \
skm/dex-k8s-authenticator \
--namespace dex \
--version 0.0.2 \
--values dex-k8s-authenticator.yaml

步骤 7:为亚马逊 EKS 集群关联 OIDC 身份提供商

运行以下命令将 OIDC 提供商配置与 Amazon EKS 集群关联起来:

export ISSUER_URL=https://dex.$DNS_DOMAIN

aws eks associate-identity-provider-config \
--cluster-name $EKS_CLUSTER_NAME\
--oidc identityProviderConfigName="dex-idp",issuerUrl=$ISSUER_URL,clientId=$CLIENT_ID,usernameClaim=email,groupsClaim=groups

等到提供商 状态为 AC TIVE, 然后继续执行下一步。您可以使用 亚马逊云科技 控制台或以下命令来检查状态。

aws eks describe-identity-provider-config \
--cluster-name $EKS_CLUSTER_NAME \
--identity-provider-config name="dex-idp",type="oidc"
--query 'identityProviderConfig.oidc.status' --output text
AWS Console - OIDC Identity Provider

图 6:亚马逊云科技 控制台 — OIDC 身份提供商

第 8 步:在 DNS 服务器中添加 DNS 记录

现在添加必要的 CNAME 记录,以便使用您的域名访问 Dex 和 Dex-K8S-Authenticator 应用程序。DNS 记录对应于安装 Dex 控制器时配置的 ALB 的完全限定域名 (FQDN)。在本演练中,我们使用外部 dns(步骤 4)与 Route 53 的集成,在 Route 53 托管区域中自动创建这些 DNS 记录,如下所示。

AWS Console – Route 53 Hosted zone

图 7:亚马逊云科技 控制台 — Route 53 托管区域

第 9 步:在 Amazon EKS 中为谷歌用户和群组创建角色和绑定

现在 EKS 集群已与 Dex OIDC 和 Google Workspace 身份验证相关联,让我们在集群中为用户和群组配置相应的基于角色的访问控制 (RBAC) 权限。为此,我们创建了两个 kubernetes 角色绑定,一个具有提升权限(集群管理员),另一个具有只读(查看)权限,并将它们与 Google Workspace 群组相关联。用你自己的值替换粗体文本。

kubectl create clusterrolebinding eksadmin-google-binding \
--clusterrole cluster-admin \
--group admins@example.com

kubectl create clusterrolebinding eksreadonly-google-binding \
--clusterrole view \
--group readonlygroup@example.com

第 10 步:登录

要测试访问权限,请打开网络浏览器并输入 dex-k8s-authenticator 网络应用程序的网址(例如 https://login.example.com/)。系统会提示你输入你的 Google 工作空间证书。

Google Workspace login

图 8:谷歌工作空间登录

继续输入电子邮件和密码以使用 Google Workspace IdP 进行身份验证。成功进行身份验证后,您将看到配置 kubectl 的说明。

kubectl instructions

图 9:kubectl 指令

步骤 11:测试访问权限

运行以下命令来验证你是否可以创建 kubernetes 对象,比如 Deployment。

kubectl auth can-i create deployment
yes

对只读组用户重复步骤 10 和 11。你会注意到只读操作成功,而创建和删除操作失败。

kubectl auth can-i get deployment
yes
kubectl auth can-i create deployment
no

此输出演示了使用 Google Workspace 群组和用户在 EKS 集群中分配 RBAC 权限的能力。

清理

为避免产生任何额外费用,请销毁您为本文中描述的解决方案而配置的所有基础架构。

删除 Dex 和 dex-k8s-身份验证器应用程序以及 ALB

helm uninstall dex-k8s-authenticator 
helm uninstall dex

删除亚马逊 EKS 集群

eksctl delete cluster --name=${EKS_CLUSTER_NAME}

删除 OAuth 客户端

打开 GCP 控制台:

  • 导航到 API 和服务 凭据 屏幕
  • 从列表中选择 OAuth 客户端 ID EKS,然后单击 “ 删除 O Auth 客户端” 按钮

删除服务账号

打开 GCP 控制台:

  • 导航到 IAM 和管理员 服务帐号 屏幕
  • 从列表中选择服务帐户,然后单击 “ 删除 ” 按钮

结论

在这篇文章中,我们展示了如何将 Amazon EKS 集群身份验证与 Google 工作空间集成。由于 Google OIDC ID 令牌中没有团体索赔信息,因此我们使用 Dex 来克服这一限制。使用 Dex OIDC 连接器,我们能够提取谷歌群组声明,并使用 k8s 原生结构(例如角色、角色绑定等)分配 RBAC 权限以进行授权。

呼吁采取行动

亚马逊云科技 的容器上详细了解支持的 容器 解决方案、客户案例研究和其他资源 。