{"id":5275,"date":"2026-06-11T09:14:28","date_gmt":"2026-06-11T09:14:28","guid":{"rendered":"https:\/\/geekmungus.co.uk\/?p=5275"},"modified":"2026-06-11T09:14:28","modified_gmt":"2026-06-11T09:14:28","slug":"generate-openssl-keys-and-certificate-for-use-with-kubernetes","status":"publish","type":"post","link":"https:\/\/geekmungus.co.uk\/?p=5275","title":{"rendered":"Generate OpenSSL Keys and Certificate for Use with Kubernetes"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">We&#8217;ll create user called &#8220;dave&#8221; to use within a Kubernetes cluster, I&#8217;m using Minikube in this case.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Create Private Key<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create the private key:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>openssl genrsa -out dave.key 2048<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Create and Sign the CSR<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now create the Certificate Signing Request (CSR):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>openssl req -new -key dave.key -out dave.csr -subj \"\/CN=dave\/O=admin\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now on this the subject is important. Here you are defining their username (CN), &#8220;dave&#8221; in this case, and then the group (O) in this case is &#8220;admin&#8221;.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We now need to sign the requests (CSRs) with the Kubernetes Certificate Authority (CA). Note i&#8217;m using Minikube in this example.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We now need to create a CSR.yaml file we can use to create the signing request to the Kubernetes CA.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We first need to get the CSR in Base64, so we can add it to the CSR.yaml, so we do this with the following, we are also removing any newline characters with &#8220;tr&#8221;.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat alice.csr | base64 | tr -d \"\\n\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now we can create the CSR.yaml as follows and paste in the CSR (Base64) encoded we just created:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: certificates.k8s.io\/v1\nkind: CertificateSigningRequest\nmetadata:\n  name: alice\nspec:\n  request: &lt;YOUR CSR BASE64 HERE&gt;\n  signerName: kubernetes.io\/kube-apiserver-client\n  expirationSeconds: 86400\n  usages:\n    - client auth<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">So once done, run kubectl to create theCSR.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl apply -f csr.yaml<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">To check it has worked, we can run the following to see the CSR within Kubernetes.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get certificatesigningrequest<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">For example:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>NAME    AGE   SIGNERNAME                            REQUESTOR       REQUESTEDDURATION   CONDITION\ndave 54s   kubernetes.io\/kube-apiserver-client   minikube-user   24h                 Pending<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Notice however it is saying &#8220;Pending&#8221;, so we now need to approve these CSRs.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl certificate approve dave<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">And repeat the above command, we can see this is now &#8220;approved&#8221;.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>NAME    AGE   SIGNERNAME                            REQUESTOR       REQUESTEDDURATION   CONDITION\ndave 54s   kubernetes.io\/kube-apiserver-client   minikube-user   24h                 Approved,Issued<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Get Signed Certificate<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To take a look at it, we can then run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get certificatesigningrequest dave -o yaml<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Within this output, you&#8217;ll find a section called &#8220;Certificate&#8221; which is what we want to obtain to be able to have the signed certificate.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get csr dave -o jsonpath='{.status.certificate}' | base64 -d &gt; dave.crt<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">To take a look inside of the certificate, we can use:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>openssl x509 -noout -text -in dave.crt<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;d get an output like the following within which we can see the &#8220;Subject&#8221; as &#8220;O = admin, CN = bob&#8221; as per what we did earlier on.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Certificate:\n    Data:\n        Version: 3 (0x2)\n        Serial Number:\n            8f:4b:1a:a1:6d:77:66:59:8f:7a:a8:d6:3f:c9:51:38\n        Signature Algorithm: sha256WithRSAEncryption\n        Issuer: CN = minikubeCA\n        Validity\n            Not Before: Jun 10 08:25:37 2026 GMT\n            Not After : Jun 11 08:25:37 2026 GMT\n        Subject: O = admin, CN = bob\n        Subject Public Key Info:\n            Public Key Algorithm: rsaEncryption\n                Public-Key: (2048 bit)\n                Modulus:\n                    00:a0:44:ea:98:c9:e4:f0:dd:84:db:00:fc:44:86:\n                    aa:c0:55:2f:b4:48:1b:fa:fa:f5:b3:45:e6:97:98:\n                    2e:05:b6:f7:40:cc:a2:1a:8b:86:0a:d3:84:22:b9:\n                    8f:b1:8d:5d:3b:99:8f:16:9f:23:0a:7d:ff:84:51:<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Context<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Create<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl config set-context bob--cluster minikube --user dave<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This will create a user and a context or that user within Kubernetes.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl config set-credentials dave --client-key $(realpath dave.key) --client-certificate $(realpath dave.crt) --embed-certs=true<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If we now run: <strong>kubectl config view<\/strong>, we&#8217;ll see that we have a new context, and further down the file we see the new user created, with the certificate and key data as &#8220;omitted&#8221; because it is stored directly within Kubernetes, rather than referring to files on disk. If you leave off the &#8220;&#8211;embed-certs=true&#8221; from the end, you&#8217;ll see that it instead points to the files on disk.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>...\ncontexts:\n- context:\n    cluster: minikube\n    user: alice\n  name: alice\n- context:\n    cluster: minikube\n    extensions:\n...\nusers:\n- name: dave\n  user:\n    client-certificate-data: DATA+OMITTED\n    client-key-data: DATA+OMITTED\n- name: minikube\n  user:\n    client-certificate: \/home\/user\/.minikube\/profiles\/minikube\/client.crt\n    client-key: \/home\/user\/.minikube\/profiles\/minikube\/client.key<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Test Context<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now try to swap context with:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl config use-context dave<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">And check with the following which should just show &#8220;dave&#8221; as the current context.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl config current-context<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If you then run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl config view<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">And within the output look for the specific &#8220;current-context&#8221;, which will say &#8220;dave&#8221;. All commands now run will be done so under the &#8220;dave&#8221; context.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We&#8217;ve explored creating a user and keys to allow a user to access Kubernetes and swap context  to actually use that user within Kubernetes. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">What you will find however is that although the user has access to Kubernetes, we&#8217;ve not yet provided any <strong>rolebindings <\/strong>or <strong>clusterolebindings <\/strong>to provide them with any privileges!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We&#8217;ll create user called &#8220;dave&#8221; to use within a Kubernetes cluster, I&#8217;m using Minikube in this case. Create Private Key Create the private key: Create and Sign the CSR Now create the Certificate Signing Request (CSR): Now on this the subject is important. Here you are defining their username (CN), &#8220;dave&#8221; in this case, and &#8230; <a title=\"Generate OpenSSL Keys and Certificate for Use with Kubernetes\" class=\"read-more\" href=\"https:\/\/geekmungus.co.uk\/?p=5275\" aria-label=\"Read more about Generate OpenSSL Keys and Certificate for Use with Kubernetes\">Read more<\/a><\/p>\n","protected":false},"author":4,"featured_media":4850,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[10,1],"tags":[],"class_list":["post-5275","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-kubernetes","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/5275","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=5275"}],"version-history":[{"count":11,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/5275\/revisions"}],"predecessor-version":[{"id":5286,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/5275\/revisions\/5286"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/media\/4850"}],"wp:attachment":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=5275"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5275"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5275"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}