Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow for nested organizational units without the use of multi-value relative distinguished names #10281

Closed
dacodas opened this issue Oct 30, 2020 · 2 comments

Comments

@dacodas
Copy link

dacodas commented Oct 30, 2020

Is your feature request related to a problem? Please describe.
I would like to be able to represent nested organizational units in the Vault-generated certificates' subject name in the same way that other directory services and openssl allow.

Describe the solution you'd like
It would be absolutely great if I could somehow specify the Subject for the CSR. Whether that be through a syntax similar to OpenSSL (e.g. subj='/CN=Dacoda Strack/OU=Subgroup/OU=Information Technology/O=Dacoda Strack LLC/') or by passing through some base64 encoded DER.

The reason I mention the base64 encoded DER is that in the documentation for Golang's pkix.Name (which I believe Vault is using to create the subject), it says

If an accurate representation is needed, asn1.Unmarshal the raw subject or issuer as an RDNSequence.

I imagine calling something like this from my shell.

vault write $VAULT_PKI_NAME/issue/$VAULT_PKI_ROLE \
	-subj 'MGgxFjAUBgNVBAMMDURhY29kYSBTdHJhY2sxETAPBgNVBAsMCFN1Ymdyb3VwMR8wHQYDVQQLDBZJbmZvcm1hdGlvbiBUZWNobm9sb2d5MRowGAYDVQQKDBFEYWNvZGEgU3RyYWNrIExMQw=='

Describe alternatives you've considered
I can specify multiple organizational units through the API, but they are encoded differently that expected from, say, OpenSSL or AD.

Explain any additional use-cases

Additional context

Here is a somewhat human-readable representation of the DER that I get from vault...

# vault write vault-issue-pki/issue/vault-issue-example-client-certificates \
> 	-format=json \
> 	'organization=Dacoda Strack LLC' \
> 	'ou=Information Technology,Subgroup' \
> 	'common_name=Dacoda Strack' \
> 	> 'build/vault-issue-pki/certs/Dacoda Strack/Dacoda Strack.json'

# jq -r .data.certificate 'build/vault-issue-pki/certs/Dacoda Strack/Dacoda Strack.json' | openssl asn1parse -i -strparse 190
    0:d=0  hl=2 l= 102 cons: SEQUENCE          
    2:d=1  hl=2 l=  26 cons:  SET               
    4:d=2  hl=2 l=  24 cons:   SEQUENCE          
    6:d=3  hl=2 l=   3 prim:    OBJECT            :organizationName
   11:d=3  hl=2 l=  17 prim:    PRINTABLESTRING   :Dacoda Strack LLC
   30:d=1  hl=2 l=  48 cons:  SET               
   32:d=2  hl=2 l=  29 cons:   SEQUENCE          
   34:d=3  hl=2 l=   3 prim:    OBJECT            :organizationalUnitName
   39:d=3  hl=2 l=  22 prim:    PRINTABLESTRING   :Information Technology
   63:d=2  hl=2 l=  15 cons:   SEQUENCE          
   65:d=3  hl=2 l=   3 prim:    OBJECT            :organizationalUnitName
   70:d=3  hl=2 l=   8 prim:    PRINTABLESTRING   :Subgroup
   80:d=1  hl=2 l=  22 cons:  SET               
   82:d=2  hl=2 l=  20 cons:   SEQUENCE          
   84:d=3  hl=2 l=   3 prim:    OBJECT            :commonName
   89:d=3  hl=2 l=  13 prim:    PRINTABLESTRING   :Dacoda Strack

I am looking for a way to ask Vault to produce a certificate more like...

# while IFS='|' read NAME SUBJECT
> do
> 	mkdir -p build/$NAME
> 
> 	openssl req \
> 		-newkey rsa:2048 -keyout build/$NAME/$NAME.key -nodes \
> 		-new -multivalue-rdn \
> 		-out build/$NAME/$NAME.csr \
> 		-subj "$SUBJECT"
> done <<EOF
> multivalue-rdn|/CN=Dacoda Strack/OU=Subgroup+OU=Information Technology/O=Dacoda Strack LLC/
> ad-rdn|/CN=Dacoda Strack/OU=Subgroup/OU=Information Technology/O=Dacoda Strack LLC/
> EOF

# openssl asn1parse -i -strparse 11 -in build/ad-rdn/ad-rdn.csr
    0:d=0  hl=2 l= 104 cons: SEQUENCE          
    2:d=1  hl=2 l=  22 cons:  SET               
    4:d=2  hl=2 l=  20 cons:   SEQUENCE          
    6:d=3  hl=2 l=   3 prim:    OBJECT            :commonName
   11:d=3  hl=2 l=  13 prim:    UTF8STRING        :Dacoda Strack
   26:d=1  hl=2 l=  17 cons:  SET               
   28:d=2  hl=2 l=  15 cons:   SEQUENCE          
   30:d=3  hl=2 l=   3 prim:    OBJECT            :organizationalUnitName
   35:d=3  hl=2 l=   8 prim:    UTF8STRING        :Subgroup
   45:d=1  hl=2 l=  31 cons:  SET               
   47:d=2  hl=2 l=  29 cons:   SEQUENCE          
   49:d=3  hl=2 l=   3 prim:    OBJECT            :organizationalUnitName
   54:d=3  hl=2 l=  22 prim:    UTF8STRING        :Information Technology
   78:d=1  hl=2 l=  26 cons:  SET               
   80:d=2  hl=2 l=  24 cons:   SEQUENCE          
   82:d=3  hl=2 l=   3 prim:    OBJECT            :organizationName
   87:d=3  hl=2 l=  17 prim:    UTF8STRING        :Dacoda Strack LLC

Here are the base64 encoded DERs for the two:

Vault distinguished name with multi-valued RDNs

MGYxFjAUBgNVBAMMDURhY29kYSBTdHJhY2sxMDAPBgNVBAsMCFN1Ymdyb3VwMB0GA1UECwwWSW5mb3JtYXRpb24gVGVjaG5vbG9neTEaMBgGA1UECgwRRGFjb2RhIFN0cmFjayBMTEM=

Distinguished name with no multi-valued RDNs a la Active Directory and others

MGgxFjAUBgNVBAMMDURhY29kYSBTdHJhY2sxETAPBgNVBAsMCFN1Ymdyb3VwMR8wHQYDVQQLDBZJbmZvcm1hdGlvbiBUZWNobm9sb2d5MRowGAYDVQQKDBFEYWNvZGEgU3RyYWNrIExMQw==

For example,

# parse() {
> 	base64 -d | openssl asn1parse -i -inform DER
> }

# parse <<< 'MGYxFjAUBgNVBAMMDURhY29kYSBTdHJhY2sxMDAPBgNVBAsMCFN1Ymdyb3VwMB0GA1UECwwWSW5mb3JtYXRpb24gVGVjaG5vbG9neTEaMBgGA1UECgwRRGFjb2RhIFN0cmFjayBMTEM='

    0:d=0  hl=2 l= 102 cons: SEQUENCE          
    2:d=1  hl=2 l=  22 cons:  SET               
    4:d=2  hl=2 l=  20 cons:   SEQUENCE          
    6:d=3  hl=2 l=   3 prim:    OBJECT            :commonName
   11:d=3  hl=2 l=  13 prim:    UTF8STRING        :Dacoda Strack
   26:d=1  hl=2 l=  48 cons:  SET               
   28:d=2  hl=2 l=  15 cons:   SEQUENCE          
   30:d=3  hl=2 l=   3 prim:    OBJECT            :organizationalUnitName
   35:d=3  hl=2 l=   8 prim:    UTF8STRING        :Subgroup
   45:d=2  hl=2 l=  29 cons:   SEQUENCE          
   47:d=3  hl=2 l=   3 prim:    OBJECT            :organizationalUnitName
   52:d=3  hl=2 l=  22 prim:    UTF8STRING        :Information Technology
   76:d=1  hl=2 l=  26 cons:  SET               
   78:d=2  hl=2 l=  24 cons:   SEQUENCE          
   80:d=3  hl=2 l=   3 prim:    OBJECT            :organizationName
   85:d=3  hl=2 l=  17 prim:    UTF8STRING        :Dacoda Strack LLC

# parse <<< 'MGgxFjAUBgNVBAMMDURhY29kYSBTdHJhY2sxETAPBgNVBAsMCFN1Ymdyb3VwMR8wHQYDVQQLDBZJbmZvcm1hdGlvbiBUZWNobm9sb2d5MRowGAYDVQQKDBFEYWNvZGEgU3RyYWNrIExMQw=='

    0:d=0  hl=2 l= 104 cons: SEQUENCE          
    2:d=1  hl=2 l=  22 cons:  SET               
    4:d=2  hl=2 l=  20 cons:   SEQUENCE          
    6:d=3  hl=2 l=   3 prim:    OBJECT            :commonName
   11:d=3  hl=2 l=  13 prim:    UTF8STRING        :Dacoda Strack
   26:d=1  hl=2 l=  17 cons:  SET               
   28:d=2  hl=2 l=  15 cons:   SEQUENCE          
   30:d=3  hl=2 l=   3 prim:    OBJECT            :organizationalUnitName
   35:d=3  hl=2 l=   8 prim:    UTF8STRING        :Subgroup
   45:d=1  hl=2 l=  31 cons:  SET               
   47:d=2  hl=2 l=  29 cons:   SEQUENCE          
   49:d=3  hl=2 l=   3 prim:    OBJECT            :organizationalUnitName
   54:d=3  hl=2 l=  22 prim:    UTF8STRING        :Information Technology
   78:d=1  hl=2 l=  26 cons:  SET               
   80:d=2  hl=2 l=  24 cons:   SEQUENCE          
   82:d=3  hl=2 l=   3 prim:    OBJECT            :organizationName
   87:d=3  hl=2 l=  17 prim:    UTF8STRING        :Dacoda Strack LLC
@atoom
Copy link

atoom commented Nov 12, 2020

+1 on this feature request since we also have a need of a hierarchial structure with multiple OUs in our certificates. It would be nice if it would be possible to configure a role how it should handle RDNs that occur multiple times in the CSR subject.

A more detailed discussion from Golang perspective here: golang/go#40876

@cipherboy
Copy link
Contributor

Just to consolidate discussion, I'll close this one in favor of #12426. As documented there, rdn= seems to have the desired structure, it is just that validation becomes much harder. Previously we only needed validation attributes for the cn= component, as the others were specified by the operator on the role.

Now however, we need to be able to validate not only the contents of each type, but perhaps also the overall structure of the request.

If anyone has thoughts, I'd appreciate them on that tissue. :-)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants