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)。