Bug 1878808 - [RFE] dsconf instance security ca-certificate add: Cannot load a certificate bundle
Summary: [RFE] dsconf instance security ca-certificate add: Cannot load a certificate ...
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Red Hat Directory Server
Classification: Red Hat
Component: 389-ds-base
Version: 12.1
Hardware: Unspecified
OS: Unspecified
high
medium
Target Milestone: DS12.1
: dirsrv-12.2
Assignee: mreynolds
QA Contact: LDAP QA Team
Evgenia Martynyuk
URL:
Whiteboard:
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2020-09-14 14:44 UTC by Graham Leggett
Modified: 2023-05-31 10:25 UTC (History)
10 users (show)

Fixed In Version: redhat-ds-12-9020020221130212339.1674d57
Doc Type: Enhancement
Doc Text:
.Directory Server can now import a certificate bundle Previously, when you tried to add a certificate bundle by using the `dsconf` or `dsctl` utility, the procedure failed with an error, and the certificate bundle was not imported. Such behavior was caused by the `certutil` utility that could import only one certificate at a time. With this update, Directory Server works around the issue with the `certutil`, and a certificate bundle is added successfully.
Clone Of:
Environment:
Last Closed: 2023-05-30 09:40:35 UTC
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)
check_cert.py (942 bytes, text/plain)
2023-02-10 13:26 UTC, Viktor Ashirov
no flags Details


Links
System ID Private Priority Status Summary Last Updated
Red Hat Product Errata RHBA-2023:3344 0 None None None 2023-05-30 09:40:50 UTC

Description Graham Leggett 2020-09-14 14:44:39 UTC
#### Issue Description

Attempt to load a certificate bundle into 389ds using dsconf fails, as dsconf only appears to handle single certificates at a time.

Because virtually no systems work with individual certs, this renders dsconf useless for importing CA certs.

certutil from NSS appears to have the same bug: https://bugzilla.mozilla.org/show_bug.cgi?id=1664816

#### Package Version and Platform

RHEL8 latest.


#### Steps to reproduce

1.  [root@gatekeeper gatekeeper]# dsconf gatekeeper security ca-certificate add --file /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
2.
3.

#### Actual results

usage: dsconf instance security ca-certificate add [-h] --file FILE --name
                                                   NAME
dsconf instance security ca-certificate add: error: the following arguments are required: --name

Failure - no certs are installed.

#### Expected results

All certificates in the bundle installed.

Comment 1 mreynolds 2020-09-14 14:52:12 UTC
"dsconf security" is just a wrapper for certutil. So if certutl can not do it, then dsconf definitely can not either.  There are also certificate tasks using dsctl, does that exhibit the same behavior?  Probably but would be good to know:

    #  dsctl localhost tls import-server-cert ...

Comment 2 Graham Leggett 2020-09-14 14:56:49 UTC
No luck:

[root@gatekeeper ~]# dsctl gatekeeper tls import-ca /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem
usage: dsctl [instance] tls import-ca [-h] cert_path nickname
dsctl [instance] tls import-ca: error: the following arguments are required: nickname

Adding a nickname means only one cert is imported, all others are ignored:

[root@gatekeeper ~]# dsctl gatekeeper tls import-ca /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem test
[root@gatekeeper ~]# dsctl gatekeeper tls list-ca
test

Comment 3 Graham Leggett 2020-09-14 17:13:17 UTC
Looks like the missing piece of dsctl and dsconf is to parse each certificate in the incoming file one at a time, and then pass each certificate to NSS.

Another option is to fix this is certutil - remove the restriction that only one certificate can be imported at a time.

Comment 4 mreynolds 2020-09-14 18:36:12 UTC
(In reply to Graham Leggett from comment #3)
> Looks like the missing piece of dsctl and dsconf is to parse each
> certificate in the incoming file one at a time, and then pass each
> certificate to NSS.
> 
> Another option is to fix this is certutil - remove the restriction that only
> one certificate can be imported at a time.

Yeah that should be doable.  Changing bug to RFE, and adding acks...

Comment 7 mreynolds 2022-02-11 03:04:29 UTC
related upstream ticket:  https://github.com/389ds/389-ds-base/issues/5162

Comment 10 mreynolds 2022-11-15 16:31:05 UTC
Fixed CLI tools to allow CA certificate PEM file bundles.

Comment 11 Viktor Ashirov 2023-02-10 11:50:11 UTC
Automated test passed:
========================================== test session starts ===========================================
platform linux -- Python 3.9.16, pytest-6.2.2, py-1.10.0, pluggy-0.13.1 -- /usr/bin/python3
cachedir: .pytest_cache
389-ds-base: 2.2.6-1.module+el9dsrv+17949+63c5b04e
nss: 3.79.0-14.el9_0
nspr: 4.34.0-14.el9_0
openldap: 2.6.2-3.el9
cyrus-sasl: not installed
FIPS: disabled
rootdir: /root/ds/dirsrvtests, configfile: pytest.ini
collected 1 item

dirsrvtests/tests/suites/clu/ca_cert_bundle_test.py::test_ca_cert_bundle PASSED                    [100%]

=========================================== 1 passed in 38.20s ===========================================


Basic functionality works (loading a CA bundle is successful), but I found minor issues:

[1] Importing the same bundle under a different name is reported as successful, but the certificates are not actually imported:
# dsconf standalone1 security ca-certificate add --file bundle.pem --name CA1 CA2
Successfully added CA certificate (CA1)
Successfully added CA certificate (CA2)

# certutil -d /etc/dirsrv/slapd-standalone1/ -L

Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI

CA1                                                          CT,,
CA2                                                          CT,,

# dsconf standalone1 security ca-certificate add --file bundle.pem --name CA1 CA2
Error: Certificate already exists with the same name (CA1)

# dsconf standalone1 security ca-certificate add --file bundle.pem --name CA3 CA4
Successfully added CA certificate (CA3)
Successfully added CA certificate (CA4)

# certutil -d /etc/dirsrv/slapd-standalone1/ -L

Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI

CA1                                                          CT,,
CA2                                                          CT,,

This issue comes from certutil, that doesn't report a non-zero exit code if the certificate is already in the database.

# /usr/bin/certutil -A -d /etc/dirsrv/slapd-standalone1 -n CA999 -t CT,, -i bundle.pem-1 -a -f /etc/dirsrv/slapd-standalone1/pwdfile.txt
# echo $?
0

We should check if the certificate with the given name was imported. And if it's missing from the list of nicknames in the database and certutil's exit code was 0, print a better message.

[2] dsconf doesn't cleanup temporary files from the current working directory:
# ls -1 bundle*
bundle.pem
bundle.pem-0
bundle.pem-1

[3] dsconf doesn't check if the imported certificate is actually a CA certificate. 
If a bundle contains a server certificate, it is also imported with CT,, trust flags.
We can check for key usage (cert sign) and basic constraints (CA) in the cert, and import it as CA only if the check is successful.

I think [1] and [2] should be fixed, and [3] is up for debate, because it might introduce additional dependency (python-cryptography) that won't be useful in 99% cases.

Moving to ASSIGNED.

Comment 12 mreynolds 2023-02-10 13:13:41 UTC
As for [3] not sure how to tell if a cert is "server" or "ca" cert.  I always thought it was just how you assign the trust flags that differentiated between the two (but I could definitely be wrong).  The tooling assumes the user knows how they want to use the cert (server vs CA).

Comment 13 Viktor Ashirov 2023-02-10 13:26:04 UTC
Created attachment 1943332 [details]
check_cert.py

It can be done something like this using python-cryptography.

Comment 14 Pierre Rogier 2023-02-10 14:28:24 UTC
If we do not want to add new dependency, we can also check for the "Usages: Certificate Signing" in certutil -d ... -n certName output
But before taking a decision we have to double check (I am not sure that the certificate extensions are mandatory (especially when the "verify cert" flag is disabled.)
Maybe we should rather open a warning window and asking the user if we should proceed or not

Comment 20 Viktor Ashirov 2023-04-24 08:20:20 UTC
Automated test passed:
============================================================= test session starts =============================================================
platform linux -- Python 3.9.16, pytest-6.2.2, py-1.10.0, pluggy-0.13.1 -- /usr/bin/python3
cachedir: .pytest_cache
389-ds-base: 2.2.7-1.module+el9dsrv+18376+e226feec
nss: 3.79.0-18.el9_1
nspr: 4.34.0-18.el9_1
openldap: 2.6.2-3.el9
cyrus-sasl: not installed
FIPS: disabled
rootdir: /root/ds/dirsrvtests, configfile: pytest.ini
collected 1 item

dirsrvtests/tests/suites/clu/ca_cert_bundle_test.py::test_ca_cert_bundle PASSED                                                         [100%]

============================================================= 1 passed in 16.64s =============================================================

Additional test cases from https://bugzilla.redhat.com/show_bug.cgi?id=1878808#c11

[1] Importing the same bundle under a different name is reported as successful, but the certificates are not actually imported:
[root@localhost ds]# certutil -d /etc/dirsrv/slapd-standalone1/ -L

Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI

CA_CERT_1                                                    CT,,
CA_CERT_2                                                    CT,,
[root@localhost ds]# dsconf standalone1 security ca-certificate add --file /tmp/ca-bundle.pem --name CA3 CA4
Successfully added CA certificate (CA3)
Successfully added CA certificate (CA4)
[root@localhost ds]# certutil -d /etc/dirsrv/slapd-standalone1/ -L

Certificate Nickname                                         Trust Attributes
                                                             SSL,S/MIME,JAR/XPI

CA_CERT_1                                                    CT,,
CA_CERT_2                                                    CT,,

[2] Fixed - temporary files are not present anymore.
[3] Fixed - Non-CA certificates are not imported:
# dsconf standalone1 security ca-certificate add --file Server-Cert.crt --name Server
Error: Certificate (Server) is not a CA certificate

Since [1] is not fixed, moving to ASSIGNED.

Comment 21 mreynolds 2023-04-25 13:59:33 UTC
> [1] Importing the same bundle under a different name is reported as successful, but the certificates are not actually imported:
> [root@localhost ds]# certutil -d /etc/dirsrv/slapd-standalone1/ -L

I think this is an issue with certutil, where if the certificate(s) itself are the same as what's in NSS db it treats it as a no-op (idempotent sort of).  Only if the certs in the bundle are different than what's in the NSS db will it perform the op.  This might require a lot of hoops to jump through to try and work around certutil's behavior...

Comment 22 Viktor Ashirov 2023-05-09 08:57:52 UTC
I'm facing another issue with CA certificates.
I have a self-signed certificate generated by openssl:
openssl req -x509 -sha256 -nodes -days 365  -newkey rsa:2048 -out my.crt -keyout my.key

I'm trying to import it, but it fails with an error message:
# dsconf localhost security ca-certificate add --name=myca --file=my.crt
Error: No <ObjectIdentifier(oid=2.5.29.15, name=keyUsage)> extension was found

My CA cert doesn't have key usage specified, but has a basic constraint to be used as a CA cert.
Turns out some of the CA certs from the system CA bundle also don't have key usage specified, and they fail to be imported.

Maybe we shouldn't be that strict or provide a "force" option to import the CA cert anyway.

Comment 23 Evgenia Martynyuk 2023-05-17 15:12:26 UTC
RN texted prepared in the DocText field. Moving to SME review

Comment 24 Evgenia Martynyuk 2023-05-17 15:43:49 UTC
RN text was reviewed by Viktor, moving to a peer review

Comment 25 Evgenia Martynyuk 2023-05-18 12:51:25 UTC
RN text was reviewed by a peer and release pending. Thanks, Masha!

Comment 26 Viktor Ashirov 2023-05-19 07:47:52 UTC
Build tested:
389-ds-base-2.2.7-3.module+el9dsrv+18864+4949f8c5.x86_64

Issue in https://bugzilla.redhat.com/show_bug.cgi?id=1878808#c22 was addressed:
# openssl req -x509 -sha256 -nodes -days 365  -newkey rsa:2048 -out my.crt -keyout my.key
# dsconf localhost security ca-certificate add --name=myca --file=my.crt
Successfully added CA certificate (myca)

# certutil -d /etc/dirsrv/slapd-localhost/ -L  | grep myca
myca                                                         CT,,

Marking as VERIFIED.

Comment 28 errata-xmlrpc 2023-05-30 09:40:35 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (redhat-ds:12 bug fix and enhancement update), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2023:3344


Note You need to log in before you can comment on or make changes to this bug.