Closed andsens closed 1 month ago
Here's a minimal reproduce in a self-contained Dockerfile (though now I'm not getting the incomaptible key usage
in the log. The renewal still fails however, and changing the --not-after=1s
on line 14 to e.g. 1m
makes everything work:
FROM cr.step.sm/smallstep/step-ca-bootstrap@sha256:5270356cf91596afe18478eab60c6c0866b2cc62618f282d42827e58f84d6eae as bootstrap
USER step
RUN mkdir certs && step certificate create --no-password --insecure --not-after=1h --template=<(echo '{\
"subject": { "commonName": {{ toJson .Subject.CommonName }} }, \
"keyUsage": ["keyEncipherment", "digitalSignature", "certSign"], \
"basicConstraints": {"isCA": true, "maxPathLen": 15}}') k3s-client-ca@1714937196 certs/root_ca.crt certs/root_ca_key
RUN mkdir config && echo '{"address": ":9000","commonName": "k3s-client-ca@1714937196","dnsNames": ["127.0.0.1"],"db": {"type": "badgerv2","dataSource": "/home/step/db"},\
"root": "/home/step/certs/root_ca.crt", "crt": "/home/step/certs/root_ca.crt", "key": "/home/step/certs/root_ca_key"}'>config/ca.json
RUN echo '{"subject": {{ toJson .AuthorizationCrt.Subject }},\
"keyUsage": ["keyEncipherment", "digitalSignature"], "extKeyUsage": ["clientAuth"]}' >x5c.tpl
RUN step ca provisioner add repro --allow-renewal-after-expiry --type X5C --x5c-root certs/root_ca.crt --x509-template x5c.tpl
RUN step certificate create --no-password --insecure --not-before=-24h --not-after=1s --template=<(echo '{ \
"subject": {"commonName": {{ toJson .Subject.CommonName }},"extraNames": [{"type":"2.5.4.10", "value": "system:masters"}]}, \
"keyUsage": ["keyEncipherment", "digitalSignature"], \
"extKeyUsage": ["clientAuth"]}') \
system:admin --ca=certs/root_ca.crt --ca-key=certs/root_ca_key peer.crt peer_key
FROM cr.step.sm/smallstep/step-ca:0.26.1
COPY --from=bootstrap /home/step /home/step
ENTRYPOINT ["/usr/bin/env", "bash", "-c"]
CMD ["\
cat config/ca.json && \
step certificate inspect certs/root_ca.crt ; \
step certificate inspect peer.crt; \
STEPDEBUG=1 step-ca &>log & pid=$! && sleep 2 && \
STEPDEBUG=1 step ca renew --ca-url 127.0.0.1:9000 --force peer.crt peer_key; \
kill $pid && wait && echo && cat log \
"]
Oooh, so because the certificate is expired authentication uses X5CInsecure with JWT instead of mTLS, which is what triggers this codepath?
@andsens exactly 🙂
Hi @andsens, I've just pushed a commit to the master branch that fixes this issue.
Due to this bug, there's a slight change in behavior. Without ClientAuth, a certificate cannot renew itself using mTLS, but this bug allowed the certificate to be renewed using the X5CInsercure flow, used for expired certificates or --mtls=false
. This was not our intention, and right now, mTLS and non-mTLS requirements are the same.
But that's fine, the client cert has client auth:
X509v3 extensions:
X509v3 Authority Key Identifier:
keyid:17:E0:10:F6:11:7E:B2:16:9F:DB:21:A1:36:D7:10:06:57:F1:8B:F4
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
Client Authentication
X509v3 Subject Key Identifier:
D9:54:C3:DC:52:9F:C7:18:BF:F2:88:FE:DE:DB:C8:70:7A:F5:59:9B
:-D
I made a Dockerfile for an easy reproduce in the next comment.
Steps to Reproduce
So I'm trying to create an authority for issuing and renewing Kubernetes client certificates in k3s. To that end I am hostpath mounting the k3s client-ca into step-ca and specifying it both as root and intermediate.
The template is configured so that the subject cannot be changed:
To bootstrap it all, the first cert is issued by running
step certificate create
using an inline template.To renew certificates I added an X5C provisioner with the same client-ca. The relevant parts of the config look like this:
The bootstrapped certificate works and I am even able to renew it with the CA when the client certificate is still valid. However, once the certificate has expired,
step ca renew --force system:admin.crt system:admin_key
fails on the server with:client output:
A client cert looks like this:
The kubernetes client ca looks like this:
(Note that there is no PathLength restriction, so setting it as root should be OK I believe)
Your Environment
step-ca
Version - 0.26.1Expected Behavior
Since
allowRenewalAfterExpiry
istrue
, the certificate should be renewed.Actual Behavior
The certificate renewal request fails.
Additional Context
So far I have traced the error from
renew.go
, throughauthorize.go
tocrytpto/jose/parse.go
, tozcrypto/x509/verify.go
(the only place I found that actually returnsIncompatibleUsage
) tocheckChainForKeyUsage()
in that same file.Now, at first glance this seems to be similar to smallstep/cli#467, but no certificates involved in the defaults templates from
step ca init
specify the ServerAuth ext key usage either, so obviously I'm reading some code wrong. Additionally, the date check happens after the key usage check, which confuses me even more as to how that error is the one I'm seeing. All in all, I really tried to see what I'm doing wrong or how I can work around a potential limitation, but I'm just not grok'ing the code well enough to follow the thread.Contributing
Vote on this issue by adding a 👍 reaction. To contribute a fix for this issue, leave a comment (and link to your pull request, if you've opened one already).
p,s,: What I'm trying to do is an ideal use-case for #186 btw. Right now I'm running a separate step-ca to issue SSH/HTTP certs etc.