domainComponent (DC) RDN not included in subject of signed certificate
- Dominant language
- Go
- Stars
- 9.5k
- Forks
- 1.2k
- PR merge metrics
- No merged PRs in 30d
Description
When cfssl receives a certifcate signing request (CSR) which contains one or multiple `domainComponent` (`DC`) relative distinguished names (RDNs) in the subject, then the subject of the signed certificate emitted by cfssl does not contain those `DC` RDNs.
Subject text representation of an example CSR:
```
$ openssl req -text -noout -verify -in client_cert.csr
verify OK
Certificate Request:
Data:
Version: 0 (0x0)
Subject: CN=readonly, DC=los-pollos, DC=io
[...]
```
Note the subject: `CN=readonly, DC=los-pollos, DC=io`
After sending this CSR to the cfssl `/sign` endpoint, this is the text representation of the cert emitted by cfssl (issuer hidden):
```
$ openssl x509 -in client.crt -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
32:77:f7:7b:9f:e9:f6:a8:24:51:44:66:14:30:3d:38:8d:7b:f4:96
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=**, ST=**, L=**, O=**, CN=**
Validity
Not Before: Jul 13 13:58:00 2016 GMT
Not After : Jul 11 13:58:00 2026 GMT
Subject: CN=readonly
[...]
```
Note how the subject DN was reduced to `CN=readonly`, missing the DC (domainComponent) RDNs.
Maybe this is a cfssl configuration issue, in which case I'd be happy to receive pointers. Otherwise, this violates [RFC 5280](http://www.ietf.org/rfc/rfc5280.txt) section 4.1.2.4. (page 20):
> As noted above, distinguished names are composed of attributes. This
> specification does not restrict the set of attribute types that may
> appear in names. However, conforming implementations MUST be
> prepared to receive certificates with issuer names containing the set
> of attribute types defined below. This specification RECOMMENDS
> support for additional attribute types.
> [...]
>
> Standard sets of attributes have been defined in the X.500 series of
> specifications [X.520]. Implementations of this specification MUST
> be prepared to receive the following standard attribute types in
> issuer and subject (Section 4.1.2.6) names:
> [...]
> **In addition, implementations of this specification MUST be prepared
> to receive the domainComponent attribute, as defined in [RFC4519].**
Note especially the emphasized text.
Below you find a self-contained MWE for reproducing.
MWE method:
- Generate CSR is using [Python's cryptography](https://cryptography.io/en/latest/) (w/ OpenSSL bindings).
- Submit CSR to a cfssl instance via [requests](http://docs.python-requests.org/en/master/), receive PEM-serialized signed cert.
- Deserialize cert using cryptography, and print all subject attributes.
MWE output:
```
Subject attributes:
, value='readonly')>
```
MWE code:
``` python
from cryptography import x509
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.x509.oid import NameOID
import requests
cryptbackend = default_backend()
# Create certificate sining request (CSR).
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
backend=cryptbackend
)
builder = x509.CertificateSigningRequestBuilder()
builder = builder.subject_name(x509.Name([
x509.NameAttribute(NameOID.COMMON_NAME, 'readonly'),
x509.NameAttribute(NameOID.DOMAIN_COMPONENT, 'los-pollos'),
x509.NameAttribute(NameOID.DOMAIN_COMPONENT, 'io')
]))
builder = builder.add_extension(
x509.BasicConstraints(ca=False, path_length=None),
critical=True,
).add_extension(
x509.KeyUsage(
digital_signature=True,
content_commitment=False,
key_encipherment=True,
data_encipherment=False,
key_agreement=False,
key_cert_sign=False,
crl_sign=False,
encipher_only=False,
decipher_only=False
),
critical=False
).add_extension(
x509.SubjectAlternativeName([x509.DNSName('los-pollos.io')]),
critical=False
).add_extension(
x509.SubjectKeyIdentifier.from_public_key(private_key.public_key()),
critical=False
)
csr = builder.sign(private_key, hashes.SHA256(), cryptbackend)
csr_pem = csr.public_bytes(encoding=serialization.Encoding.PEM).decode('ascii')
print("CSR:")
print(csr_pem)
# Send CSR to cfssl.
data = {
'certificate_request': csr_pem,
'profile': '',
'crl_override': '',
'label': ''
}
r = requests.post(
url='http://cfsslhost/ca/api/v2/sign',
headers={'Accept': 'application/json', 'Accept-Charset': 'utf-8'},
json=data
)
cert_pem = r.json()['result']['certificate'].strip() + '\n'
print("Cert:")
print(cert_pem)
cert = x509.load_pem_x509_certificate(
cert_pem.encode('ascii'), cryptbackend)
print("Subject attributes:")
for attr in cert.subject:
print(attr)
```
Contributor guide
Assessment
This issue has not been assessed yet.