kubernetes-对node的kubeconfig安全加固
日拱一卒,功不唐捐。大家好,目前我的kubernetes集群遇到一个安全问题,因为有些集群部署kubeadm部署方式部署的,所以有些集群中kubelet启动的时候使用的admin权限的kubeconfig,这个在生产环境下是存在安全风险的,所以考虑对其进行安全加固。
我们知道kubelet启动的时候需要传kubeconfig,如果使用的是admin权限的kubeconfig,那如果被黑客利用了有很大的安全风险,那如何解决呢?我们自然会想到要么降低权限大小要么选择加密对吧,加密自然麻烦一些你得改kubernetes代码,加密倒不是不可以,主要是还得自己维护代码,所以这里选择降低权限,选择降低node权限使其只能访问本节点数据,不能横向访问其他节点数据。其实是借助了kubernetes的Node Authorizer + NodeRestriction, 限制kubelet只能访问本node的相关资源。
完整流程
admin kubeconfig(仅用于创建 CSR) ↓ 创建 kubelet CSR(system:node:<nodeName>) ↓ approve + 签发证书 ↓ 生成 kubelet 专用 kubeconfig ↓ 重启 kubelet ↓ 删除 admin kubeconfig假设node的主机名称是 node1.localdomain
1. 控制节点参数
apiserver启用Node+RBAC
--authorization-mode=Node,RBACapiserver启用NodeRestriction Admission
--enable-admission-plugins=NodeRestrictioncontroller-manager
--cluster-signing-cert-file=/etc/kubernetes/pki/ca.pem --cluster-signing-key-file=/etc/kubernetes/pki/ca-key.pem2. 为node生成证书
生成私钥
#openssl genrsa -out kubelet.key 2048CSR 资源用于请求指定签名者签发证书,流程如下:
设置 CSR 的 CN 和 O 属性非常重要。CN 是用户的名称,O 是此用户所属的群组。 你可以参阅 RBAC 了解标准的群组。
#openssl req -new \ -key kubelet.key \ -subj "/CN=system:node:node1.localdomain/O=system:nodes" \ -out kubelet.csr创建 CertificateSigningRequest 并通过 kubectl 将其提交到 Kubernetes 集群, 并 批准CerfificateSigningRequest,确保状态是Approved,Issued
#cat <<EOF | kubectl --kubeconfig config-cluster-test apply -f - apiVersion: certificates.k8s.io/v1 kind: CertificateSigningRequest metadata: name: node1.localdomain-kubelet-client spec: signerName: kubernetes.io/kube-apiserver-client-kubelet request: $(base64 -w0 kubelet.csr) usages: - client auth - digital signature - key encipherment EOF #kubectl --kubeconfig config-cluster-test certificate approve node1.localdomain-kubelet-client证书值以 Base64 编码格式显示在.status.certificate下, 从 CertificateSigningRequest 导出已颁发的证书。
#kubectl --kubeconfig config-cluster-test get csr node1.localdomain-kubelet-client -o jsonpath='{.status.certificate}' | base64 -d > kubelet-client.crt将证书配置到 kubeconfig 中并生成新的 /var/lib/kubelet/kubeconfig
#kubectl --kubeconfig config-cluster-test config set-cluster kubernetes \ --server=https://10.236.111.57:6443 \ --certificate-authority=/etc/kubernetes/ca.crt \ --embed-certs=true \ --kubeconfig=/var/lib/kubelet/kubeconfig #kubelet-client.crt和kubelet-client.key为前面生成的私钥和crt #kubectl --kubeconfig config-cluster-test config set-credentials system:node:node1.localdomain \ --client-certificate=/var/lib/kubelet/pki/kubelet-client.crt \ --client-key=/var/lib/kubelet/pki/kubelet-client.key \ --embed-certs=true \ --kubeconfig=/var/lib/kubelet/kubeconfig #kubectl --kubeconfig config-cluster-test config set-context default \ --cluster=kubernetes \ --user=system:node:node1.localdomain \ --kubeconfig=/var/lib/kubelet/kubeconfig #kubectl --kubeconfig config-cluster-test config use-context default \ --kubeconfig=/var/lib/kubelet/kubeconfig测试
#kubectl --kubeconfig=/var/lib/kubelet/kubeconfig auth can-i get pods测试效果
实测不能list ns以及configmap/secret, 只能获取本pod相关的configmap以及pod以及secret都能获取,同时能list获取nodes以及pod,但不能exec pod.
# kubectl --kubeconfig=/var/lib/kubelet/kubeconfig -n my-test get secrets Error from server (Forbidden): secrets is forbidden: User "system:node:node1.localdomain" cannot list resource "secrets" in API group "" in the namespace "my-test": No Object name found附脚本:
#!/bin/sh #用于集群生成node证书 #------ 变量 -------# NODE_HOSTNAME=`hostname` #当前worker节点主机名 API_ENDPOINT="https://10.236.111.57:3141" #集群api的地址 CA_PUB_PATH="/etc/kubernetes/ca.crt" #集群的ca证书 ADMIN_KUBECONFIG="/root/admin-kubeconfig" #集群的admin的kubeconfig DST_KUBECONFIG_PATH="/var/lib/kubelet/kubeconfig.node.new" #最终新的kubeconfig #--------------------# #cd /root openssl genrsa -out kubelet-client.key 2048 openssl req -new \ -key kubelet-client.key \ -subj "/CN=system:node:$HOSTNAME/O=system:nodes" \ -out kubelet-client.csr kubectl --kubeconfig $ADMIN_KUBECONFIG delete csr $NODE_HOSTNAME-kubelet-client cat <<EOF | kubectl --kubeconfig $ADMIN_KUBECONFIG apply -f - apiVersion: certificates.k8s.io/v1 kind: CertificateSigningRequest metadata: name: $NODE_HOSTNAME-kubelet-client spec: signerName: kubernetes.io/kube-apiserver-client-kubelet request: $(base64 -w0 kubelet-client.csr) usages: - client auth - digital signature - key encipherment EOF sleep 3 kubectl --kubeconfig $ADMIN_KUBECONFIG certificate approve $NODE_HOSTNAME-kubelet-client kubectl --kubeconfig $ADMIN_KUBECONFIG get csr $NODE_HOSTNAME-kubelet-client -o jsonpath='{.status.certificate}' | base64 -d > kubelet-client.crt kubectl --kubeconfig $ADMIN_KUBECONFIG config set-cluster kubernetes \ --server=$API_ENDPOINT \ --certificate-authority=$CA_PUB_PATH \ --embed-certs=true \ --kubeconfig=$DST_KUBECONFIG_PATH kubectl --kubeconfig $ADMIN_KUBECONFIG config set-credentials system:node:$NODE_HOSTNAME \ --client-certificate=./kubelet-client.crt \ --client-key=./kubelet-client.key \ --embed-certs=true \ --kubeconfig=$DST_KUBECONFIG_PATH kubectl --kubeconfig $ADMIN_KUBECONFIG config set-context default \ --cluster=kubernetes \ --user=system:node:$NODE_HOSTNAME \ --kubeconfig=$DST_KUBECONFIG_PATH kubectl --kubeconfig $ADMIN_KUBECONFIG config use-context default \ --kubeconfig=$DST_KUBECONFIG_PATH #覆盖原来使用的kubeconfig cat $DST_KUBECONFIG_PATH > /etc/kubernetes/admin.config参考:
https://kubernetes.io/zh-cn/docs/tasks/tls/certificate-issue-client-csr/