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:
kubectl config use-context bob
When running a “get pods”, I see I’m not actually authenticated!
$ kubectl get pods
error: You must be logged in to the server (Unauthorized)
Hunting the Issue
Looking under the Minikube logs, and specifically at the API Server (being that is what i’m attempting to access) what did I find….?
minikube logs --file=logs.txt
==> kube-apiserver [8567a0d00751] <==
...
E0612 08:54:39.300791 1 authentication.go:73] "Unable to authenticate the request" err="[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]"
E0612 08:54:39.377540 1 authentication.go:73] "Unable to authenticate the request" err="[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]"
E0612 09:10:17.218577 1 authentication.go:73] "Unable to authenticate the request" err="[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]"
E0612 09:12:18.527477 1 authentication.go:73] "Unable to authenticate the request" err="[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]"
...
Ah ha, the certificate for my user has expired, let’s check it out:
$ openssl x509 -in dave.crt -noout -text | grep ' Not '
Not Before: Jun 10 08:25:37 2026 GMT
Not After : Jun 11 08:25:37 2026 GMT
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.
Renew Certificate
I already have a key, so need to just generate a new CSR.
openssl req -new -key dave.key -out dave.csr -subj "/CN=dave/O=dev"
Now get it signed.
cat dave.csr | base64 | tr -d "\n"
Create (or update) the CSR yaml file, pasting in the Base64 encoded CSR.
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
name: dave
spec:
request: <CSR Base64 String>
signerName: kubernetes.io/kube-apiserver-client
expirationSeconds: 86400
usages:
- client auth
Notice the 86400 (1 day/24 hours) in the expirationsSeconds.
Apply that:
kubectl apply -f csr.yaml
Check on it.
kubectl get certificatesigningrequests
And we can see it indeed was a 24 hour request:
$ kubectl get certificatesigningrequests
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
dave 21s kubernetes.io/kube-apiserver-client minikube-user 24h Pending
We now need to approve it.
kubectl certificate approve dave
Now we see it is approved and issued.
$ kubectl get certificatesigningrequests
NAME AGE SIGNERNAME REQUESTOR REQUESTEDDURATION CONDITION
dave 5m17s kubernetes.io/kube-apiserver-client minikube-user 24h Approved,Issued
Get the certificate:
kubectl get csr dave -o jsonpath='{.status.certificate}' | base64 -d > dave.crt
Configure the credentials for the user to use the new certificate just issued, the “realpath” ensures a full path to the file is used.
kubectl config set-credentials dave --client-key $(realpath dave.key) --client-certificate $(realpath dave.crt)
If we now check it:
openssl x509 -in dave.crt -noout -text | grep ' Not '
We can see we are good for another day, time of running was June 12th 2026, 10:45, so good until the following morning.
$ openssl x509 -in dave.crt -noout -text | grep ' Not '
Not Before: Jun 12 09:34:42 2026 GMT
Not After : Jun 13 09:34:42 2026 GMT
Testing
Now we test to see if we can authenticate.
kubectl config use-context dave
And now query for something we know we have privilege’s for (within Dave’s role):
$ kubectl get pod -n dev
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 60m
Lovely, that’s that, we’re up and running again.
Conclusion
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.
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!
Quick Synopisis of the commands used:
openssl req -new -key dave.key -out dave.csr -subj "/CN=dave/O=dev"
cat dave.csr | base64 | tr -d "\n"
Update CSR yaml file with new Base64 encoded CSR.
kubectl apply -f csr.yaml
kubectl get certificatesigningrequests
kubectl certificate approve dave
kubectl get certificatesigningrequests
kubectl get csr dave -o jsonpath='{.status.certificate}' | base64 -d > dave.crt
kubectl config set-credentials dave --client-key $(realpath dave.key) --client-certificate $(realpath dave.crt)
Then test with:
kubectl config use-context dave
kubectl get pod -n dev