【问题标题】:system:node 无法通过 curl 从 apiserver 获取机密
【发布时间】:2022-01-23 16:48:51
【问题描述】:

我正在为安全研究做一些 POC,尝试直接从工作节点访问命名空间机密。我在 GKE 上有一个运行 Kubernetes 1.20 的集群

我正在从工作(非主)节点运行以下命令:

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 kubelet kube-apiserver kubernetes-security kubernetes-rbac


    【解决方案1】:

    source code 中挖掘后,我发现了No Object name found 错误的含义-必须命名secrets 或configmaps 才能检索。正如文档所建议的,如果某个 pod 映射到相关节点,则可以检索它们。

    因此假设我的节点中的某个 pod 使用了一些秘密 server-password,以下命令按预期工作:

    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
    

    【讨论】:

      【解决方案2】:

      这是意料之中的。

      因为(通常)允许通过服务帐户访问机密。您需要找到挂载在节点上运行的 pod 上的服务帐户令牌。为此,您可以尝试挖掘节点上的“神奇”/proc 文件夹。如果您可以访问挂载在 pod 上的服务帐户令牌,并且该服务帐户具有访问机密的权限,则只能从节点访问机密。

      【讨论】:

      • 这与文档相矛盾。深入挖掘,我发现你确实受限于你可以阅读的秘密,但你可以阅读它们,除了节点客户端证书之外没有任何东西。
      【解决方案3】:
      • 我认为您提供的证书位置不正确。我已经在具有以下证书的普通 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
      

      【讨论】:

      • 你确定你在工作节点上看到了这个?在工作人员上,路径 /etc/kubernetes/pki 不存在,我在文件系统中找不到任何名为 apiserver-kubelet-client.crt 的文件
      • 已验证这些证书在设计上不应存在于非主节点上。 Node 只有 kubelet 客户端证书来与 kube-apiserver 通信。
      猜你喜欢
      • 1970-01-01
      • 2017-06-29
      • 1970-01-01
      • 2015-12-23
      • 2021-02-24
      • 2019-01-19
      • 2020-05-01
      • 2014-05-03
      • 1970-01-01
      相关资源
      最近更新 更多