【问题标题】:RBAC (Role Binding Access Control) on K3sK3s 上的 RBAC(角色绑定访问控制)
【发布时间】:2021-07-16 11:36:48
【问题描述】:

在 kubernetes(其中this one 对我来说是最透明的)上观看了有关 RBAC(基于角色的访问控制)的视频后,我已经按照这些步骤进行操作,但是在 k3s 上,而不是在 k8s 上,因为所有消息来源都暗示.据我所知(不工作),问题不在于实际的角色绑定过程,而在于 API 服务未确认的 x509 用户证书

$ kubectl get pods --kubeconfig userkubeconfig

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

也没有在Rancher's wiki 上记录关于 K3s 的安全性(虽然记录在他们的 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) 下,但是基于 this 似乎在 /var/lib/rancher/k3s/server/ tls/ (server-ca.crt & server-ca.key).

  1. 来自 ca 证书的 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 question 提出了解决问题的方法,但是在 github 提要之后,它或多或少地归结为这里遵循的相同方法(除非我遗漏了什么)?

【问题讨论】:

  • 您是否可以创建CertificateSigningRequest 而不是手动签署 csr ?
  • 非常有趣的@matt_j,到目前为止还没有看到这方面的实现。我使用 serviceAccounts 解决了这个问题(我将详细说明),但也很想给你的建议一个古怪。似乎足够前卫。 (1) 创建密钥+CSR。 (2) 通过 kubectl 添加为 CSR 对象,并批准。 (3) 将 crt 添加到 kubeconfig.... 如果您知道有关此方法的任何好的教程,请您也分享一下吗?。

标签: kubernetes rancher k3s kubernetes-rbac


【解决方案1】:

我们可以在Kubernetes Certificate Signing Requests documentation 中找到:

需要几个步骤才能让普通用户能够验证和调用 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 并通过kubectl 将其提交到Kubernetes 集群。

# 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 文件中(参见:Add to 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 权限)。

【讨论】:

    【解决方案2】:

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

    1. 服务帐号创建

    //kubectl create serviceaccount name -n namespace

    $ kubectl create serviceaccount 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
    

    users部分,可以用token替换证书数据:

    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 获取 pods --kubeconfig

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

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

    $ kubectl 获取命名空间 --kubeconfig

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

    【讨论】:

      猜你喜欢
      • 2016-10-08
      • 2011-03-18
      • 2014-12-26
      • 2015-02-16
      • 2017-02-06
      • 2014-01-25
      • 2012-09-14
      • 2020-05-23
      • 1970-01-01
      相关资源
      最近更新 更多