system:node 无法通过 curl 从 apiserver 获取机密
system:node fails to get secrets from apiserver via curl
我正在为安全研究做一些 POC,尝试直接从工作节点访问名称空间机密。我在 GKE 运行 Kubernetes 1.20
上有一个集群
我是运行来自工作节点(none-master)节点的以下命令:
curl -v $APISERVER/api/v1/namespaces/default/pods/ \
--cacert /etc/srv/kubernetes/pki/ca-certificates.crt \
--cert /var/lib/kubelet/pki/kubelet-client.crt \
--key /var/lib/kubelet/pki/kubelet-client.key
而且效果很好。
但是,尝试获取机密失败:
curl -v $APISERVER/api/v1/namespaces/default/secrets/ \
--cacert /etc/srv/kubernetes/pki/ca-certificates.crt \
--cert /var/lib/kubelet/pki/kubelet-client.crt \
--key /var/lib/kubelet/pki/kubelet-client.key
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "secrets is forbidden: User \"system:node:gke-XXX--YYY\" cannot list resource \"secrets\" in API group \"\" in the namespace \"pencil\": No Object name found",
"reason": "Forbidden",
"details": {
"kind": "secrets"
},
"code": 403
查看文档,我看到节点上的 kubelet 运行 应该能够访问秘密:https://kubernetes.io/docs/reference/access-authn-authz/node/
根据我的理解,授权由 ClusterRole
system:node
支持。看着它,我确实看到它对 get
秘密有作用:
% kubectl get clusterrole system:node -o json
{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRole",
...
{
"apiGroups": [
""
],
"resources": [
"configmaps",
"secrets"
],
"verbs": [
"get",
"list",
"watch"
]
},
...
]
}
还有一些关于 kubelet 和 kube-apiserver 之间通信的更多相关文档:https://kubernetes.io/docs/concepts/architecture/control-plane-node-communication/#node-to-control-plane
- 我认为您提供的证书位置不正确。我已经使用以下证书在我的普通 kubernetes 集群上进行了相同的尝试,并且运行良好。
curl --cacert /etc/kubernetes/pki/ca.crt --cert /etc/kubernetes/pki/apiserver-kubelet-client.crt --key /etc/kubernetes/pki/apiserver-kubelet-client.key $APISERVER/api/v1/namespaces/default/secrets
这是预期的。
因为允许(通常)通过服务帐户访问机密。您需要找到安装在节点上的 pod 运行 上的服务帐户令牌。为此,您可以尝试深入研究节点上的“神奇”/proc 文件夹。如果您可以访问挂载在 pod 上的服务帐户令牌,并且该服务帐户具有访问机密的权限,则只能从节点访问机密。
深入研究 source code 后,我发现了 No Object name found
错误的含义 - 必须命名机密或配置映射才能检索。正如文档所建议的那样,如果某些 pod 映射到有问题的节点,则可以检索它们。
因此假设一些秘密 server-password
被我节点中的某个 pod 使用,以下命令按预期工作:
curl -v $APISERVER/api/v1/namespaces/default/secrets/server-password \
--cacert /etc/srv/kubernetes/pki/ca-certificates.crt \
--cert /var/lib/kubelet/pki/kubelet-client.crt \
--key /var/lib/kubelet/pki/kubelet-client.key
显然 kubectl
也可以简单地使用,它首先在 /var/lib/kubelet/pki
创建证书。
kubectl --kubeconfig /var/lib/kubelet/kubeconfig -n default get secret server-password -o json
我正在为安全研究做一些 POC,尝试直接从工作节点访问名称空间机密。我在 GKE 运行 Kubernetes 1.20
上有一个集群我是运行来自工作节点(none-master)节点的以下命令:
curl -v $APISERVER/api/v1/namespaces/default/pods/ \
--cacert /etc/srv/kubernetes/pki/ca-certificates.crt \
--cert /var/lib/kubelet/pki/kubelet-client.crt \
--key /var/lib/kubelet/pki/kubelet-client.key
而且效果很好。
但是,尝试获取机密失败:
curl -v $APISERVER/api/v1/namespaces/default/secrets/ \
--cacert /etc/srv/kubernetes/pki/ca-certificates.crt \
--cert /var/lib/kubelet/pki/kubelet-client.crt \
--key /var/lib/kubelet/pki/kubelet-client.key
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {
},
"status": "Failure",
"message": "secrets is forbidden: User \"system:node:gke-XXX--YYY\" cannot list resource \"secrets\" in API group \"\" in the namespace \"pencil\": No Object name found",
"reason": "Forbidden",
"details": {
"kind": "secrets"
},
"code": 403
查看文档,我看到节点上的 kubelet 运行 应该能够访问秘密:https://kubernetes.io/docs/reference/access-authn-authz/node/
根据我的理解,授权由 ClusterRole
system:node
支持。看着它,我确实看到它对 get
秘密有作用:
% kubectl get clusterrole system:node -o json
{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRole",
...
{
"apiGroups": [
""
],
"resources": [
"configmaps",
"secrets"
],
"verbs": [
"get",
"list",
"watch"
]
},
...
]
}
还有一些关于 kubelet 和 kube-apiserver 之间通信的更多相关文档:https://kubernetes.io/docs/concepts/architecture/control-plane-node-communication/#node-to-control-plane
- 我认为您提供的证书位置不正确。我已经使用以下证书在我的普通 kubernetes 集群上进行了相同的尝试,并且运行良好。
curl --cacert /etc/kubernetes/pki/ca.crt --cert /etc/kubernetes/pki/apiserver-kubelet-client.crt --key /etc/kubernetes/pki/apiserver-kubelet-client.key $APISERVER/api/v1/namespaces/default/secrets
这是预期的。
因为允许(通常)通过服务帐户访问机密。您需要找到安装在节点上的 pod 运行 上的服务帐户令牌。为此,您可以尝试深入研究节点上的“神奇”/proc 文件夹。如果您可以访问挂载在 pod 上的服务帐户令牌,并且该服务帐户具有访问机密的权限,则只能从节点访问机密。
深入研究 source code 后,我发现了 No Object name found
错误的含义 - 必须命名机密或配置映射才能检索。正如文档所建议的那样,如果某些 pod 映射到有问题的节点,则可以检索它们。
因此假设一些秘密 server-password
被我节点中的某个 pod 使用,以下命令按预期工作:
curl -v $APISERVER/api/v1/namespaces/default/secrets/server-password \
--cacert /etc/srv/kubernetes/pki/ca-certificates.crt \
--cert /var/lib/kubelet/pki/kubelet-client.crt \
--key /var/lib/kubelet/pki/kubelet-client.key
显然 kubectl
也可以简单地使用,它首先在 /var/lib/kubelet/pki
创建证书。
kubectl --kubeconfig /var/lib/kubelet/kubeconfig -n default get secret server-password -o json