smallstep / cli

🧰 A zero trust swiss army knife for working with X509, OAuth, JWT, OATH OTP, etc.
https://smallstep.com/cli
Apache License 2.0
3.57k stars 247 forks source link

Add OCSP and CRL support to certificate verify #1161

Closed redrac closed 2 months ago

redrac commented 2 months ago

Name of feature:

Add OCSP and CRL support to certificate verify

Pain or issue this feature alleviates:

Add args and functionality to certificate verify to check a CRL and OCSP for a certificate based on the extensions. Users can pass flags to enable verification of each (CRL, OCSP). The command will try and get the CRL and OCSP server from the certificate extensions if the endpoints are not provided.

Supporting links/other PRs/issues:

Implements #845

Notes

redrac commented 2 months ago

Getting a certificate, before revoking:

export STEPPATH=/etc/step
TOKEN=$(step ca token --provisioner-password-file=pass.txt --provisioner=provisioner@acme.com foo.acme.com)

redrac@test-host:~$ step ca certificate --token ${TOKEN} foo.acme.com foo.crt foo.key
✔ CA: https://dev-step-ca.acme.com
✔ Certificate: foo.crt
✔ Private Key: foo.key

$ step certificate inspect foo.crt
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number: 250957313983734049942497464497330310647 (0xbccc9ede18bfa11b2f8f6de16055cdf7)
    Signature Algorithm: ECDSA-SHA256
        Issuer: ****************************************
        Validity
            Not Before: Apr 28 21:58:41 2024 UTC
            Not After : May 28 21:58:51 2024 UTC
        Subject: CN=foo.acme.com
....
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature
            X509v3 Extended Key Usage:
                Server Authentication, Client Authentication
            X509v3 Subject Key Identifier:
                E0:A3:9B:7D:AC:AC:98:72:69:4C:C8:70:CC:23:D1:10:8F:46:DF:83
            X509v3 Authority Key Identifier:
                keyid:0B:53:D4:15:2F:90:92:87:93:67:E7:9D:BB:64:B2:B6:D8:E4:AA:67
            Authority Information Access:
                OCSP - URI:http://dev-step-ca.acme.com/ocsp
                CA Issuers - URI:https://dev-step-docs.acme.com/certs/intermediate.crt
            X509v3 Subject Alternative Name:
                DNS:foo.acme.com
                email:provisioner@acme.com
            X509v3 CRL Distribution Points:
                Full Name:
                  URI:http://dev-step-ca.acme.com/crl
            X509v3 Step Provisioner:
                Type: JWK
                Name: provisioner@acme.com
                CredentialID: LhmOBZ3rNZfv49GHM9bLuCq2px2KV03-9REcHaa5ikw
...

Revoking:

redrac@test-host:~$ step ca revoke --cert foo.crt --key foo.key
✔ CA: https://dev-step-ca.acme.com
Certificate with Serial Number 250957313983734049942497464497330310647 has been revoked.

$ step crl inspect --insecure foo_crl
Certificate Revocation List (CRL):
    Data:
        Valid: false
        Version: 656 (0x290)
    Signature algorithm: ECDSA-SHA256
        Issuer:
        Last Update: 2024-04-28 21:59:50 +0000 UTC
        Next Update: 2024-04-29 21:59:50 +0000 UTC
        CRL Extensions:
            X509v3 Authority Key Identifier:
                keyid:0B:53:D4:15:2F:90:92:87:93:67:E7:9D:BB:64:B2:B6:D8:E4:AA:67
            X509v3 CRL Number:
                656
            X509v3 Issuing Distribution Point: critical
                Full Name:
                    URI:http://dev-step-ca.acme.com/crl
                Only User Certificates
        Revoked Certificates:
            Serial Number: 250957313983734049942497464497330310647 (0xBCCC9EDE18BFA11B2F8F6DE16055CDF7)
                Revocation Date: 2024-04-28 21:59:50 +0000 UTC
...

Verifying with step certificate verify:

$ ./step certificate verify foo.crt --roots foo_roots.crt --ca foo_issuer.crt  --verify-verbose
certificate validated against roots
certficiate is valid
$ echo $?
0

$ ./step certificate verify foo.crt --roots foo_roots.crt --ca foo_issuer.crt  --verify-crl --verify-verbose
certificate marked as revoked in CRL
$ echo $?
1

$ ./step certificate verify foo.crt --roots foo_roots.crt --ca foo_issuer.crt --verify-ocsp  --verify-verbose
certificate has been revoked according to OCSP
$ echo $?
1
redrac commented 2 months ago

And a non-revoked cert:

$ ./step certificate verify ./certificate.pem --roots /etc/ssl/certs/ --ca ./intermediate.pem  --verify-crl --verify-ocsp  --verify-verbose
certificate validated against roots
certificate not revoked in CRL
certificate status shows good in OCSP
certficiate is valid
$ echo $?
0
redrac commented 2 months ago

Existing CRL functionality works still..

$ ./step crl inspect --ca foo_issuer.pem http://dev-step-ca.acme.com/crl
Certificate Revocation List (CRL):
    Data:
        Valid: false
        Version: 656 (0x290)
    Signature algorithm: ECDSA-SHA256
        Issuer:
        Last Update: 2024-04-28 21:59:50 +0000 UTC
        Next Update: 2024-04-29 21:59:50 +0000 UTC
        CRL Extensions:
            X509v3 Authority Key Identifier:
                keyid:0B:53:D4:15:2F:90:92:87:93:67:E7:9D:BB:64:B2:B6:D8:E4:AA:67
            X509v3 CRL Number:
                656
            X509v3 Issuing Distribution Point: critical
                Full Name:
                    URI:http://dev-step-ca.acme.com/crl
                Only User Certificates
        Revoked Certificates:
            Serial Number: 250957313983734049942497464497330310647 (0xBCCC9EDE18BFA11B2F8F6DE16055CDF7)
                Revocation Date: 2024-04-28 21:59:50 +0000 UTC
..

And JSON:

$ ./step crl inspect --ca foo_issuer.pem http://dev-step-ca.acme.com/crl --format json
{
  "version": 657,
  "signature_algorithm": {
    "name": "ECDSA-SHA256",
    "oid": "1.2.840.10045.4.3.2"
  },
  "issuer": {
    "organization": [
redrac commented 2 months ago

Try verifying a cert against a user provided CRL

$ ./step certificate verify foo.crt --roots foo_roots.crt --ca foo_issuer.crt  --verify-verbose --verify-crl --crl-endpoint http://dev-step-ca.acme.com/crl
certificate marked as revoked in CRL http://dev-step-ca.acme.com/crl

Try verifying a cert against a user provided CRL for a different CA

$ ./step certificate verify foo.crt --roots foo_roots.crt --ca foo_issuer.crt  --verify-verbose --verify-crl --crl-endpoint http://step-ca.acme.com/crl
error validating the CRL against the CA issuer: x509: ECDSA verification failure

Try verifying a cert against a user provided OCSP server

$ ./step certificate verify foo.crt --roots foo_roots.crt --ca foo_issuer.crt  --verify-verbose --verify-ocsp --ocsp-endpoint http://dev-step-ca.acme.com/ocsp
certificate has been revoked according to OCSP http://dev-step-ca.acme.com/ocsp

Try verifying a cert against an OCSP for a different CA

$ ./step certificate verify foo.crt --roots foo_roots.crt --ca foo_issuer.crt  --verify-verbose --verify-ocsp --ocsp-endpoint http://step-ca.acme.com/ocsp
error parsing repsonse from OCSP server: http://step-ca.acme.com/ocsp
redrac commented 2 months ago

Linting fixed @maraino

redrac commented 2 months ago

Updated to

For the CRL & OCSP endpoints, as long as we get a valid response from a CRL or OCSP we break the loop; whether the response indicates the certificate is good or revoked or unknown makes no difference to breaking the loop.

redrac commented 2 months ago

Running against a public website

# ./step certificate verify --verify-crl --verify-ocsp --verify-verbose https://google.com
certificate validated against roots
certificate not revoked in CRL http://c.pki.goog/wr2/GSyT1N4PBrg.crl
certificate status is good according OCSP http://o.pki.goog/wr2
certficiate is valid

Running against internal website with private CA

$ ./step certificate verify foo.crt --roots foo_roots.crt --verify-verbose --verify-crl --verify-ocsp
certificate validated against roots
certificate not revoked in CRL http://dev-step-ca.acme.com/crl
certificate status is good according OCSP http://dev-step-ca.acme.com/ocsp
certficiate is valid

Running against internal website with private CA after revoking

$ ./step certificate verify foo.crt --roots foo_roots.crt --verify-verbose --verify-ocsp
certificate has been revoked according to OCSP http://dev-step-ca.acme.com/ocsp

$ ./step certificate verify foo.crt --roots foo_roots.crt --verify-verbose --verify-crl
certificate marked as revoked in CRL http://dev-step-ca.acme.com/crl
redrac commented 2 months ago

@maraino looks, good I made one small tweak to the break logic

hslatman commented 2 months ago

Late to the game, but is it an option to rename the flags to shorter versions, e.g. --crl and --ocsp? Given that they're used on the verify subcommand, I think the shorter names are sufficient. Or is it expected that those will be reused on (many) other subcommands in the future?