从签发用户证书认识Kubernetes的用户认证

Kubernetes 用户认证

  1. 从Dashboard鉴权认识Kubernetes的用户认证
  2. 从签发用户证书认识Kubernetes的用户认证

接上篇从Dashboard鉴权认识Kubernetes的用户认证,我们通过给普通用户签发证书,来认识Kubernetes用户认证。

请注意!本文可以作为签发证书的教程,但只需要参照章节1.1、1.2、3.1、3.2.1。其他内容仅为测试内容。


目录

1. 使用CertificateSigningRequest方式自动签发证书

这是k8s集群的证书签发的标准动作,按照下面的步骤操作,你将获得一个用户名为dave,组名为foo的用户,证书有效期一天。

1. 创建私钥和证书请求文件

openssl csr
#创建用户私钥
openssl genrsa -out dave.key 2048
#证书请求文件
req -new -key dave.key -out dave.csr -subj /CN=dave/O=foo/C=CN

2. CertificateSigningRequest(证书签发请求)

签发申请
CSR=`cat dave.csr | base64 | tr -d "\n"`
#提交证书签发申请
cat <<EOF | kubectl apply -f -
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: dave
spec:
request: $CSR
signerName: kubernetes.io/kube-apiserver-client
expirationSeconds: 86400
usages:
- client auth
EOF
获取证书请求记录,验证是否提交成功
dama@node1:~/tmp$ kubectl get csr
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
dave 5s kubernetes.io/kube-apiserver-client system:serviceaccount:kubernetes-dashboard:admin-user 24h Pending
批准 CSR
kubectl certificate approve dave

再次获取CSR列表,dave的请求状态已经变更为Approved,Issued

导出证书
kubectl get csr dave -o jsonpath='{.status.certificate}' | base64 -d > dave.crt
验证证书信息
dama@node1:~/tmp$ openssl x509 -in dave.crt -noout -subject -dates
subject=C = CN, O = foo, CN = dave
notBefore=Sep 20 08:51:51 2023 GMT
notAfter=Sep 21 08:51:51 2023 GMT

证书已经签发成功了,有效期1天

2. 使用集群CA手动签发

除了使用CertificateSigningRequest签发证书,我们还可以使用集群CA手动签发证书。这个签发证书与普通证书签发过程无异。

1. 创建私钥和证书请求文件

openssl csr
#创建用户私钥
openssl genrsa -out jane.key 2048
#证书请求文件
req -new -key jane.key -out jane.csr -subj /CN=jane/O=foo/C=CN

2. 使用集群CA证书签发客户证书

openssl new cert
sudo openssl  x509 -req -in jane.csr -CA /etc/kubernetes/pki/ca.crt -CAkey /etc/kubernetes/pki/ca.key -CAcreateserial -out jane.crt -days 1
验证证书信息
dama@node1:~/tmp$ openssl x509 -in jane.crt -noout -subject -dates
subject=CN = jane, O = foo, C = CN
notBefore=Sep 20 09:11:28 2023 GMT
notAfter=Sep 21 09:11:28 2023 GMT

证书已经签发成功了,有效期1天

3. 用户权限设置

1. 配置kubeconfig

.kube/config
#添加dave到kubeconfig
kubectl config set-credentials dave \
--client-certificate=dave.crt --client-key=dave.key \
--embed-certs && \
kubectl config set-context foo-dave --user=dave --cluster=kubernetes

#添加jane到kubeconfig
kubectl config set-credentials jane \
--client-certificate=jane.crt --client-key=jane.key \
--embed-certs && \
kubectl config set-context foo-jane --user=jane --cluster=kubernetes
验证配置
dama@node1:~/tmp$ kubectl config view
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: DATA+OMITTED
server: https://127.0.0.1:6443
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: admin-user
name: dashboard
- context:
cluster: kubernetes
user: jane
name: foo-jane
- context:
cluster: kubernetes
user: dave
name: foo-dave
- context:
cluster: kubernetes
namespace: qietv
user: admin-user
name: godev
current-context: dashboard
kind: Config
preferences: {}
users:
- name: admin-user
user:
token: REDACTED
- name: jane
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED
- name: dave
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED
- name: godev
user:
client-certificate-data: DATA+OMITTED
client-key-data: DATA+OMITTED

2. 配置用户权限

Kubernetes鉴权游RBAC、ABAC、Node三种。基于角色(Role)的访问控制(RBAC)是最常用的方式,权限控制力度可以是用户可以是用户组。

1. 使用Role和RoleBinding设置dave的权限

案例中dave拥有对daveown Namespace的全部权限

创建namespace
kubectl create ns daveown
创建Role
cat << EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: daveown
name: superdave
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]
EOF
创建RoleBinding
cat << EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
# 此角色绑定允许 "dave"
kind: RoleBinding
metadata:
name: dave-can-do-everything
namespace: daveown
subjects:
- kind: User
name: dave
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role # 此字段必须是 Role 或 ClusterRole
name: superdave # 此字段必须与你要绑定的 Role 或 ClusterRole 的名称匹配
apiGroup: rbac.authorization.k8s.io
EOF
验证dave的权限
kubectl config use-context foo-dave && \
kubectl get pod -n daveown && \
cat << EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: daveown
spec:
containers:
- image: busybox
command:
- sleep
- "3600"
imagePullPolicy: IfNotPresent
name: busybox
restartPolicy: Always
EOF
busybox pod created by dave
kubectl get pod -n daveown
2. 修改RoleBinding是jane拥有相同的权限
创建RoleBinding
cat << EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
# 此角色绑定允许 "dave"
kind: RoleBinding
metadata:
name: dave-can-do-everything
namespace: daveown
subjects:
- kind: User
name: dave
apiGroup: rbac.authorization.k8s.io
#!注意这里,jane和dave都在foo用户组
- kind: Group
name: foo
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role # 此字段必须是 Role 或 ClusterRole
name: superdave # 此字段必须与你要绑定的 Role 或 ClusterRole 的名称匹配
apiGroup: rbac.authorization.k8s.io
EOF

修改完的RoleBinding,是foo组所有用户拥有了daveown的所有操作权限。

验证jane的权限
dama@node1:~$ kubectl config use-context foo-jane && \
> kubectl get pod -n daveown
Switched to context "foo-jane".
NAME READY STATUS RESTARTS AGE
busybox 1/1 Running 0 10m
3. 配置jane拥有集群所有pod的访问权限

这里采用RBAC的另外一个资源ClusterRoleBinding。

define a new ClusterRole
cat << EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: foo-can-read-all-pods
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get","list","watch"]
EOF
ClusterRoleBinding Define
cat << EOF | kubectl apply -f -
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: foo-can-read-all-pods
subjects:
- kind: Group
name: foo
apiGroup: rbac.authorization.k8s.io
- kind: User
name: alice
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: foo-can-read-all-pods
apiGroup: rbac.authorization.k8s.io
EOF

验证jane的权限
kubectl config use-context foo-jane

dama@node1:~$ kubectl get pod --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
daveown busybox 1/1 Running 0 24m
istio-system grafana-78588947bf-9mgt6 1/1 Running 35 56d

这里可能有些名词需要解释一下
apiGroups: 可以使用的api组。
verbs: 用户可以执行的动作,包括get create list delete等。
resources:Kubernetes资源,pod service deployment等资源。
更多关于RBAC的内容可以查看Kubernetes Reference

4. 手动签名与自动签名有差异吗?

没有。
https://github.com/kubernetes/kubernetes/blob/master/pkg/controller/certificates/signer/signer.go#L195