<p>after watching a view videos on RBAC (role based access control) on kubernetes (of which <a href="https://www.youtube.com/watch?v=U67OwM-e9rQ" rel="nofollow noreferrer">this one</a> was the most transparent for me), I've followed the steps, however on k3s, not k8s as all the sources imply. From what I could gather (not working), the problem isn't with the actual role binding process, but rather the x509 user cert which isn't acknowledged from the API service</p>
<blockquote>
<p>$ kubectl get pods --kubeconfig userkubeconfig</p>
<p>error: You must be logged in to the server (Unauthorized)</p>
</blockquote>
<p>Also not documented on <a href="https://rancher.com/docs/k3s/latest/en/security/" rel="nofollow noreferrer">Rancher's wiki</a> on security for K3s (while documented for their k8s implementation)?, while described for <a href="https://rancher.com/docs/rancher/v2.x/en/admin-settings/rbac/" rel="nofollow noreferrer">rancher 2.x</a> itself, not sure if it's a problem with my implementation, or a k3s &lt;-&gt; k8s thing.</p>
<pre><code>$ kubectl version --short
Client Version: v1.20.5+k3s1
Server Version: v1.20.5+k3s1

</code></pre>
<hr />
<p><strong>With duplication of the process, my steps are as follows:</strong></p>
<ol>
<li>Get k3s ca certs</li>
</ol>
<p>This was described to be under <em>/etc/kubernetes/pki</em> (k8s), however based on <a href="https://www.reddit.com/r/kubernetes/comments/f69h3y/help_k3s_where_to_find_ca_certificate_files/" rel="nofollow noreferrer">this</a> seems to be at <em>/var/lib/rancher/k3s/server/tls/ (server-ca.crt &amp; server-ca.key)</em>.</p>
<ol start="2">
<li>Gen user certs from ca certs</li>
</ol>
<pre><code>#generate user key
$ openssl genrsa -out user.key 2048

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

# 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
</code></pre>
<p>... all good:
<a href="https://i.stack.imgur.com/mBqwM.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/mBqwM.png" alt="enter image description here" /></a></p>
<ol start="3">
<li>Creating kubeConfig file for user, based on the certs:</li>
</ol>
<pre><code># 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
</code></pre>
<ul>
<li>Created config file:</li>
</ul>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: v1
clusters:
- cluster:
    certificate-authority-data: &lt;server-ca.crt base64-encoded&gt;
    server: https://&lt;k3s masterIP&gt;: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: &lt;user.crt base64-encoded&gt;
    client-key-data: &lt;user.key base64-encoded&gt;
</code></pre>
<ol start="4">
<li>Setup role &amp; roleBinding (within specified namespace 'rbac')</li>
</ol>
<ul>
<li>role</li>
</ul>
<pre class="lang-yaml prettyprint-override"><code>apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: user-rbac
  namespace: rbac
rules:
- apiGroups:
  - &quot;*&quot;
  resources:
  - pods
  verbs:
  - get
  - list
</code></pre>
<ul>
<li>roleBinding</li>
</ul>
<pre class="lang-yaml prettyprint-override"><code>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 
</code></pre>
<hr />
<p>After all of this, I get fun times of...</p>
<pre><code>$ kubectl get pods --kubeconfig userkubeconfig
error: You must be logged in to the server (Unauthorized)
</code></pre>
<p>Any suggestions please?</p>
<blockquote>
<p>Apparently this <a href="https://stackoverflow.com/questions/59940927/k3s-create-user-with-client-certificate">stackOverflow question</a> presented a solution to the problem, but following the github feed, it came more-or-less down to the same approach followed here (unless I'm missing something)?</p>
</blockquote>

<p>As we can find in the <a href="https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#normal-user" rel="nofollow noreferrer">Kubernetes Certificate Signing Requests documentation</a>:</p>
<blockquote>
<p>A few steps are required in order to get a normal user to be able to authenticate and invoke an API.</p>
</blockquote>
<p><br>I will create an example to illustrate how you can get a normal user who is able to authenticate and invoke an API (I will use the user <code>john</code> as an example).</p>
<hr />
<p>First, create PKI private key and CSR:</p>
<pre><code># openssl genrsa -out john.key 2048
</code></pre>
<p><strong>NOTE:</strong> <code>CN</code> is the name of the user and <code>O</code> is the group that this user will belong to</p>
<pre><code># openssl req -new -key john.key -out john.csr -subj &quot;/CN=john/O=group1&quot;

# ls
john.csr  john.key
</code></pre>
<p>Then create a <code>CertificateSigningRequest</code> and submit it to a Kubernetes Cluster via <code>kubectl</code>.</p>
<pre><code># cat &lt;&lt;EOF | kubectl apply -f -
&gt; apiVersion: certificates.k8s.io/v1
&gt; kind: CertificateSigningRequest
&gt; metadata:
&gt;   name: john
&gt; spec:
&gt;   groups:
&gt;   - system:authenticated
&gt;   request: $(cat john.csr | base64 | tr -d '\n')
&gt;   signerName: kubernetes.io/kube-apiserver-client
&gt;   usages:
&gt;   - client auth
&gt; 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
</code></pre>
<p>Export the issued certificate from the <code>CertificateSigningRequest</code>:</p>
<pre><code># kubectl get csr john -o jsonpath='{.status.certificate}'  | base64 -d &gt; john.crt

# ls
john.crt  john.csr  john.key
</code></pre>
<p>With the certificate created, we can define the <code>Role</code> and <code>RoleBinding</code> for this user to access Kubernetes cluster resources. I will use the <code>Role</code> and <code>RoleBinding</code> similar to yours.</p>
<pre><code># cat role.yml 
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: john-role
rules:
- apiGroups:
  - &quot;&quot;
  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
</code></pre>
<p>The last step is to add this user into the kubeconfig file (see: <a href="https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#add-to-kubeconfig" rel="nofollow noreferrer">Add to kubeconfig</a>)</p>
<pre><code># kubectl config set-credentials john --client-key=john.key --client-certificate=john.crt --embed-certs=true
User &quot;john&quot; set.

# kubectl config set-context john --cluster=default --user=john
Context &quot;john&quot; created.
</code></pre>
<p>Finally, we can change the context to <code>john</code> and check if it works as expected.</p>
<pre><code># kubectl config use-context john
Switched to context &quot;john&quot;.

# 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 &quot;john&quot; cannot create resource &quot;pods&quot; in API group &quot;&quot; in the namespace &quot;default&quot;
</code></pre>
<p>As you can see, it works as expected (user <code>john</code> only has <code>get</code> and <code>list</code> permissions).</p>
