Kubernetes 服务账号默认权限
Kubernetes service account default permissions
我正在试验服务帐户。我相信以下应该会产生访问错误(但不会):
apiVersion: v1
kind: ServiceAccount
metadata:
name: test-sa
---
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
serviceAccountName: test-sa
containers:
- image: alpine
name: test-container
command: [sh]
args:
- -ec
- |
apk add curl;
KUBE_NAMESPACE="$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)";
curl \
--cacert "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" \
-H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
"https://kubernetes.default.svc/api/v1/namespaces/$KUBE_NAMESPACE/services";
while true; do sleep 1; done;
kubectl apply -f test.yml
kubectl logs test-pod
我看到的是成功的服务列表,但我预计会出现权限错误,因为我从未为 test-sa
.[=22 创建任何 RoleBinding
s 或 ClusterRoleBinding
s =]
我正在努力寻找列出特定 SA 可用权限的方法,但根据 Kubernetes check serviceaccount permissions,应该可以使用:
kubectl auth can-i list services --as=system:serviceaccount:default:test-sa
> yes
虽然我怀疑该命令是否真的有效,因为我可以用任何乱码替换 test-sa
但它仍然说“是”。
根据文档,默认情况下服务帐户有 "discovery permissions given to all authenticated users"。它没有说明这实际上意味着什么,但通过更多阅读,我发现这个资源可能就是它所指的:
kubectl get clusterroles system:discovery -o yaml
> [...]
> rules:
> - nonResourceURLs:
> - /api
> - /api/*
> [...]
> verbs:
> - get
这意味着所有服务帐户对所有 API 端点都具有 get
权限,尽管“nonResourceURLs”位暗示这不适用于 API 之类的资源服务,即使那些 API 位于该路径下...... (???)
如果我完全删除 Authorization
header,我会看到预期的访问错误。但是我不明白为什么它能够使用这个空服务帐户获取数据。我的误解是什么,如何正确限制权限?
这是因为在 Docker Desktop 中,默认情况下 clusterrolebinding docker-for-desktop-binding
为创建的所有服务帐户提供 cluster-admin
角色。
有关详细信息,请查看问题 here
事实证明这是 Docker 桌面中 Mac 的 Kubernetes 支持的错误。
它会自动添加一个 ClusterRoleBinding
给 cluster-admin
到 所有服务帐户 (!)。它只是 打算 将其提供给 kube-system
命名空间内的服务帐户。
最初在docker/for-mac#3694 but fixed incorrectly. I have raised a new issue docker/for-mac#4774提出(原issue因年代久远被锁)
等待错误解决的快速修复是 运行:
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: docker-for-desktop-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:serviceaccounts:kube-system
EOF
我不知道这是否会导致未来 Docker 桌面升级出现问题,但它现在可以完成工作。
修复该问题后,上面的代码会正确给出 403 错误,并且需要以下内容来明确授予对服务资源的访问权限:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: service-reader
rules:
- apiGroups: [""]
resources: [services]
verbs: [get, list]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-sa-service-reader-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: service-reader
subjects:
- kind: ServiceAccount
name: test-sa
一个有用的调查命令是 kubectl auth can-i --list --as system:serviceaccount
,它显示恶意权限正在应用于 所有 服务帐户:
Resources Non-Resource URLs Resource Names Verbs
*.* [] [] [*]
[*] [] [*]
[...]
Docker-Desktop for Windows 存在同样的错误。
It automatically adds a ClusterRoleBinding giving cluster-admin to all service accounts (!). It only intends to give this to service accounts inside the kube-system namespace.
我正在试验服务帐户。我相信以下应该会产生访问错误(但不会):
apiVersion: v1
kind: ServiceAccount
metadata:
name: test-sa
---
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
serviceAccountName: test-sa
containers:
- image: alpine
name: test-container
command: [sh]
args:
- -ec
- |
apk add curl;
KUBE_NAMESPACE="$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)";
curl \
--cacert "/var/run/secrets/kubernetes.io/serviceaccount/ca.crt" \
-H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
"https://kubernetes.default.svc/api/v1/namespaces/$KUBE_NAMESPACE/services";
while true; do sleep 1; done;
kubectl apply -f test.yml
kubectl logs test-pod
我看到的是成功的服务列表,但我预计会出现权限错误,因为我从未为 test-sa
.[=22 创建任何 RoleBinding
s 或 ClusterRoleBinding
s =]
我正在努力寻找列出特定 SA 可用权限的方法,但根据 Kubernetes check serviceaccount permissions,应该可以使用:
kubectl auth can-i list services --as=system:serviceaccount:default:test-sa
> yes
虽然我怀疑该命令是否真的有效,因为我可以用任何乱码替换 test-sa
但它仍然说“是”。
根据文档,默认情况下服务帐户有 "discovery permissions given to all authenticated users"。它没有说明这实际上意味着什么,但通过更多阅读,我发现这个资源可能就是它所指的:
kubectl get clusterroles system:discovery -o yaml
> [...]
> rules:
> - nonResourceURLs:
> - /api
> - /api/*
> [...]
> verbs:
> - get
这意味着所有服务帐户对所有 API 端点都具有 get
权限,尽管“nonResourceURLs”位暗示这不适用于 API 之类的资源服务,即使那些 API 位于该路径下...... (???)
如果我完全删除 Authorization
header,我会看到预期的访问错误。但是我不明白为什么它能够使用这个空服务帐户获取数据。我的误解是什么,如何正确限制权限?
这是因为在 Docker Desktop 中,默认情况下 clusterrolebinding docker-for-desktop-binding
为创建的所有服务帐户提供 cluster-admin
角色。
有关详细信息,请查看问题 here
事实证明这是 Docker 桌面中 Mac 的 Kubernetes 支持的错误。
它会自动添加一个 ClusterRoleBinding
给 cluster-admin
到 所有服务帐户 (!)。它只是 打算 将其提供给 kube-system
命名空间内的服务帐户。
最初在docker/for-mac#3694 but fixed incorrectly. I have raised a new issue docker/for-mac#4774提出(原issue因年代久远被锁)
等待错误解决的快速修复是 运行:
kubectl apply -f - <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: docker-for-desktop-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: system:serviceaccounts:kube-system
EOF
我不知道这是否会导致未来 Docker 桌面升级出现问题,但它现在可以完成工作。
修复该问题后,上面的代码会正确给出 403 错误,并且需要以下内容来明确授予对服务资源的访问权限:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: service-reader
rules:
- apiGroups: [""]
resources: [services]
verbs: [get, list]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: test-sa-service-reader-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: service-reader
subjects:
- kind: ServiceAccount
name: test-sa
一个有用的调查命令是 kubectl auth can-i --list --as system:serviceaccount
,它显示恶意权限正在应用于 所有 服务帐户:
Resources Non-Resource URLs Resource Names Verbs *.* [] [] [*] [*] [] [*] [...]
Docker-Desktop for Windows 存在同样的错误。
It automatically adds a ClusterRoleBinding giving cluster-admin to all service accounts (!). It only intends to give this to service accounts inside the kube-system namespace.