在說明完 cloud 層的安全後,我們接下來看 cluster 層的安全,也就是 k8s,然後這裡因為我大部份是使用 google gke 所以就以上為主要的來說說。
authentication 與 authorization 應該在不少資安相關的地方都提到,所以相對的 k8s 當然也有提到這項基本的資安設定。然後這個東西的 best pracetice 一直都是所謂的 :
Principle of least privilege
就是只給足夠的權限。
然後 k8s 有提供以下兩種的 authentication :
user accounts
service account ( 注意,這不是指 gcp iam service account )
然後在 gke 中,它有多提供以下的 2 種 :
google account : 就是我們用 email 註冊的東東。
google cloud service account
然後接下來在 authorization 方面,它是使用了 Role-Based Access Control (RBAC) 這個權限機制。
然後在 k8s 中,它的 role 分成兩類 :
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: accounting
name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
resources: ["pods"]
verbs: ["get", "watch", "list"]
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
然後上面有個東西要提一下apiGroup
,它並不是可以我自自已將 pod 或啥進行分組,然後來設 apiGroups 的,它主要是識別 k8s api 的 group
,你可以使用以下指令看到 :
kubectl api-resources
然後接下來會透過所謂的ClusterRoleBinding
與 RoleBinding
將 role 設給 user 或 group,然後再 gke 中這兩個的設置的 subject type ( 就是 user ) 如下 :
Google Cloud user account
: Google Cloud registered email address
Kubernetes service account
: The name of a Kubernetes ServiceAccount object in the cluster
IAM service account
: Automatically generated IAM service account email address
Google Group address on a verified domain
: Email address of a Google Workspace Group
以下為 google 所提供的範例 :
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: pod-reader-binding
namespace: accounting
subjects:
# Google Cloud user account
- kind: User
name: janedoe@example.com
# Kubernetes service account
- kind: ServiceAccount
name: johndoe
# IAM service account
- kind: User
name: test-account@test-project.iam.gserviceaccount.com
# Google Group
- kind: Group
name: accounting-group@example.com
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
會先用 k8s rbac 看有沒有權限,如果沒有,再去看 gcp iam permission。
沒有,它只有正向列表。
沒有辦法,那是需要用另一個東西,這裡提到的比較像是某個 subject 對某些 resource 類型的操作操權
。
這個需要使用以下的方案 :
Network Policies
使用 Service 標籤選擇器
PodSecurityPolicy ( v1.25 被移除,需要用
根據以下這份文件,有以下幾點可以參考 :
https://cloud.google.com/kubernetes-engine/docs/best-practices/rbac
Use the principle of least privilege : 這個應該是每一個 Authentication and Authorization 的基本規範了。
Avoid default roles and groups : 因為這些預設的 role 與 groups 權限很廣,違反了上面那點,而且這在 owasp 的 Web Application Security Testing 中,也有提到這點。
Scope permissions to the namespace level : 基本也是為了 遵守第一點。
Don't use wildcards : 像是 *
這種就是 wildcards,然後它代表全開。
Use separate rules to grant least-privilege access to specific resources : 請看下面的範例,概念上也是設計時,role 的權限也越少越好。
Bad
- rules:
apiGroups: ["apps"]
resources: ["deployments", "daemonsets"]
verbs: ["get","list","watch"]
Good
- rules:
apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get"]
- rules:
apiGroups: ["apps"]
resources: ["daemonsets"]
verbs: ["list", "watch"]
Restrict access to specific resource instances : 就是儘可能縮小 resource 範圍,例如下面範例好的是針對這個 resourceNames 的,而不是整個 configmaps 類型的 resource。
Bad
- rules:
apiGroups: [""]
resources: ["configmaps"]
verbs: ["update"]
- rules:
apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["seccomp-high"]
verbs: ["update"]
Don't let service accounts modify RBAC resources : 因為這可能讓 hacker 透過這個 service accounts bypass 過 RBAC 想保護的東西。
Create a Kubernetes service account for each workload : 如果一個 service account 給所有個 workload 就可能會發生,不是所有的 workload 需要某一個權限,違反了 principle of least privilege。
Don't use the default service account : 就是權限太廣。
Don't automatically mount service account tokens : 如果你的 pod 不需要打 k8s api,則將 automountServiceAccountToken 設為 false ( 預設好像是 true … )
Prefer ephemeral tokens over Secret-based tokens : ephemeral tokens 就是所謂的『 短暫 token 』,就是有時效性的,因為舊有的 secret-based 的是放在 secret 而且沒有過期時間的。