2

在 kubernetes 上观看了关于 RBAC(基于角色的访问控制)的视频后(其中这个对我来说是最透明的),我遵循了这些步骤,但是在 k3s 上,而不是在所有消息来源所暗示的 k8s 上。根据我收集到的信息(不工作),问题不在于实际的角色绑定过程,而在于 API 服务未确认的 x509 用户证书

$ kubectl 获取 pods --kubeconfig userkubeconfig

错误:您必须登录到服务器(未经授权)

也没有记录在Rancher 的关于 K3s 安全性的 wiki 上(同时记录了他们的 k8s 实现)?虽然描述了 Rancher 2.x本身,但不确定这是我的实现问题,还是 k3s <-> k8s 的问题。

$ kubectl version --short
Client Version: v1.20.5+k3s1
Server Version: v1.20.5+k3s1


通过重复该过程,我的步骤如下:

  1. 获取 k3s ca 证书

这被描述为在/etc/kubernetes/pki (k8s) 下,但基于似乎在/var/lib/rancher/k3s/server/tls/ (server-ca.crt & server-ca.key) .

  1. 来自 ca certs 的 Gen 用户证书
#generate user key
$ openssl genrsa -out user.key 2048

#generate signing request from ca
openssl req -new -key user.key -out user.csr -subj "/CN=user/O=rbac"

# generate user.crt from this
openssl x509 -req -in user.csr -CA server-ca.crt -CAkey server-ca.key -CAcreateserial -out user.crt -days 365

... 都好: 在此处输入图像描述

  1. 根据证书为用户创建 kubeConfig 文件:
# Take user.crt and base64 encode to get encoded crt
cat user.crt | base64 -w0

# Take user.key and base64 encode to get encoded key
cat user.key | base64 -w0
  • 创建的配置文件:
apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: <server-ca.crt base64-encoded>
    server: https://<k3s masterIP>:6443
  name: home-pi4
contexts:
- context:
    cluster: home-pi4
    user: user
    namespace: rbac
  name: user-homepi4
current-context: user-homepi4
kind: Config
preferences: {}
users:
- name: user
  user:
    client-certificate-data: <user.crt base64-encoded>
    client-key-data: <user.key base64-encoded>
  1. 设置角色和角色绑定(在指定的命名空间“rbac”内)
  • 角色
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: user-rbac
  namespace: rbac
rules:
- apiGroups:
  - "*"
  resources:
  - pods
  verbs:
  - get
  - list
  • 角色绑定
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: user-rb
  namespace: rbac
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: user-rbac
subjects:
  apiGroup: rbac.authorization.k8s.io
  kind: User
  name: user 

在这一切之后,我得到了有趣的时光......

$ kubectl get pods --kubeconfig userkubeconfig
error: You must be logged in to the server (Unauthorized)

请问有什么建议吗?

显然这个stackOverflow问题提出了一个解决问题的方法,但是在github提要之后,它或多或少地归结为这里遵循的相同方法(除非我遗漏了什么)?

4

2 回答 2

2

我们可以在Kubernetes 证书签名请求文档中找到:

为了让普通用户能够验证和调用 API,需要执行几个步骤。


我将创建一个示例来说明如何获得能够验证和调用 API 的普通用户(我将使用该用户john作为示例)。


首先,创建 PKI 私钥和 CSR:

# openssl genrsa -out john.key 2048

注意: CN是用户的名称,并且O是该用户所属的组

# openssl req -new -key john.key -out john.csr -subj "/CN=john/O=group1"

# ls
john.csr  john.key

然后创建一个CertificateSigningRequest并通过 .将其提交到 Kubernetes 集群kubectl

# cat <<EOF | kubectl apply -f -
> apiVersion: certificates.k8s.io/v1
> kind: CertificateSigningRequest
> metadata:
>   name: john
> spec:
>   groups:
>   - system:authenticated
>   request: $(cat john.csr | base64 | tr -d '\n')
>   signerName: kubernetes.io/kube-apiserver-client
>   usages:
>   - client auth
> EOF
certificatesigningrequest.certificates.k8s.io/john created


# kubectl get csr
NAME   AGE   SIGNERNAME                            REQUESTOR      CONDITION
john   39s   kubernetes.io/kube-apiserver-client   system:admin   Pending

# kubectl certificate approve john
certificatesigningrequest.certificates.k8s.io/john approved

# kubectl get csr
NAME   AGE   SIGNERNAME                            REQUESTOR      CONDITION
john   52s   kubernetes.io/kube-apiserver-client   system:admin   Approved,Issued

从以下位置导出颁发的证书CertificateSigningRequest

# kubectl get csr john -o jsonpath='{.status.certificate}'  | base64 -d > john.crt

# ls
john.crt  john.csr  john.key

创建证书后,我们可以为该用户定义RoleRoleBinding访问 Kubernetes 集群资源。我将使用RoleRoleBinding你的类似的。

# cat role.yml 
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: john-role
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  
# kubectl apply -f role.yml 
role.rbac.authorization.k8s.io/john-role created

# cat rolebinding.yml 
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: john-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: john-role
subjects:
- apiGroup: rbac.authorization.k8s.io
  kind: User
  name: john
  
# kubectl apply -f rolebinding.yml 
rolebinding.rbac.authorization.k8s.io/john-binding created

最后一步是将此用户添加到 kubeconfig 文件中(请参阅:添加到 kubeconfig

# kubectl config set-credentials john --client-key=john.key --client-certificate=john.crt --embed-certs=true
User "john" set.

# kubectl config set-context john --cluster=default --user=john
Context "john" created.

最后,我们可以将上下文更改为john并检查它是否按预期工作。

# kubectl config use-context john
Switched to context "john".

# kubectl config current-context
john

# kubectl get pods
NAME   READY   STATUS    RESTARTS   AGE
web    1/1     Running   0          30m

# kubectl run web-2 --image=nginx
Error from server (Forbidden): pods is forbidden: User "john" cannot create resource "pods" in API group "" in the namespace "default"

如您所见,它按预期工作(用户john只有getlist权限)。

于 2021-04-30T15:46:45.040 回答
1

谢谢matt_j的例子 | 回答我的问题。将其标记为答案,因为它是我通过证书有关 RBAC 的问题的直接答案。除此之外,我还想通过服务帐户提供一个 RBAC 示例,作为变体(对于那些更喜欢特定用例的人)。

  1. 服务帐户创建

//kubectl 创建服务账户-n命名空间

$ kubectl 创建服务帐户 udef -n rbac

这将创建服务帐户 + 自动创建相应的机密 (udef-token-lhvm8)。查看 yaml 输出:

秘密名称

  1. 从创建的秘密中获取令牌:

// kubectl 描述秘密secretName -o yaml

$ kubectl 描述秘密 udef-token-lhvm8 -o yaml

secret 将包含 3 个对象,(1) ca.crt (2) 命名空间 (3) 令牌

# ... other secret context

Data
====
ca.crt: x bytes
namespace: x bytes
token: xxxx token xxxx 
  1. 将令牌放入配置文件

可以从获取您的“管理员”配置文件并输出到文件开始

// location of **k3s** kubeconfig
$ sudo cat /etc/rancher/k3s/k3s.yaml > /home/{userHomeFolder}/userKubeConfig

用户部分下,可以用令牌替换证书数据:

apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: xxx root ca cert content xxx
    server: https://<host IP>:6443
  name: home-pi4
contexts:
- context:
    cluster: home-pi4
    user: nametype
    namespace: rbac
  name: user-homepi4
current-context: user-homepi4
kind: Config
preferences: {}
users:
- name: nametype
  user:
    token: xxxx token xxxx
  1. 可以根据需要创建角色和角色绑定清单,就像之前指定的一样(在同一命名空间中的nb ),在这种情况下链接到服务帐户:
# role manifest
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: user-rbac
  namespace: rbac
rules:
- apiGroups:
  - "*"
  resources:
  - pods
  verbs:
  - get
  - list

---
# rolebinding manifest
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: user-rb
  namespace: rbac
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: user-rbac
subjects:
- kind: ServiceAccount
  name: udef
  namespace: rbac


完成此操作后,您将能够远程测试:

// 显示 pod -> 将被允许

$ kubectl 获取 pod --kubeconfig

.....提供了有效的回应

// 获取命名空间(或其他类型的命令)-> 不应该被允许

$ kubectl 获取命名空间 --kubeconfig

服务器错误(禁止):命名空间被禁止:用户 bla-bla

于 2021-05-04T09:56:00.657 回答