Kubernetes RBAC configuration can seem like a daunting task at first. In this article we will try to demystify some of the mechanism behind the authorisation process in Kubernetes and learn how to generate our own credentials to communicate with the Kubernetes API server.
We’ll also take a look at why you generally shouldn’t use the kubeconfig you initially get after creating a cluster,
and how to configure OIDC authentication with the Kubernetes API server for use with kubectl
.
Although the topic of Kubernetes authorisation is covered in-depth in the official documentation — and multiple articles and videos already exist on the topic, I’ve written this summary article as a way of better understanding Kubernetes, and hopefully helping others in doing the same.
RBAC Authorisation#
Authorization in Kubernetes can be done through role-based access control (RBAC). Kubernetes also supports attribute-based access control (ABAC), and there exists a special-purpose node authorisation mode to authorise API requests made by kubelets. In this article we’ll only focus on RBAC authorisation.
For cluster-wide authorisation we can use non-namespaced ClusterRole resource — which defines PolicyRules for what the role allows, and ClusterRoleBindings — which links ClusterRoles to Subjects (users, groups, or service accounts), granting them access to specified Kubernetes resources.
More fine-grained authorisation can be obtained by using the namespaced Role and RoleBinding resources. Note that you can bind a ClusterRole to a RoleBinding to limit the scope of the ClusterRole to the namespace the RoleBinding exists in.
Kubernetes ships with
some default ClusterRoles.
These include the super-user cluster-admin
ClusterRole,
and the aptly named admin
, edit
and view
ClusterRoles intended to be granted within namespaces using
RoleBindings.
To have a request authorised,
you have to present either a valid token or certificate recognised as a subject
by a RoleBinding, which in turn references a Role describing what is allowed.
There is also a special,
hard-coded system:master
Group
that allows full access to the cluster without any associated ClusterRole or ClusterRoleBinding.
This group is meant for break-glass access to a cluster,
and should generally be avoided in favour
of least-privilege access.
Kubeconfig#
As a primer before we continue,
we’ll quickly go through the kubeconfig-file used by kubectl
to
store access details to clusters.
Kubernetes follows the X.509 standard for certificates, and uses a public key infrastructure (PKI) for certificate distribution.
Given the sample kubeconfig file below, the certificate-authority field (line 8) contains a base64 encoded certificate meant to authenticate the API server we’re trying to communicate with. This helps mitigate man-in-the-middle attacks, making it harder to spoof the API server.
|
|
For authorising with the Kubernetes API server we can present a client-certificate (line 13) signed by the Kubernetes Certificate Authority (CA) and our private client-key (line 14) used to generate the certificate signing request. It’s also possible to use a token instead of a certificate, something we’ll look into later.
The context field (line 16) holds configuration used to communicate with the API server, i.e. a combination of user, cluster and optionally a namespace.
Whereas the CA and client certificates can be considered public, the client key should never be shared unless you want everyone to have access to your cluster. In lack of better judgement, I’ve added certificates and client keys for defunct clusters in the Summary section as examples.
Although certificate revocation is a well established part of PKI, Kubernetes does not (yet) support this feature. This means that any certificate signed by the Kubernetes CA is valid throughout its whole lifetime.
It’s possible to change the whole certificate chain instead, but I can only imagine it’s an arduous task filled with peril… and possibly a dragon or maybe a balrog. Kubeadm does have support for managing certificates, and there exist documentation on how to manually rotate the Kubernetes CA certificates, so it is possible.
Out-of-the-box Authorisation#
Before we investigate how we can generate our own means of authorisation, let’s first look at what we get out-of-the-box from some common Kubernetes distributions.
The easiest starting point is Minikube, which is meant for local use. Looking at the kubeconfig generated by spinning up a Minikube-cluster, we see it referencing files for the certificate-authority, client-certificate and client-key fields.
Following the RSA algorithm, the client-key is just a collection of integers, including some really big ones that have special properties and are hard to both guess and compute — barring collapsing wave functions in future quantum computers, so we won’t pay it much mind.
If you’re interested in the RSA-key details you can check them using openssl
by executing
openssl rsa -text -noout -in <key-file>
The more interesting part for our case are the certificates. These can be inspected by running
openssl x509 -text -noout -in <certificate-file>
Looking at the CA certificate, we see that it is self-signed — the Issuer and Subject fields reference the same Common Name (CN).
Certificate:
Data:
Issuer: CN=minikubeCA
Subject: CN=minikubeCA
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:TRUE
X509v3 Subject Key Identifier:
61:34:D4:BB:7A:50:5C:59:BE:B7:12:AF:EB:86:6F:49:E5:7B:3C:02
Also note the Subject Key Identifier value.
Inspecting the client certificate reveals the CN of the certificate Issuer to be minikubeCA
,
we can also recognise the Subject Key Identifier from the CA certificate as the Authority Key Identifier,
linking the two certificates.
More interestingly, the subject Organisation (O) is the special system:masters
group.
Certificate:
Data:
Issuer: CN=minikubeCA
Subject: O=system:masters, CN=minikube-user
X509v3 extensions:
X509v3 Basic Constraints: critical
CA:FALSE
X509v3 Authority Key Identifier:
61:34:D4:BB:7A:50:5C:59:BE:B7:12:AF:EB:86:6F:49:E5:7B:3C:02
Directly referencing the special system:masters
group means that there is no way to rescind authorisation for this
certificate since we can’t remove the group, nor revoke the certificate itself.
Kubeadm addressed the system:masters
issue
in
version 1.28
onwards.
Kubeadm now issues two kubeconfig-files upon cluster bootstrapping,
a super-admin.conf
file which is supposed to be kept for emergency purposes only
— since it uses the system:masters
group,
Certificate:
Data:
Issuer: CN=kubernetes
Subject: O=system:masters, CN=kubernetes-super-admin
and another kubeconfig file — admin.conf
,
Certificate:
Data:
Issuer: CN=kubernetes
Subject: O=kubeadm:cluster-admins, CN=kubernetes-admin
which instead references the ClusterRoleBinding
kubeadm:cluster-admins
We can inspect the kubeadm:cluster-admins
CRB to see that it in turn references the default cluster-admin
ClusterRole which gives full access to the cluster
|
|
The difference between the kubeconfig-files is that if we suspect the admin.conf
file to be compromised,
we can delete the kubeadm:cluster-admins
CRB,
and the associated certificate loses its authorisation.
Executing this
proverbial footgun
using the admin.conf
credentials,
we see that we lose access to the cluster
> kubectl delete clusterrolebinding kubeadm:cluster-admins
clusterrolebinding.rbac.authorization.k8s.io "kubeadm:cluster-admins" deleted
> kubectl get nodes
Error from server (Forbidden): nodes is forbidden: User "kubernetes-admin" cannot list resource "nodes" in API group "" at the cluster scope
Take note that if you switch to the super-admin.conf
kubeconfig and re-create the CRB we just deleted,
the admin.conf
kubeconfig regains its privileges.
Avoid restoring this CRB if you suspect that the admin.conf
kubeconfig is compromised!
Instead, conjure up a new Group subject and issue a new certificate as in the next section.
Out of the other Kubernetes distros I
tried, Talos, AKS,
and K3s all generated a system:masters
level access certificate,
except GKE which uses
a plugin
based on
the client-go credential plugins
framework for authorisation.
Custom Authorisation#
For custom authorisation in Kubernetes, we can either take advantage of one of the default ClusterRoles
— cluster-admin
, admin
, edit
, view
, or we can craft our own by stitching
together appropriate rules.
It’s also possible to
create aggregated cluster roles.
Instead of directly defining policyRules,
aggregated cluster roles defines an aggregationRule which combines the policyRules of ClusterRoles which matches the
given criteria,
this includes other aggregated cluster roles.
As an example you can inspect the default admin
, edit
, and view
ClusterRoles.
The aggregation mechanism comes in handy when you create custom resources where you might want cluster users to be able to view or create the resources. Assuming you’re already using the built-in roles for cluster users, you can simply define a new ClusterRole with the appropriate label which will then be aggregated to an applicable default ClusterRole.
As an example of creating and using our own ClusterRole,
we will copy the details of the built-in cluster-admin
— since it’s fairly straight-forward,
ClusterRole and name it super-admin
(line 4) to distinguish it
|
|
To actually use the ClusterRole we just created, we need to create a ClusterRoleBinding to link this role to a user, group, or service account.
Kubernetes assumes that a cluster-independent service manages normal users, and thus Kubernetes does not have any objects that represents normal user accounts.
Without any third party tool managing users, that means we’re free to make up users on a whim, which is what we’ll do here.
|
|
The above CRB grants any subject recognised as belonging to the group super-admin
(line 6-7),
the specified user lain
(line 9-10), and the sa-super-admin
ServiceAccount in namespace cluster-access
(line 12-13) the super-admin
role (line 17-18) we created earlier.
Generating Certificates#
Following PKI, we need to first create a private key before generating
a CertificateSigningRequest
(CSR).
Diverging from the more common RSA cryptographic scheme,
we can instead try out Elliptic-curve cryptography (ECC)
which offers equivalent security with smaller keys compared to RSA,
thus arguably being more efficient.
We can generate a secp521r1 curve1 EC-key using openssl
by running
openssl ecparam -genkey -name secp521r1 -out private.key
To conjure up a user called alice
belonging to thesuper-admin
group we can create
a certificate signing request
signed by our freshly generated key
— with organisation (O) super-admin
and common name (CN) alice
,
by invoking
openssl req -new -key private.key -subj "/O=super-admin/CN=alice" -out alice.csr
Next we create a
CertificateSigningRequest
(CSR) resource with the alice.csr
certificate signing request base64 encoded (line 6) to ask
a Kubernetes signer
(line 7) to sign the certificate for us
|
|
We also have to indicate that the certificate is to be used for authentication by adding client auth
in the usages
list (line 9).
After applying the above CSR to a cluster, we can see it pending approval
> kubectl get csr
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
alice-csr 26s kubernetes.io/kube-apiserver-client admin <none> Pending
Assuming we have the right privileges we can approve the request by running
kubectl certificate approve alice-csr
If everything went well,
the signed certificate should now be in the satus field of the CSR resource.
We can extract the signed certificate from the status field to alice.crt
file by running
kubectl get csr alice-csr -o yaml | yq '.status.certificate' | base64 -d > alice.crt
Note the validity of the certificate
> openssl x509 -text -noout -in alice.crt
Certificate:
Data:
Validity
Not Before: Nov 30 19:01:08 2024 GMT
Not After : Nov 30 19:01:08 2025 GMT
Be sure to issue a new certificate before it expires if you wish to keep the access. If you want to revoke Alice’s access you have to delete either the ClusterRole or ClusterRoleBinding to rescind the authorisation vested in the certificate. Deleting the CR or CRB will naturally also revoke access to anyone else relying on them, so it might be a good idea to create a CRB for each cluster user.
With our private.key
private key and alice.crt
signed certificate in hand we can add them as
credentials to our kubeconfig file by executing
kubectl config set-credentials alice --client-key=private.key --client-certificate=alice.crt --embed-certs=true
Next, create a new context that combines the newly created user credentials with the current cluster
(you can find the cluster name by running kubectl config get-clusters
)
kubectl config set-context alice --cluster=kubernetes --user=alice
To change to the new context run
kubectl config use-context alice
and verify that everything works by invoking
kubectl get pods -A
This last command should give an overview of all the pods running in the cluster if the certificate is valid and the private key is correct.
A simplified graph of the authorisation flow we just performed is summarised in the figure below
Creating a user certificate for the omnipotent Lain is left as an exercise to the reader.
ServiceAccounts#
Every namespace in Kubernetes contains a ServiceAccount
named default.
This default
ServiceAccount is only granted
the default API discovery permission
which all authenticated users get.
If we don’t manually assign a ServiceAccount to a
Pod,
that pod will get be assigned this default
ServiceAccount.
A ServiceAccount can be used by Pods to communicate with the Kubernetes API server. Tools like Argo CD, Cilium and Cert manager extensively use the concepts in this article to communicate with the API server. If you run similar tools in your cluster I urge you to explore the ClusterRoles, ClusterRoleBindings, and ServiceAccounts these tools create when installed.
ServiceAccount Tokens#
We can manually retrieve
ServiceAccount tokens by either looking
in /var/run/secrets/kubernetes.io/serviceaccount
inside a Pod,
or by using
the TokenRequest API.
ServiceAccounts are primarily intended to be used by applications and services — i.e. non-human entities, although the documentation for the Kubernetes Dashboard links to a guide to create a sample user where they use a ServiceAccount, so we’ll allow ourselves to do the same for demonstrative purposes.
With the super-admin
ClusterRoleBinding we created earlier,
we can create the following ServiceAccount to bind to it (line 4)
|
|
To authenticate using the service account we can create a base 64 encoded JSON Web Token (JWT) by running
kubectl -n cluster-access create token sa-super-admin
We can inspect the generated JWT by pasting it into e.g. https://jwt.io
{
"exp": 1733053970,
"iat": 1733050370,
"sub": "system:serviceaccount:cluster-access:sa-super-admin",
...
}
here we see that the token is valid for 3 600 seconds (exp - iat
), or an hour.
The JWT can be used in a similar fashion as a certificate by adding it as a credential to a kubeconfig context
TOKEN=$(kubectl -n cluster-access create token sa-super-admin)
kubectl config set-credentials sa-super-admin --token=$TOKEN
kubectl config set-context sa-super-admin --cluster kubernetes --user sa-super-admin
kubectl config use-context sa-super-admin
If this is your only way of authenticating wth the cluster you’ll have to refresh the token every hour before it expires, or else you lose access.
OpenID Connect Authorisation#
Rather than juggling long-lived certificates and abusing ServiceAccounts, we can instead use OpenID Connect (OIDC) for a more user-friendly way of authenticating to the Kubernetes API server.
Although OIDC authorisation is easier for the end-user, it requires some extra configuration from the cluster admin. We’ll need to set up an OIDC provider as well as configure the kube-apiserver to use said OIDC provider.
To avoid dealing with a client secret we’ll use the Proof Key for Code Exchange by OAuth Public Clients, or PKCE for short, pronounced pixy.
It’s possible to authenticate with the API server using vanilla
kubectl
,
though using a plugin like kubelogin makes it a lot easier,
and is what we’ll be using here.
Assuming you already know the client-id
and URL-base of your OIDC provider discovery URL
— e.g. <URL>/.well-known/openid-configuration
,
you can configure the kubelogin plugin by adding the following to your kubeconfig file
|
|
Here <URL>
on line 10 is the base of the discovery URL, and kubectl
is the client ID (line 11).
We also ask for the profile
and groups
scope which we can use to match with CRB subjects
.
The next step is to configure an OIDC capable identity provider. There’s a plethora of self-hosted OIDC providers out there. Some examples are Authelia, Authentik, Kanidm, Keycloak, Rauthy, and Zitadel. I’m currently running both Authelia (with LLDAP for user management) and Keycloak (using the Crossplane Keycloak-provider for declarative setup), though I’m contemplating giving Kanidm a go. If you instead prefer an external service you can e.g. create a GitHub App, or use Google’s OpenID Connect solution.
I opted to use Authelia because of its inherent declarative config. Authelia was a bit finicky to set up as an OIDC provider at first — I’m working on an article on how to configure it, but once it’s working I added the following configuration
identity_providers:
oidc:
clients:
- client_id: kubectl
client_name: kubectl
public: true
redirect_uris: [ 'http://localhost:8000', 'http://localhost:18000' ]
scopes: [ 'openid', 'groups', 'email', 'profile', 'offline_access' ]
userinfo_signed_response_alg: 'none'
To enable OIDC integration in Kubernetes we need to pass the relevant arguments to kube-apiserver.
Using Minikube this can be done by starting it with the following parameters
|
|
Notice the OIDC-provider base <URL>
on line 2 and client-id
on line 3.
We’ve also explicitly configured the oidc-username-claim (line 4) to be the JWT sub
-claim.
Other options for the username claim depends on your OIDC provider setup,
some options can be either email
, name
, or preferred_username
.
The username-claim will be used to match User
-kind subject in CRBs.
To match Group
-kind subjects we selected the aptly named groups
-claim to select from (line 6).
The equivalent in Talos’ machineconfig would be
|
|
With Minikube started,
the kubectl
context should be automatically change to the system:masters
context for the cluster.
Using this context we can create the following CRB to match appropriate OIDC-claims
|
|
Here we’ve chosen to match the k8s:cluster-admin
(line 7) group from the groups
-claim and the specific user with the
sub
-claim lain
(line 10).
To make it easy for ourselves we’ve used the built-in cluster-admin
CR to grant full access to the cluster for
subjects matching the given rules.
We can now create a new kubectl
context using the oidc-user we manually created earlier and start using that context
kubectl config set-context oidc --cluster minikube --user oidc
kubectl config use-context oidc
When running a kubectl
command that requires authentication,
your web browser should pop up and greet you with the
login page of your selected OIDC provider.
After successfully logging in you should be greeted with a consent screen to hand over your details
Consenting to sharing your details, a Kubelogin view from localhost should appear informing you that you’ve successfully logged in to the cluster.
The JWT is cached in the ~/.kube/oidc-login/
-folder if you want to inspect it.
This token will be forwarded with each request to the API server.
Summary#
Note that it is generally a very bad idea to share certificates and private keys as they can be used to wreak havoc. These have been generated inside a virtual machine that has now been decommissioned, so like a key to a burnt down house, they have no use except as examples.
I encourage you to inspect both certificates and keys using e.g. openssl
.
Minikube#
Public CA certificate
-----BEGIN CERTIFICATE-----
MIIDBjCCAe6gAwIBAgIBATANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwptaW5p
a3ViZUNBMB4XDTIyMDkyNjExMTIyOFoXDTMyMDkyNDExMTIyOFowFTETMBEGA1UE
AxMKbWluaWt1YmVDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMUk
ZWeZXz2so0RxTQukz6TJvcBc//IwIxCFIHAgBdHMxucrO6H8hyDWasRpn+LMs6SG
zhdwF7Q83gI/KzsurP1asjNeMWVOnrjvedeLefx8gbbGAG5cbqXfirXmy/8TSTta
hrncwsJJmBZ3BfbV81fGuBFNXpw8C7cv8JSca2yCJyzJDa8MBgogB/JA30vyX6GB
yzUChRzl043PBeVt0Y96AKo+9Wlmzf+uaKQkK19CAqnH5a/JqPjibRXWt1ZcWCAw
rpT494kjzspaZrGWGgXiYcM++zPx04p0hanmnFN3aJ1SjgwX3EbsMhG2IQi4VUPf
7LAOZUaPmz6cOfjTglECAwEAAaNhMF8wDgYDVR0PAQH/BAQDAgKkMB0GA1UdJQQW
MBQGCCsGAQUFBwMCBggrBgEFBQcDATAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
BBRhNNS7elBcWb63Eq/rhm9J5Xs8AjANBgkqhkiG9w0BAQsFAAOCAQEABfeXOmNE
886/0qbJ41OrT6Bcmcr6Mg0jxqqkR/sQok0QNPFNzI4BOzag7e6qS9JfZfRyGNNA
NjUJeKSpzx5uwX2Uy06GkLYC8RwJ283Mj+IVfNfu+kpyz/m9bbk22ZhMiFutm23b
vveOmO8ajpZ+IOtVisuGTXZ0iAC9Fw5n/uwfyJ6DpqJdulP6lv0f+3HKrQveo4zC
fSPycTNQW6zfvJjS1SHvglJO/VIdJ4uoR/qOaSkVtJRLu2jijPWItxi05aGWQgpv
gjYubUTmiUHPlE3FL4wbDNGHsE/pViT3GBeVjaNpXkT8KdYXfdjG1YNtmIPZ26j2
2fW4eKuNjDql7A==
-----END CERTIFICATE-----
Client certificate signed by CA
-----BEGIN CERTIFICATE-----
MIIDITCCAgmgAwIBAgIBAjANBgkqhkiG9w0BAQsFADAVMRMwEQYDVQQDEwptaW5p
a3ViZUNBMB4XDTI0MTEyMTA4NDgzNloXDTI3MTEyMjA4NDgzNlowMTEXMBUGA1UE
ChMOc3lzdGVtOm1hc3RlcnMxFjAUBgNVBAMTDW1pbmlrdWJlLXVzZXIwggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCwfXXByZHdwGO752BgvDjwbchEf7KV
lmwD6eGOulOsFPzQz+JoLWzNRLXKECorRX5lDL9bY+pjZKIcqOvnz2m8l3GYcqJW
qDxFi9POpiC53KG9yDNalmocE7HvJJXzKivEoJnlfFrN4/BWqpmqdKtbfF0B77be
JD1vJ+HSdGgjjRMAK/efMsrSj+5De+Y5b3uLuIc/ubtBkYb63/1AC0zSFZsvhfIB
/s3YILQCBFUL5BzPYRA5oU+T2+ePLPKigiSmfKULf8VsNEBHKOuBr5kGaSNkpc9/
YqTyjdN5CcDSWqO8YGNSU3/LC61YoNL5v5w2Zj+TvyykAjURtjTLlaIrAgMBAAGj
YDBeMA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH
AwIwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBRhNNS7elBcWb63Eq/rhm9J5Xs8
AjANBgkqhkiG9w0BAQsFAAOCAQEAKuVsy9DMz9PvnaIjvSUopTvrS8l9DAvXrxmv
droY/9zmet3/V0u9I7MtDmKxhO41X00s6gnSfZ5uHJX+ONjzZcdw6SEtwQ2prt/l
NQcKTqfgi+6akoTt8dqT0oa2/IYIV9kKRawsbPyTySATkxWDA42NcPGkaovPWz6Q
qVkhGBKuPhENNyt4911orI6VeFLMuPwuyuCU6o+ISS6zclNkUn71l16enmWBUUuM
J8bQDjkB48w+EqETsVLIgrAEbbdj8Mq3oyYk1xzAIhcsMnwD4B41GP+a34P9Ilyt
PJ9ocfoGVg4d+Sj3MnAqkZWEX8lKHtqM+0JbAkXEUDoK07MSWA==
-----END CERTIFICATE-----
Private key
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAsH11wcmR3cBju+dgYLw48G3IRH+ylZZsA+nhjrpTrBT80M/i
aC1szUS1yhAqK0V+ZQy/W2PqY2SiHKjr589pvJdxmHKiVqg8RYvTzqYgudyhvcgz
WpZqHBOx7ySV8yorxKCZ5XxazePwVqqZqnSrW3xdAe+23iQ9byfh0nRoI40TACv3
nzLK0o/uQ3vmOW97i7iHP7m7QZGG+t/9QAtM0hWbL4XyAf7N2CC0AgRVC+Qcz2EQ
OaFPk9vnjyzyooIkpnylC3/FbDRARyjrga+ZBmkjZKXPf2Kk8o3TeQnA0lqjvGBj
UlN/ywutWKDS+b+cNmY/k78spAI1EbY0y5WiKwIDAQABAoIBAEHV2xp51abRwKJ0
chhDvj25xg3/UJ/KZ+qh0RkL2nCDt7cxBPT1lPORYPrKQuC3YKnTMoKl5+ZBwNNO
FAn57iiCmcZTZMlMoocS3OTmRajva4o+5yEwoM5ubl6V2DXIEmGbwyy+0aSiFaJO
q1nRgaZz4sH5KM7+18fiKbP25m3z8DYABglkaAa3bGOtnAaAVBpTleCswHcifVHu
bjLSJUv/af7TChncZTOBya5GShHgV5t/hlW6jd+hq+IV3A/muvqmvo6Uj1zx4u5w
7KH/OkjD/BDgaTaLCrrur/3Bqr+gTOOJ1gWCHuP6zvvFEFMlLZCl2wP+MeNzBVAE
4ZevEPkCgYEAyBNaAfmsWT4quo/rexchzyBJHfSGWD76DHzIowqt2dfg5kO+Yf5g
aZyeVA3L2Sa/btiRXSOtBpvek8cPdbcrzp0165MgBk37C51w0mcFz1uxPGVDjArx
uTcpkVG8aTXXFpubA634Q+zn6C4U1XceRB3F5M6pHfog85TGqD0arw0CgYEA4dJr
MMk35D4lcGeHlWLItXiEfRJqvQPWm3E+wXog7q1g6FWQSJlAzk+ldpp9UiSY2MYY
jW1XVyKHtFqIQVPmD3wfHlxp3NzYsKIY6FP/M7E1PTOXJPDkzrnRBy7gbpVEWX58
CO7sYzAKoNAnu980Znm/Eka+Y9f0vvrK0ZG1iBcCgYEAjAwPquZLX8SGQETRfj24
6rUcuR0alNawTOFjx8yH2L6lrEirEQjwD70Tjp6BnCTlRv/M8LcyPDgK2sIx7iIj
ReMBhT5c4kzfd0fjW0PF61mxfCcd2v8mKJGWRSRDkBmhzy9omHDEITfJNNpctvdE
dkWo6fpGorcdLaNsUwNClFkCgYEAozBsRdUjjs1aQOCQGmRIpttw4vFsMSuU6r/r
meWn5tNkNIGgwtX8/xqPeCYsajAIRJ7jH1DkzRMm/i5uSMdYedg4pLgjyHfQH9UE
KuCIi9KDprahgxCSSNH/PDGj/kXgHsxI1ivSp9sP0yaZkCq8s1FHwu1cqMpnE5wo
9UlW5gECgYAz2a7j5dcQ1/PiH54iEf9t3aggadYcZT3WC/PK5969PPuMmU69MBis
oju2bm2aLMn+j9VONc18U/wazR6k0E4+V00XRMvoO3bl8KR4fxpOrD6GBBS9wf14
syGcTNLHTmIfeLSlg3raOLMTbt8+bc3bzKzfCE1nD8f94yZlyTxnNw==
-----END RSA PRIVATE KEY-----
K3s#
Public CA certificate
-----BEGIN CERTIFICATE-----
MIIBdzCCAR2gAwIBAgIBADAKBggqhkjOPQQDAjAjMSEwHwYDVQQDDBhrM3Mtc2Vy
dmVyLWNhQDE3MzI5MjA2NDgwHhcNMjQxMTI5MjI1MDQ4WhcNMzQxMTI3MjI1MDQ4
WjAjMSEwHwYDVQQDDBhrM3Mtc2VydmVyLWNhQDE3MzI5MjA2NDgwWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAATMPChJTCjWRsjqv8LmnrGrZE1Lmum8pTUo8JlRs+Fr
VMUiJco7/MTg4zNdHW5vr+PaEfw9W90DQeD1kg52sVoqo0IwQDAOBgNVHQ8BAf8E
BAMCAqQwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUHFTC5WJBpIblmDNHNakd
l/s0Ef4wCgYIKoZIzj0EAwIDSAAwRQIhALuGHkxUEGiuLmx3ryz3urQ+XLSN94dy
GMzOKjmzGW+wAiBHgZSZmEBZ7oPL01DpKYNb6f0eeNjz91VGPp74bpPrOA==
-----END CERTIFICATE-----
Client certificate signed by CA
-----BEGIN CERTIFICATE-----
MIIBkjCCATegAwIBAgIIRom1Wpt2eYowCgYIKoZIzj0EAwIwIzEhMB8GA1UEAwwY
azNzLWNsaWVudC1jYUAxNzMyOTIwNjQ4MB4XDTI0MTEyOTIyNTA0OFoXDTI1MTEy
OTIyNTA0OFowMDEXMBUGA1UEChMOc3lzdGVtOm1hc3RlcnMxFTATBgNVBAMTDHN5
c3RlbTphZG1pbjBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABEZnKx9oFVP8Aq3I
Lt3F5jmQOAWz5YH+tWWmK/4TrWOT8PvDqY28k0sowEees2ltywnJTMGUJ77XeKpl
CiTzaB6jSDBGMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggrBgEFBQcDAjAf
BgNVHSMEGDAWgBRdDTEgrYmKDMkPR5stdQ33OKXupTAKBggqhkjOPQQDAgNJADBG
AiEAireWiHMO3CmYnWaIHes7oO6lLJEOIkymZUOQQHK93MUCIQDE4Y4eUZ68n3VX
Ioq6rnqmPUEe3LfpEtE3FeOFzBPicA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIBeDCCAR2gAwIBAgIBADAKBggqhkjOPQQDAjAjMSEwHwYDVQQDDBhrM3MtY2xp
ZW50LWNhQDE3MzI5MjA2NDgwHhcNMjQxMTI5MjI1MDQ4WhcNMzQxMTI3MjI1MDQ4
WjAjMSEwHwYDVQQDDBhrM3MtY2xpZW50LWNhQDE3MzI5MjA2NDgwWTATBgcqhkjO
PQIBBggqhkjOPQMBBwNCAASy/9ws7rclttxjIk+ILMCqyPVLEOiiiBLn8RdQeMeQ
RfUfu3naBpZinDwIyyBMJvsk4TYZKdiN3HAklX4YaUKNo0IwQDAOBgNVHQ8BAf8E
BAMCAqQwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUXQ0xIK2JigzJD0ebLXUN
9zil7qUwCgYIKoZIzj0EAwIDSQAwRgIhALY+KYo368CnoGvhuWL7MxMh9mvbyPyB
abdMwjTvqvr5AiEAhaXy63UmNZNCMdqKihiv0XDJ2Xlix6OTMtbCquQcAsQ=
-----END CERTIFICATE-----
Private key
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIDaSmvCaHI5j2yVcchnbuMtqMM3K+N4z8TcwXhGDwFyaoAoGCCqGSM49
AwEHoUQDQgAERmcrH2gVU/wCrcgu3cXmOZA4BbPlgf61ZaYr/hOtY5Pw+8OpjbyT
SyjAR56zaW3LCclMwZQnvtd4qmUKJPNoHg==
-----END EC PRIVATE KEY-----
Kubeadm#
Public CA certificate
-----BEGIN CERTIFICATE-----
MIIDBTCCAe2gAwIBAgIIBVHWOO6S1/IwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE
AxMKa3ViZXJuZXRlczAeFw0yNDExMjcxMTMxMDRaFw0zNDExMjUxMTM2MDRaMBUx
EzARBgNVBAMTCmt1YmVybmV0ZXMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQCVSFCg5NqyWXSyuCoJx/YwQeHsdJRNOSzq8IxMdBUQFnHO2Wq3wvcw2EXz
ZzHAbZk58G13y+UAViToIaIJvLfpBqLLQLGxrQqdlMPC6ySEn5DJJxNAatTIaCw2
Dpnadw9INVJBdso696ejItWwwjDKAkff746WCnoUbSOS258yk6Qk5gxJiSws6o3f
Wn+RI9f7ZITYeed8i1BSDvUAQAgqVWUskkv8lCLU5hgCs6R4sxqaQ3QHjN8FNBj7
D4bWx3Ghjg4no6tssGrJYNxO6aE8HsL2tObqdJPYZ9TrH3/lz24VcONbtCXwkLaw
27tqAjnpvzng21m2JqvfSovMFbyxAgMBAAGjWTBXMA4GA1UdDwEB/wQEAwICpDAP
BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTAx10f7XoSzvnK5z5IAwvxYEWrUTAV
BgNVHREEDjAMggprdWJlcm5ldGVzMA0GCSqGSIb3DQEBCwUAA4IBAQCTk/DUi9xK
ndGulLeHRpQuoYEgSdxhxTT/txNA90xIfFP8V0i8suHdnFpybrz4Tq0HVdaqTK4j
K0LbJjVid5loBmtCYxgCYPOWRy9+qZF8ANldMDdWxYxgfoF5dbbRzyWvriHW1jC3
O5JXY+l5sqcTe9pibmSvAxJxsuUpFEFOWXQskG9c3ksTOF9tkraArNpZFRynCIyI
tO2ijzNUGfF/fyY1/dmZ/qKwhiIOlYMiW0hXNrQFtkSC4dwVbqKAoEG5UCacJkYm
BFakFYtwZCB9679gTbp3FeyTwqIDKGs7Jm7883APuZvZFKJipg4ObUchXA4qR4rQ
5wiKpLobNPgx
-----END CERTIFICATE-----
Super admin certificate signed by CA
-----BEGIN CERTIFICATE-----
MIIDJzCCAg+gAwIBAgIINvuFsCZ0o/wwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE
AxMKa3ViZXJuZXRlczAeFw0yNDExMjcxMTMxMDRaFw0yNTExMjcxMTM2MDRaMDox
FzAVBgNVBAoTDnN5c3RlbTptYXN0ZXJzMR8wHQYDVQQDExZrdWJlcm5ldGVzLXN1
cGVyLWFkbWluMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAm090CjPa
tqT1yFvh33jm2Skm1aLR4tC+klMJKmKASEo0bKbNPfdoXY5cdXWsq0G3vDRwC7FA
YSqUXE3p6Ki5xtlpoK54arG2gr33ewwE2cHv9cluSiQyk60hfT/pOudagRmQM828
P9vPC+lnmAN2xb37BIrVTzZrODFRHERVY5tM2tBSWD6l/E0qafe/G9h9Yf/Q+WGP
GZMADtCGLemoXp+OUBkvlZ2kK23DUvE8JMkuIyL3KIOHH/JfUXaK15y415HiGy+k
+ApXOyrYqbcx4NuLb5MkWv6M5NWXgKopp41T4odG+LhDindhDl/DP4Bw3YDYPfqi
+kZrnIQUSSRKywIDAQABo1YwVDAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYI
KwYBBQUHAwIwDAYDVR0TAQH/BAIwADAfBgNVHSMEGDAWgBTAx10f7XoSzvnK5z5I
AwvxYEWrUTANBgkqhkiG9w0BAQsFAAOCAQEAHMhUvKaqnKG6z6y9NwTLzqzI2/S+
Y7pY6gfjumVKz0m+GXL9tSX4GronZbU3ZrBH+dGzZ1nZ6idHMuaCv4v44+SdBMHm
KJ3hzoeCDrjO2trKSI/StqghBwLAeKi97KtLVKLtkVyBSJ19w8+/mMLi8hYDLQIY
U+jwi7Bw+5//+nu97WXNdOJD1c+EvYYUuPQORmJPZYnseHRExS1ruNRqlL5aPAkQ
vxW1Csr8kVQ6H+iE9u1YQxyZrViUKUKU0Gw7hUNGppL6nijiJmJqcgNdX7WUmeGr
Y3V5NMckmSj3KogURaC8fv7jBxlOlM8Zi+2wBVGUzpkVKp8sp6XZ1+irPg==
-----END CERTIFICATE-----
Private key for super-admin certificate
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAm090CjPatqT1yFvh33jm2Skm1aLR4tC+klMJKmKASEo0bKbN
PfdoXY5cdXWsq0G3vDRwC7FAYSqUXE3p6Ki5xtlpoK54arG2gr33ewwE2cHv9clu
SiQyk60hfT/pOudagRmQM828P9vPC+lnmAN2xb37BIrVTzZrODFRHERVY5tM2tBS
WD6l/E0qafe/G9h9Yf/Q+WGPGZMADtCGLemoXp+OUBkvlZ2kK23DUvE8JMkuIyL3
KIOHH/JfUXaK15y415HiGy+k+ApXOyrYqbcx4NuLb5MkWv6M5NWXgKopp41T4odG
+LhDindhDl/DP4Bw3YDYPfqi+kZrnIQUSSRKywIDAQABAoIBAQCPqQ3wRgjge3Qy
EfO776yxYSRf5sz4Xhh5Zz+KKjT5KVKW0i/1Sr4KFB4oNGI0w4Q+Hc8qsZmYh3dW
bmeYY0H80qynCduu7ZWiGDAsbHCsMH1TQDC5egQin7njjlOhvdD0q/28PWkNNLiv
DwZZEZMy1Em16Ono7LB++PdLC1Zk3BhjiSlrQKQGRlOcoMmvwsZDxzp0Kn+BxQgh
bMgtwAvyCfBzj7v8zyCK630nFL/Pkb4n2E2dl3AAuCsbiGGGtoj+aGDXYnPB+fGw
2wBkW63yhly9ZOmp+U3uH+FV4sGULA3BUX/gaeW6+blzc/lHgFZqGxX3vqtrWSon
7kcQ4MHBAoGBAMt/TsdnXluL9CUTALGKsCh+ZJNtB/i1MVN2rGbVDf7U25gTul7z
X10KT8eC/inbs19QTd8m+G7o2FdZrAZCnP4E85vTj+E3aT2Uaf1wRWT/896Uwny6
zNS8cwrWeWwaVOVxNBSwcKM+d31mxGshJ8tPOs2HMfsXhRJNad0d98crAoGBAMNh
eIKQpstE3vLBMSA0cMa/BVU1M3FfXdpTt4Sfw8qJNncfZVdi1tspKFI2Lebkq1ko
Il0QhIm9ifLfDQmmuxuhTQyQy0cFdeerVihzzSIXv0tOMBFtogMxlmwfqPl9B/o8
6asGirygAUXJfog3Tjqg6WCM8tAa6wxnfyGue7rhAoGBAKfs8VRpf5rp/dmOOddI
jB+OVW623Yol84Ndfd0J2Ze9jUyMkxIBoWNEvBr2hMiD7RwtR2VrYj0b1lMWw3cT
BzwzV9fyGFwQfr77Nw+V0x4KfPLjLS8Ccz7mF8UMwXwsqnwAE6szAnAjfzUzVcjV
vmHuiqbJ9ruuZ/h3e3GlZi+rAoGAZmVwDiWXdNK8ccd0Yqd5L4AvYE/IjTNo8aKM
fLJqn3w4EkhfCWRgrG2ulx+UAP15G/nfwJyGidXPNX1WzOcYCswHoH1GPAuNloQC
XKMMMED33ZS1tnyZu0jCyBnzqgWwJ6LC6AI+tcq5wARxDxzFIA7zIMnd+9kPtOmN
BG74o6ECgYAz/8DrIPJ6UMYPiNEIWkzaomeo4lLy8lov2v3mmk2LRVu85zjp++dv
6Qme9cdqpZ4gCv7xXG9F+aZQOG/Od0B96vHPCw38/+4XhoCTAbWcBjKvpjURDxC8
AK6xmzBQUDaaFVjsSVC+vIzWhFM52g1xPQ8DHnLXDaJx02JKrOT6lQ==
-----END RSA PRIVATE KEY-----
Admin certificate signed by CA
-----BEGIN CERTIFICATE-----
MIIDKTCCAhGgAwIBAgIIfMSskSav/ykwDQYJKoZIhvcNAQELBQAwFTETMBEGA1UE
AxMKa3ViZXJuZXRlczAeFw0yNDExMjcxMTMxMDRaFw0yNTExMjcxMTM2MDRaMDwx
HzAdBgNVBAoTFmt1YmVhZG06Y2x1c3Rlci1hZG1pbnMxGTAXBgNVBAMTEGt1YmVy
bmV0ZXMtYWRtaW4wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDX/tnq
8PTYhb6jkQUPUMNi8RkSJX2exkrvaGormoINHmn/3pfO1PuCGd8aDxYf1ZbDvjWL
00RIQWkrydcA/C7BrSCeFqiKL3iE8J+kJIzW1XLH5jliSNPlFeg48ueImg297Dn1
Kw6pnVwQhSaISSmcIgf1H1xkOoHbVIIeJpXD8OYr5MLlQSKXmNBe9qwmeQdFIoVm
MD/ImVZL0LY2nrPFOgrQF5zdcyI+16v1+Hn6K289Tu97W0cyroMyrODYOxDC+Y31
Sns3Fuvh2mg6z1LkVPPheMZpMgT2XviwQxmGkOEAzSJyq9fmg+1i9+uf5mGe4+HF
SYx1zgUXqX0/Z5LlAgMBAAGjVjBUMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAK
BggrBgEFBQcDAjAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFMDHXR/tehLO+crn
PkgDC/FgRatRMA0GCSqGSIb3DQEBCwUAA4IBAQBhl/j5zBjyB/0cpqLU/k2gDaJt
pBKvWctGP5YfwmKqIDF1ZaUolm2yjjAGSCPOPWCggMuNdh+AMR5o85/ffziP1nGp
jIcPjje47tHSogvmHFahGxPnAgvw4GOoVi5PeAYwZTxi4ZqmXJ8tP4HAsfSRlRN7
GZ66LwGzbplNp41W6XYcmzzuB0MG9K2pd3R0nOar14vAoTX8j2Hq+8rValpZrV6o
D2YkgF0ZD0wlTLIL1+XuyOKnh2f/S5BaArq+tjTwvMHIYLOYCLSdq2hC4dsVr6Y5
/sxSl+c+8u3ai3Wi5vM/dzUBEu735vie/TqZHw7O9LntOHtuLB1eEz7nSc9Y
-----END CERTIFICATE-----
Private key for admin certificate
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEA1/7Z6vD02IW+o5EFD1DDYvEZEiV9nsZK72hqK5qCDR5p/96X
ztT7ghnfGg8WH9WWw741i9NESEFpK8nXAPwuwa0gnhaoii94hPCfpCSM1tVyx+Y5
YkjT5RXoOPLniJoNvew59SsOqZ1cEIUmiEkpnCIH9R9cZDqB21SCHiaVw/DmK+TC
5UEil5jQXvasJnkHRSKFZjA/yJlWS9C2Np6zxToK0Bec3XMiPter9fh5+itvPU7v
e1tHMq6DMqzg2DsQwvmN9Up7Nxbr4dpoOs9S5FTz4XjGaTIE9l74sEMZhpDhAM0i
cqvX5oPtYvfrn+ZhnuPhxUmMdc4FF6l9P2eS5QIDAQABAoIBAQDBrS6gAVG7OSn5
Jtc/pW6dsIyHfgCHN00IITtaP+AvfT8VBPZgqw+e2C36At8WyoG2oT8IUvceRzDT
59eXdYlDd0cRGkYkKm7J3a14FKIJHTofzutTmvQNrbgeIIjGL0T1MPXDRcmPA6AC
3DHx8JCUBNvXyzggU2oPTlaiTHzsRNd5II9pwOre4XkuoIXhE3CptQX/d7prB+qe
TutJMf8LdQb09QJn879dxs7PScBcJWeXjg/UTf7hWwj1bqI3zG1mIPJZsHOqnKAH
05GPKhbTxfWBVt1YEDe5wy+xjAoO2rngZEhLkktZqaE6UHz0G5s0MGbTzo5AUwcU
1b/UmsG9AoGBAPEIzW1fnK8ssJpZgU6UjhhFR+6QkfmHkJF56Yk+KA6TbINB92oj
CO5Ci3HS+nl6AMjfSAiZvLbhkxyc4hgGg2JcjrWX45DGN2+ItfUl41iqM8wSW80M
l3cRkSFz2bnZKgwJtyXMX5sbPqC42eeuk0IIr2DcXaNsINNSnPDihzHTAoGBAOVo
D3xnwsblAl/47lEiaD/BqyZmUKq1MuVngqIbh91l4woO1pMT0JxCxhaxcR+9iQoq
r0kddXGIjybJ9yIqbnNN0M2X3WkwLQEAQMyDms5Pu8cs7xcV12H4C9970taExEj/
/42bdgYWXYMwSyivjf91rHfdfSQ7cSzonWgWB/1nAoGAIQm61q4PVPeEMXPpRHMa
UvtUE8AfMhvB1h7mwtgRN4Y/jnJBTnwE4luer3hiurndV6s7PWqNMmgS+Q4L840Y
/yd+rCdomtSAjronbrXFxsZ1mRg/GwkJzdlLklFF27KHj+TZBMZRqHoAiJktzRLh
vmBgYZ9y+k585VpihqYWL98CgYEAqZLuP4uDkvodc0vS/e5tGRPTq6Ld5hHi+Wg2
TBYFrEZwOTMWscln3toNCyFG+atk7Tr4LxezhKTpDEcmgv7SfjD7M74aUHLoEWFa
hNKTUAXoTCaO5YWjnCt6u0wQYbnqTfvNr6NG7uEBZsQACqcaU8dsIX57zpiR5Bxe
nl4KsekCgYEA6na7ywTvwrf/Lmt+x4EbXqvKy/hSyqOUZPiaduLlGjYcZBsh7Udw
c3t29Myj3bmXNr2Fh7lqHNN4PyJ1mIp9Kv1BXowZ3SuQOPXIYIrFi+luPURvX00j
XfZODxPLF/HfGkg24cbs4EybqY78UOUS6G4IAAJZ79hHZxOcoRxLtY8=
-----END RSA PRIVATE KEY-----
kubeadm:cluster-admins
ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: kubeadm:cluster-admins
subjects:
- apiGroup: rbac.authorization.k8s.io
kind: Group
name: kubeadm:cluster-admins
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
I think this curve is overkill, and I’m open to suggestions on better cryptographic curves! ↩︎