OpenVPN / easy-rsa

easy-rsa - Simple shell based CA utility
Other
4.05k stars 1.2k forks source link

Providing nameConstraints and pathlen in subca CSR #934

Closed zoltan-magyar closed 1 year ago

zoltan-magyar commented 1 year ago

I started migrating my OpenSSL configurations of my current chain to easy-rsa but I hit a few roadblocks.

My current chain looks like this:

My main goal was to make it as effortless as it can be to generate them, trying to eliminate as much CLI magic as I could with OpenSSL configuration files. (It's worth noting that this is a homelab project, so I fiddle with them often)

My problems should probably be broken down to multiple Issues since they are separate. I couldn't get the pathlen to work on my Root, but I can let that issue go for now.

I was using separate OpenSSL configs for all certificates previously, which worked quite well. I provided CA/server specific information (SANs, nameConstraints) in the CSR itself, while generic information came from the signing CA. When I signed, I copied the CSR extensions over.

Currently I'm trying to include nameConstraints in my subca CSR, but unsuccessfully. I edited the OpenSSL config in my subca PKI folder, which is supposedly is included in the req settings, but it does not appear on the CSR.

The example is here:

[ easyrsa_ca ]

# PKIX recommendations:

subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer:always

# This could be marked critical, but it's nice to support reading by any
# broken clients who attempt to do so.
basicConstraints = CA:true, pathlen:0
nameConstraints = critical, permitted;DNS:.home

# Limit key usage to CA tasks. If you really want to use the generated pair as
# a self-signed cert, comment this out.
keyUsage = cRLSign, keyCertSign

# nsCertType omitted by default. Let's try to let the deprecated stuff die.
# nsCertType = sslCA

# A placeholder to handle the $X509_TYPES and CA extra extensions $EXTRA_EXTS:
#%CA_X509_TYPES_EXTRA_EXTS% # Do NOT remove or change this line as $X509_TYPES and EXTRA_EXTS demands it

# CRL extensions.

A similar problem is going to arise when I'm trying to create my server certificates, since there is no OpenSSL config filed that I know of.

I would be interested in best-practices for my usecase. This is the most I could get out of the documentation.

I'm trying to do something similar to this, but with the tweaks mentioned above:

# Build root CA:
EASYRSA_PKI=offline ./easyrsa init-pki
EASYRSA_PKI=offline ./easyrsa build-ca nopass

# Build sub-CA request:
EASYRSA_PKI=sub ./easyrsa init-pki
EASYRSA_PKI=sub ./easyrsa build-ca nopass subca

# Import the sub-CA request under the short-name "sub" on the offline PKI:
EASYRSA_PKI=offline ./easyrsa import-req sub/reqs/ca.req sub
# Then sign it as a CA:
EASYRSA_PKI=offline ./easyrsa sign-req ca sub
# Transport sub-CA cert to sub PKI:
cp offline/issued/sub.crt sub/ca.crt

# Generate and sign some requests on the sub-CA.
# Real-world use should import a CSR from the actual clients. We don't for brevity here.
EASYRSA_PKI=sub ./easyrsa gen-req server nopass
EASYRSA_PKI=sub ./easyrsa gen-req client nopass
EASYRSA_PKI=sub ./easyrsa sign-req server server
EASYRSA_PKI=sub ./easyrsa sign-req client client

# Finally, create "bundle" files for use at each entity (ie: server and client ends.)
cat sub/issued/server.crt sub/ca.crt > server-bundle.crt
cat sub/issued/client.crt sub/ca.crt > client-bundle.crt
zoltan-magyar commented 1 year ago

I needed some time to understand the source, and my pathlen problem is already solved with the x509-dir. So no worries there.

I also found the issue with nameConstraints:

The problem is the openSSL config that's generated on easyrsa init-pki:

[ req ]
default_bits        = $ENV::EASYRSA_KEY_SIZE
default_keyfile = privkey.pem
default_md      = $ENV::EASYRSA_DIGEST
distinguished_name  = $ENV::EASYRSA_DN
x509_extensions     = easyrsa_ca    # Only applies to -x509, but subca doesn't use it, so it's ignored

Basically, this cnf is working as intended for self-signed root CAs, because they use the -x509 flag. The problem is that if we are creating a subca, which spits out a CSR, that does not use this flag. For that, req_extensions should be used.

I do believe that the ca x509-dir contents are relevant here, since it is a CA, although I'm not sure if this problem should be approached from the signer CA's side. It's also worth noting that this will remain useless unless we copy the CSR extensions.

My suggestion would be to add a line on the OpenSSL config template, resolving req_extensions to the same easyrsa_ca, without the authorityKeyIdentifier, since that cannot be resolved for a CSR. As far as I know this would not affect anything else, only subca's.

TinCanTech commented 1 year ago

Please raise a PR showing your changes, with a description of the change.

Or, minimally, a diff, posted here.

TinCanTech commented 1 year ago

The way EasyRSA sources /x509-types is as follows:

Edit the pki/x509-types as you require. Share your changes, if you like.

It is unlikely that the default x509-types will change, unless there is a bug.