ServiceAccount Token作为身份验证的凭证,使Pod中运行的应用程序可以安全地与Kubernetes API进行通信。为解决传统的ServiceAccount Token以Secret的形式自动挂载到Pod中可能带来的安全风险,您可以通过ACK的服务账户令牌卷投影功能,使Pod以卷投影的形式将ServiceAccount Token或其他相关证书挂载到容器中,减少Secret的暴漏风险。
功能介绍
ServiceAccount是Pod和集群API Server通讯的访问凭证。传统方式下,在Pod中使用ServiceAccount可能会面临以下挑战:
ServiceAccount中的JSON Web Token (JWT) 没有绑定
audience
身份,因此所有ServiceAccount的使用者都可以彼此扮演,存在伪装攻击的可能。传统方式下,每个ServiceAccount都需要存储在一个对应的Secret中,并且会以文件形式存储在对应的应用节点上,而集群的系统组件在运行过程中也会使用到一些权限很高的ServiceAccount,其增大了集群控制面的攻击面,攻击者可以通过获取这些管控组件使用的ServiceAccount非法提权。
ServiceAccount中的JWT Token没有设置过期时间,当上述ServiceAccount泄露情况发生时,您只能通过轮转ServiceAccount的签发私钥来进行防范,而client-go中还不支持这样的自动化流程,需要一个繁琐的手动运维流程。
每一个ServiceAccount都需要创建一个与之对应的Secret,在大规模的应用部署下存在弹性和容量风险。
ServiceAccount Token卷投影特性用于增强ServiceAccount的安全性,以更安全、更灵活的方式向Pod提供ServiceAccount相关的认证信息。ServiceAccount Token卷投影可使Pod以卷投影的形式将ServiceAccount挂载到容器中,从而避免了对Secret的依赖。
前提条件
已创建ACK托管集群、ACK专有集群、ACK Serverless集群,且集群版本为1.20及以上。具体操作,请参见创建ACK托管集群、创建ACK专有集群、创建集群。
已在创建集群的过程中启用ServiceAccount Token卷投影功能。
1.22及以上版本的集群默认启用ServiceAccount Token卷投影功能,无需手动操作。如需升级集群,请参见手动升级集群。
集群的系统组件API Server和Controller Manager会自动开启绑定ServiceAccount Token卷投影的特性门控,同时在API Server的启动参数中增加以下配置。
参数
说明
默认值
控制台配置
service-account-issuer
ServiceAccount Token中的签发身份,即Token payload中的
iss
字段。https://kubernetes.default.svc
支持。
api-audiences
合法的请求Token身份,用于API Server服务端认证请求Token是否合法。
https://kubernetes.default.svc
支持。可以配置多个
audience
,通过英文半角逗号,
分割。service-account-signing-key-file
Token签名私钥文件路径。
/etc/kubernetes/pki/sa.key
不支持。默认使用/etc/kubernetes/pki/sa.key,无需配置。
步骤一:创建一个ServiceAccount对象
每个命名空间会存在一个默认的default
ServiceAccount,您可以通过kubectl get serviceaccounts
命令来查看。如果您需要为Pod中运行的进程提供其他身份标识,您可以参见以下代码创建一个新的ServiceAccount。
kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-robot
EOF
ServiceAccount创建完成后,您可以执行kubectl get serviceaccounts/build-robot -o yaml
命令查看该ServiceAccount的完整信息。
步骤二:部署使用ServiceAccount Token卷投影的Pod应用
您可以将该ServiceAccount以卷的形式投射到Pod中,Pod中的容器便可以使用该Token访问集群API Server,并使用该ServiceAccount来进行身份验证。例如,您可以指定Token的audience
、有效期限(expirationSeconds
)等属性,将其投射到一个Pod应用中。
使用以下示例代码,创建nginx.yaml文件,其中Pod声明了需要使用
audience
为vault
且有效期限为2个小时的ServiceAccount。apiVersion: v1 kind: Pod metadata: name: nginx spec: containers: - image: nginx name: nginx volumeMounts: - mountPath: /var/run/secrets/tokens name: vault-token serviceAccountName: build-robot volumes: - name: vault-token projected: sources: - serviceAccountToken: path: vault-token expirationSeconds: 7200 audience: vault
执行以下命令,部署使用卷投影的Pod应用。
kubectl apply -f nginx.yaml
验证该Pod中挂载的Token的有效期。
执行以下命令,确认Pod已正常运行。
kubectl get pod nginx
预期输出:
NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 3m15s
下载Pod容器中挂载的Token。
kubectl exec -t nginx -- cat /var/run/secrets/tokens/vault-token > vault-token
执行以下命令,获取Token过期时间。
cat vault-token |awk -F '.' '{print $2}' |base64 -d 2>/dev/null |jq '.exp' | xargs -I {} date -d @{}
示例输出:
一 8 26 15:45:59 CST 2024
请您确保Pod中能够实时获取到轮转后最新的Token,也就是确保Pod逻辑中能够定期重新加载目标Token(建议为5分钟)。官方Kubernetes在client-go 10.0.0版本后已经支持自动获取最新的Token。
容器中ServiceAccount对应的Token文件属性不再是644,在使用绑定ServiceAccount Token卷投影时,对应的Token文件属性已经改为600(使用fsGroup特性时为640)。