使用ServiceAccount Token卷投影
ServiceAccount Token作為身份驗(yàn)證的憑證,使Pod中運(yùn)行的應(yīng)用程序可以安全地與Kubernetes API進(jìn)行通信。為解決傳統(tǒng)的ServiceAccount Token以Secret的形式自動(dòng)掛載到Pod中可能帶來的安全風(fēng)險(xiǎn),您可以通過ACK的服務(wù)賬戶令牌卷投影功能,使Pod以卷投影的形式將ServiceAccount Token或其他相關(guān)證書掛載到容器中,減少Secret的暴漏風(fēng)險(xiǎn)。
功能介紹
ServiceAccount是Pod和集群API Server通訊的訪問憑證。傳統(tǒng)方式下,在Pod中使用ServiceAccount可能會(huì)面臨以下挑戰(zhàn):
ServiceAccount中的JSON Web Token (JWT) 沒有綁定
audience
身份,因此所有ServiceAccount的使用者都可以彼此扮演,存在偽裝攻擊的可能。傳統(tǒng)方式下,每個(gè)ServiceAccount都需要存儲(chǔ)在一個(gè)對(duì)應(yīng)的Secret中,并且會(huì)以文件形式存儲(chǔ)在對(duì)應(yīng)的應(yīng)用節(jié)點(diǎn)上,而集群的系統(tǒng)組件在運(yùn)行過程中也會(huì)使用到一些權(quán)限很高的ServiceAccount,其增大了集群控制面的攻擊面,攻擊者可以通過獲取這些管控組件使用的ServiceAccount非法提權(quán)。
ServiceAccount中的JWT Token沒有設(shè)置過期時(shí)間,當(dāng)上述ServiceAccount泄露情況發(fā)生時(shí),您只能通過輪轉(zhuǎn)ServiceAccount的簽發(fā)私鑰來進(jìn)行防范,而client-go中還不支持這樣的自動(dòng)化流程,需要一個(gè)繁瑣的手動(dòng)運(yùn)維流程。
每一個(gè)ServiceAccount都需要?jiǎng)?chuàng)建一個(gè)與之對(duì)應(yīng)的Secret,在大規(guī)模的應(yīng)用部署下存在彈性和容量風(fēng)險(xiǎn)。
ServiceAccount Token卷投影特性用于增強(qiáng)ServiceAccount的安全性,以更安全、更靈活的方式向Pod提供ServiceAccount相關(guān)的認(rèn)證信息。ServiceAccount Token卷投影可使Pod以卷投影的形式將ServiceAccount掛載到容器中,從而避免了對(duì)Secret的依賴。
前提條件
已創(chuàng)建ACK托管集群、ACK專有集群、ACK Serverless集群,且集群版本為1.20及以上。具體操作,請(qǐng)參見創(chuàng)建ACK托管集群、創(chuàng)建ACK專有集群、創(chuàng)建集群。
已在創(chuàng)建集群的過程中啟用ServiceAccount Token卷投影功能。
1.22及以上版本的集群默認(rèn)啟用ServiceAccount Token卷投影功能,無需手動(dòng)操作。如需升級(jí)集群,請(qǐng)參見手動(dòng)升級(jí)集群。
集群的系統(tǒng)組件API Server和Controller Manager會(huì)自動(dòng)開啟綁定ServiceAccount Token卷投影的特性門控,同時(shí)在API Server的啟動(dòng)參數(shù)中增加以下配置。
參數(shù)
說明
默認(rèn)值
控制臺(tái)配置
service-account-issuer
ServiceAccount Token中的簽發(fā)身份,即Token payload中的
iss
字段。https://kubernetes.default.svc
支持。
api-audiences
合法的請(qǐng)求Token身份,用于API Server服務(wù)端認(rèn)證請(qǐng)求Token是否合法。
https://kubernetes.default.svc
支持??梢耘渲枚鄠€(gè)
audience
,通過英文半角逗號(hào),
分割。service-account-signing-key-file
Token簽名私鑰文件路徑。
/etc/kubernetes/pki/sa.key
不支持。默認(rèn)使用/etc/kubernetes/pki/sa.key,無需配置。
步驟一:創(chuàng)建一個(gè)ServiceAccount對(duì)象
每個(gè)命名空間會(huì)存在一個(gè)默認(rèn)的default
ServiceAccount,您可以通過kubectl get serviceaccounts
命令來查看。如果您需要為Pod中運(yùn)行的進(jìn)程提供其他身份標(biāo)識(shí),您可以參見以下代碼創(chuàng)建一個(gè)新的ServiceAccount。
kubectl apply -f - <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
name: build-robot
EOF
ServiceAccount創(chuàng)建完成后,您可以執(zhí)行kubectl get serviceaccounts/build-robot -o yaml
命令查看該ServiceAccount的完整信息。
步驟二:部署使用ServiceAccount Token卷投影的Pod應(yīng)用
您可以將該ServiceAccount以卷的形式投射到Pod中,Pod中的容器便可以使用該Token訪問集群API Server,并使用該ServiceAccount來進(jìn)行身份驗(yàn)證。例如,您可以指定Token的audience
、有效期限(expirationSeconds
)等屬性,將其投射到一個(gè)Pod應(yīng)用中。
使用以下示例代碼,創(chuàng)建nginx.yaml文件,其中Pod聲明了需要使用
audience
為vault
且有效期限為2個(gè)小時(shí)的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
執(zhí)行以下命令,部署使用卷投影的Pod應(yīng)用。
kubectl apply -f nginx.yaml
驗(yàn)證該P(yáng)od中掛載的Token的有效期。
執(zhí)行以下命令,確認(rèn)Pod已正常運(yùn)行。
kubectl get pod nginx
預(yù)期輸出:
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
執(zhí)行以下命令,獲取Token過期時(shí)間。
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
請(qǐng)您確保Pod中能夠?qū)崟r(shí)獲取到輪轉(zhuǎn)后最新的Token,也就是確保Pod邏輯中能夠定期重新加載目標(biāo)Token(建議為5分鐘)。官方Kubernetes在client-go 10.0.0版本后已經(jīng)支持自動(dòng)獲取最新的Token。
容器中ServiceAccount對(duì)應(yīng)的Token文件屬性不再是644,在使用綁定ServiceAccount Token卷投影時(shí),對(duì)應(yīng)的Token文件屬性已經(jīng)改為600(使用fsGroup特性時(shí)為640)。