K3s - create user with client certificate

1/28/2020

I've tried to create user accounts with a client certificate.

I followed two tutorials but stuck with both options in an error with the message

https://medium.com/better-programming/k8s-tips-give-access-to-your-clusterwith-a-client-certificate-dfb3b71a76fe

https://docs.bitnami.com/kubernetes/how-to/configure-rbac-in-your-kubernetes-cluster/

I set the right user, server and the right context. I set the namespace but still the same error.

> kubectl get pods
You must be logged in to the server (Unauthorized) 

Did someone already experienced something similar? Or does someone knows what i'm doing wrong?

My k3s cluster version is 1.15.4.

-- Manuel Polacek
k3s
kubectl
kubernetes

2 Answers

1/28/2020

I finally found my answer in this ticket.

https://github.com/rancher/k3s/issues/684

The user huapox posted the following code:

[root@(⎈ |default:default) sec-rbac]$ cat t2.sh 
ws=/opt/sec-rbac
day=3650

clus_name="t1.k3s"
clus_ns="default"
user="koper"
#clus_url="https://10.200.100.183:7442"
clus_url="https://server:6443"  ##
ca_path=$ws/server/tls
rm -f $ca_path/*-ca.srl

ctx=gen && mkdir -p $ws/$ctx/{kube,keys} && cd $ws/$ctx
#############
ca1=client-ca
generate="keys/u-"$user
echo -e "\033[32m#>>GEN-KEY\033[0m"
#openssl genrsa -out $generate.key 2048
openssl ecparam -name prime256v1 -genkey -noout -out $generate.key
openssl req -new -key $generate.key -out $generate.csr -subj "/CN=${user}@${clus_name}/O=key-gen"
openssl x509 -req -in $generate.csr -CA $ca_path/$ca1.crt -CAkey $ca_path/$ca1.key -CAcreateserial -out $generate.crt -days $day

#-----------
#generate=$ca_path/client-admin  ##test
ca2=server-ca
embed=false
ctx2="$user@$clus_name"
config="kube/$user.kubeconfig"
echo -e "\033[32m#>>KUBE-CONFIG\033[0m" 
kubectl --kubeconfig=$config config set-cluster $clus_name --embed-certs=$embed --server=$clus_url --certificate-authority=$ca_path/$ca2.crt
kubectl --kubeconfig=$config config set-credentials $user --embed-certs=$embed --client-certificate=$generate.crt  --client-key=$generate.key
kubectl --kubeconfig=$config config set-context $ctx2 --cluster=$clus_name --namespace=$clus_ns --user=$user
kubectl --kubeconfig=$config config set current-context $ctx2
kubectl --kubeconfig=$config --context=$ctx2 get pods

Big thanks to huapox.

-- Manuel Polacek
Source: StackOverflow

1/28/2020

From the error you posted, your user is getting failed in Authentication phase only (HTTP error code: 401), you can validate the same using:

$ k get pods -v=6
...
I0123 16:34:18.842853   29373 helpers.go:203] server response object: [{
  ...
  "code": 401
}]
F0123 16:34:18.842907   29373 helpers.go:114] error: You must be logged in to the server (Unauthorized)

Debug your setup using below steps:

  1. Verify you are using the correct context and correct user as you expected (with * in CURRENT column):

    $ kubectl config get-contexts 
    CURRENT   NAME                          CLUSTER      AUTHINFO                NAMESPACE
    *         context-user-ca-signed        kubernetes   user-user-ca-signed     ns1
              kubernetes-admin@kubernetes   kubernetes   kubernetes-admin        
  2. Verify the CA certificate for Kubernetes API Server (assuming API server running as a Pod):

    $ sudo cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep -i "\-\-client-ca-file"
        - --client-ca-file=/etc/kubernetes/pki/ca.crt
    
    $ openssl x509 -in /etc/kubernetes/pki/ca.crt -text -noout | grep -i "Issuer:\|Subject:"
            Issuer: CN = kubernetes
            Subject: CN = kubernetes
    
  3. Verify your user's certificate is signed by above CA (Issuer CN of user's cert is same as Subject CN of CA cert, "kubernetes" here), which is configured in API server:

    $ kubectl config view --raw -o jsonpath="{.users[?(@.name == \"user-user-ca-signed\")].user.client-certificate-data}" | base64 -d > client.crt
    
    $ openssl x509 -in client.crt -text -noout | grep -i "Issuer:\|Subject:"
            Issuer: CN = kubernetes
            Subject: C = IN, ST = Some-State, O = Some-Organization, CN = user-ca-signed

If the above steps are fine for the user you created, you shall pass Authentication phase. But Authorization phase still needs to be configured using RBAC, ABAC or any other supported authorization mode, else you may still get HTTP error code: 403

$ kubectl get pods -v=6
I0123 16:59:41.350501   28553 helpers.go:203] server response object: [{
  ...
  "code": 403
}]
F0123 16:59:41.351080   28553 helpers.go:114] Error from server (Forbidden): pods is forbidden: User "user-ca-signed" cannot list resource "pods" in API group "" in the namespace "ns1": No policy matched.
-- Ramesh Singal
Source: StackOverflow