{"id":5289,"date":"2026-06-12T09:52:21","date_gmt":"2026-06-12T09:52:21","guid":{"rendered":"https:\/\/geekmungus.co.uk\/?p=5289"},"modified":"2026-06-12T09:52:42","modified_gmt":"2026-06-12T09:52:42","slug":"kubernetes-certificates-expiry-and-logins","status":"publish","type":"post","link":"https:\/\/geekmungus.co.uk\/?p=5289","title":{"rendered":"Kubernetes (Minikube) &#8211; Certificates, Expiry and Logins"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">I was using Minikube and had created some users with some certificates (see a previous article), however upon trying to login the following day and attempt to perform some commands I got this error:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl config use-context bob<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">When running a &#8220;get pods&#8221;, I see I&#8217;m not actually authenticated!<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ kubectl get pods\nerror: You must be logged in to the server (Unauthorized)<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Hunting the Issue<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Looking under the Minikube logs, and specifically at the API Server (being that is what i&#8217;m attempting to access) what did I find&#8230;.?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>minikube logs --file=logs.txt<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>==> kube-apiserver &#91;8567a0d00751] &lt;==\n...\nE0612 08:54:39.300791       1 authentication.go:73] \"Unable to authenticate the request\" err=\"&#91;x509: certificate has expired or is not yet valid: current time 2026-06-12T08:54:39Z is after 2026-06-11T08:25:37Z, verifying certificate SN=67937780518389855383239215857675577693, SKID=, AKID=2F:24:CC:BD:09:6B:24:92:92:EF:40:37:16:B6:18:4B:29:25:0B:03 failed: x509: certificate has expired or is not yet valid: current time 2026-06-12T08:54:39Z is after 2026-06-11T08:25:37Z]\"\nE0612 08:54:39.377540       1 authentication.go:73] \"Unable to authenticate the request\" err=\"&#91;x509: certificate has expired or is not yet valid: current time 2026-06-12T08:54:39Z is after 2026-06-11T08:25:37Z, verifying certificate SN=67937780518389855383239215857675577693, SKID=, AKID=2F:24:CC:BD:09:6B:24:92:92:EF:40:37:16:B6:18:4B:29:25:0B:03 failed: x509: certificate has expired or is not yet valid: current time 2026-06-12T08:54:39Z is after 2026-06-11T08:25:37Z]\"\nE0612 09:10:17.218577       1 authentication.go:73] \"Unable to authenticate the request\" err=\"&#91;x509: certificate has expired or is not yet valid: current time 2026-06-12T09:10:17Z is after 2026-06-11T08:25:37Z, verifying certificate SN=67937780518389855383239215857675577693, SKID=, AKID=2F:24:CC:BD:09:6B:24:92:92:EF:40:37:16:B6:18:4B:29:25:0B:03 failed: x509: certificate has expired or is not yet valid: current time 2026-06-12T09:10:17Z is after 2026-06-11T08:25:37Z]\"\nE0612 09:12:18.527477       1 authentication.go:73] \"Unable to authenticate the request\" err=\"&#91;x509: certificate has expired or is not yet valid: current time 2026-06-12T09:12:18Z is after 2026-06-11T08:25:37Z, verifying certificate SN=67937780518389855383239215857675577693, SKID=, AKID=2F:24:CC:BD:09:6B:24:92:92:EF:40:37:16:B6:18:4B:29:25:0B:03 failed: x509: certificate has expired or is not yet valid: current time 2026-06-12T09:12:18Z is after 2026-06-11T08:25:37Z]\"\n...<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Ah ha, the certificate for my user has expired, let&#8217;s check it out:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ openssl x509 -in dave.crt -noout -text | grep ' Not '\n            Not Before: Jun 10 08:25:37 2026 GMT\n            Not After : Jun 11 08:25:37 2026 GMT<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Yep, the certificate has indeed expired I was attempting to connect at after 08:25 in the morning, so now I need to renew it.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Renew Certificate<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">I already have a key, so need to just generate a new 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=dev\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Now get it signed.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>cat dave.csr | base64 | tr -d \"\\n\"<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Create (or update) the CSR yaml file, pasting in the Base64 encoded CSR.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: certificates.k8s.io\/v1\nkind: CertificateSigningRequest\nmetadata:\n  name: dave\nspec:\n  request: &lt;CSR Base64 String>\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\">Notice the 86400 (1 day\/24 hours) in the expirationsSeconds.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Apply that:<\/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\">Check on it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get certificatesigningrequests<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">And we can see it indeed was a 24 hour request:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ kubectl get certificatesigningrequests\nNAME    AGE   SIGNERNAME                            REQUESTOR       REQUESTEDDURATION   CONDITION\ndave     21s   kubernetes.io\/kube-apiserver-client   minikube-user   24h                 Pending<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We now need to approve it.<\/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\">Now we see it is approved and issued.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ kubectl get certificatesigningrequests\nNAME    AGE     SIGNERNAME                            REQUESTOR       REQUESTEDDURATION   CONDITION\ndave 5m17s   kubernetes.io\/kube-apiserver-client   minikube-user   24h                 Approved,Issued<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Get the certificate:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get csr dave -o jsonpath='{.status.certificate}' | base64 -d > dave.crt<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Configure the credentials for the user to use the new certificate just issued, the &#8220;realpath&#8221; ensures a full path to the file is used.<\/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)<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If we now check it:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>openssl x509 -in dave.crt -noout -text | grep ' Not '<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We can see we are good for another day, time of running was June 12th 2026, 10:45, so good until the following morning.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ openssl x509 -in dave.crt -noout -text | grep ' Not '\n            Not Before: Jun 12 09:34:42 2026 GMT\n            Not After : Jun 13 09:34:42 2026 GMT<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Testing<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now we test to see if we can authenticate.<\/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 now query for something we know we have privilege&#8217;s for (within Dave&#8217;s role):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ kubectl get pod -n dev\nNAME    READY   STATUS    RESTARTS   AGE\nnginx   1\/1     Running   0          60m<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Lovely, that&#8217;s that, we&#8217;re up and running again.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A potentially common problem, and a balance of certificate lifetime against risk of compromise. You can decide how long certificates should be issued for. Its obviously better to have some automated process to generate renewals for you.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can also set the expirationSeconds within the CSR to something longer if you so wish to avoid having to re-run this process so frequently!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Quick Synopisis of the commands used:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>openssl req -new -key dave.key -out dave.csr -subj \"\/CN=dave\/O=dev\"\ncat dave.csr | base64 | tr -d \"\\n\"\nUpdate CSR yaml file with new Base64 encoded CSR.\nkubectl apply -f csr.yaml\nkubectl get certificatesigningrequests\nkubectl certificate approve dave\nkubectl get certificatesigningrequests\nkubectl get csr dave -o jsonpath='{.status.certificate}' | base64 -d > dave.crt\nkubectl config set-credentials dave --client-key $(realpath dave.key) --client-certificate $(realpath dave.crt)\n\nThen test with:\n\nkubectl config use-context dave\nkubectl get pod -n dev<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Additional Information<\/h2>\n\n\n\n<figure class=\"wp-block-embed is-type-wp-embed is-provider-ralph-039-s-open-source-blog wp-block-embed-ralph-039-s-open-source-blog\"><div class=\"wp-block-embed__wrapper\">\n<blockquote class=\"wp-embedded-content\" data-secret=\"qhIMUXF0Dt\"><a href=\"https:\/\/ralph.blog.imixs.com\/2022\/01\/09\/kubectl-get-nodes-error-you-must-be-logged-in-to-the-server\/\">kubectl get nodes error: You must be logged in to the server<\/a><\/blockquote><iframe loading=\"lazy\" class=\"wp-embedded-content\" sandbox=\"allow-scripts\" security=\"restricted\" style=\"position: absolute; visibility: hidden;\" title=\"\u201ckubectl get nodes error: You must be logged in to the server\u201d \u2014 Ralph&amp;apos;s Open Source Blog\" src=\"https:\/\/ralph.blog.imixs.com\/2022\/01\/09\/kubectl-get-nodes-error-you-must-be-logged-in-to-the-server\/embed\/#?secret=TumXtOLUqL#?secret=qhIMUXF0Dt\" data-secret=\"qhIMUXF0Dt\" width=\"600\" height=\"338\" frameborder=\"0\" marginwidth=\"0\" marginheight=\"0\" scrolling=\"no\"><\/iframe>\n<\/div><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>I was using Minikube and had created some users with some certificates (see a previous article), however upon trying to login the following day and attempt to perform some commands I got this error: When running a &#8220;get pods&#8221;, I see I&#8217;m not actually authenticated! Hunting the Issue Looking under the Minikube logs, and specifically &#8230; <a title=\"Kubernetes (Minikube) &#8211; Certificates, Expiry and Logins\" class=\"read-more\" href=\"https:\/\/geekmungus.co.uk\/?p=5289\" aria-label=\"Read more about Kubernetes (Minikube) &#8211; Certificates, Expiry and Logins\">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],"tags":[],"class_list":["post-5289","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-kubernetes"],"_links":{"self":[{"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/5289","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=5289"}],"version-history":[{"count":3,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/5289\/revisions"}],"predecessor-version":[{"id":5292,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=\/wp\/v2\/posts\/5289\/revisions\/5292"}],"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=5289"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=5289"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/geekmungus.co.uk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=5289"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}