From bef91027b50ed4c718286e8208def1ca751bc8d0 Mon Sep 17 00:00:00 2001 From: "Endi S. Dewata" Date: Wed, 16 Aug 2023 10:27:35 -0500 Subject: [PATCH] Add test for subordinate CA clone A new test has been added to install a subordinate CA with external cert then clone it into another instance. The test will also compare the CS.cfg, the users, and the certs in these instances to ensure that they are (mostly) identical. The .gitignore has been updated to ignore files generated by other branches. --- .github/workflows/ca-tests.yml | 5 + .github/workflows/subca-clone-test.yml | 406 +++++++++++++++++++++++++ .gitignore | 1 + 3 files changed, 412 insertions(+) create mode 100644 .github/workflows/subca-clone-test.yml diff --git a/.github/workflows/ca-tests.yml b/.github/workflows/ca-tests.yml index aa63e1627c7..70b2621dc7b 100644 --- a/.github/workflows/ca-tests.yml +++ b/.github/workflows/ca-tests.yml @@ -1156,6 +1156,11 @@ jobs: path: | /tmp/artifacts/secondary + subca-clone-test: + name: Sub-CA clone + needs: [init, build] + uses: ./.github/workflows/subca-clone-test.yml + scep-test: name: Testing SCEP responder needs: [init, build] diff --git a/.github/workflows/subca-clone-test.yml b/.github/workflows/subca-clone-test.yml new file mode 100644 index 00000000000..44c05b1122f --- /dev/null +++ b/.github/workflows/subca-clone-test.yml @@ -0,0 +1,406 @@ +name: Sub-CA clone + +on: + workflow_call: + +jobs: + test: + name: Test + runs-on: ubuntu-latest + env: + PKIDIR: /tmp/workdir/pki + steps: + - name: Clone repository + uses: actions/checkout@v3 + + - name: Retrieve pki-runner image + uses: actions/cache@v3 + with: + key: pki-runner-${{ github.sha }} + path: pki-runner.tar + + - name: Load runner image + run: docker load --input pki-runner.tar + + - name: Create network + run: docker network create example + + - name: Set up root CA container + run: | + tests/bin/runner-init.sh + env: + IMAGE: pki-runner + NAME: root-ca + HOSTNAME: root-ca.example.com + + - name: Connect root CA container to network + run: docker network connect example root-ca --alias root-ca.example.com + + - name: Create root CA in NSS database + run: | + # https://github.com/dogtagpki/pki/wiki/Creating-Self-Signed-CA-Signing-Certificate-with-PKI-NSS + + docker exec root-ca pki nss-cert-request \ + --subject "CN=Root CA Signing Certificate" \ + --ext /usr/share/pki/server/certs/ca_signing.conf \ + --csr $PKIDIR/root-ca_signing.csr + docker exec root-ca pki nss-cert-issue \ + --csr $PKIDIR/root-ca_signing.csr \ + --ext /usr/share/pki/server/certs/ca_signing.conf \ + --cert $PKIDIR/root-ca_signing.crt + docker exec root-ca pki nss-cert-import \ + --cert $PKIDIR/root-ca_signing.crt \ + --trust CT,C,C \ + root-ca_signing + + - name: Set up primary DS container + run: | + tests/bin/runner-init.sh + env: + IMAGE: pki-runner + NAME: primary-ds + HOSTNAME: primary-ds.example.com + + - name: Connect primary DS container to network + run: docker network connect example primary-ds --alias primary-ds.example.com + + - name: Install DS package + run: docker exec primary-ds dnf install -y 389-ds-base + + - name: Install primary DS instance + run: docker exec primary-ds $PKIDIR/tests/bin/ds-create.sh + + - name: Set up primary sub-CA container + run: | + tests/bin/runner-init.sh + env: + IMAGE: pki-runner + NAME: primary-subca + HOSTNAME: primary-subca.example.com + + - name: Connect primary sub-CA container to network + run: docker network connect example primary-subca --alias primary-subca.example.com + + - name: Install primary sub-CA (step 1) + run: | + # docs/installation/ca/Installing_CA_with_External_CA_Signing_Certificate.md + + # customize installation config file + docker exec primary-subca sed \ + -e "s,^\(pki_ca_signing_csr_path\)=.*$,\1=$PKIDIR/subca_signing.csr," \ + -e "$ a pki_ds_hostname=primary-ds.example.com" \ + -e "$ a pki_client_admin_cert_p12=$PKIDIR/caadmin.p12" \ + /usr/share/pki/server/examples/installation/ca-external-cert-step1.cfg \ + | tee ca-external-cert-step1.cfg + + docker exec primary-subca pkispawn \ + -f $PKIDIR/ca-external-cert-step1.cfg \ + -s CA \ + -v + + - name: Issue primary sub-CA signing cert + run: | + # https://github.com/dogtagpki/pki/wiki/Issuing-CA-Signing-Certificate-with-PKI-NSS + + cat > subca_signing.conf << EOF + basicConstraints = critical, CA:TRUE + subjectKeyIdentifier = hash + authorityKeyIdentifier = keyid:always + keyUsage = critical, digitalSignature, nonRepudiation, keyCertSign, cRLSign + EOF + + docker exec root-ca pki nss-cert-issue \ + --issuer root-ca_signing \ + --csr $PKIDIR/subca_signing.csr \ + --ext $PKIDIR/subca_signing.conf \ + --cert $PKIDIR/subca_signing.crt + + - name: Install primary sub-CA (step 2) + run: | + # docs/installation/ca/Installing_CA_with_External_CA_Signing_Certificate.md + + # customize installation config file + docker exec primary-subca sed \ + -e "s,^\(pki_cert_chain_path\)=.*$,\1=$PKIDIR/root-ca_signing.crt," \ + -e "s,^\(pki_ca_signing_csr_path\)=.*$,\1=$PKIDIR/subca_signing.csr," \ + -e "s,^\(pki_ca_signing_cert_path\)=.*$,\1=$PKIDIR/subca_signing.crt," \ + -e "$ a pki_ds_hostname=primary-ds.example.com" \ + -e "$ a pki_client_admin_cert_p12=$PKIDIR/caadmin.p12" \ + /usr/share/pki/server/examples/installation/ca-external-cert-step2.cfg \ + | tee ca-external-cert-step2.cfg + + docker exec primary-subca pkispawn \ + -f $PKIDIR/ca-external-cert-step2.cfg \ + -s CA \ + -v + + docker exec primary-subca pki-server cert-find + + - name: Run PKI healthcheck + run: docker exec primary-subca pki-healthcheck --failures-only + + - name: Check primary sub-CA admin + run: | + # https://github.com/dogtagpki/pki/wiki/Importing-Admin-Certificate-into-PKI-CLI + + docker exec primary-subca pki client-cert-import \ + --ca-cert $PKIDIR/root-ca_signing.crt \ + root-ca_signing + docker exec primary-subca pki client-cert-import \ + --pkcs12 $PKIDIR/caadmin.p12 \ + --pkcs12-password Secret.123 + docker exec primary-subca pki -n caadmin ca-user-show caadmin + + - name: Export primary sub-CA certs + run: | + docker exec primary-subca pki-server ca-clone-prepare \ + --pkcs12-file $PKIDIR/subca-certs.p12 \ + --pkcs12-password Secret.123 + + - name: Set up secondary DS container + run: | + tests/bin/runner-init.sh + env: + IMAGE: pki-runner + NAME: secondary-ds + HOSTNAME: secondary-ds.example.com + + - name: Connect secondary DS container to network + run: docker network connect example secondary-ds --alias secondary-ds.example.com + + - name: Install DS package + run: docker exec secondary-ds dnf install -y 389-ds-base + + - name: Install secondary DS instance + run: docker exec secondary-ds $PKIDIR/tests/bin/ds-create.sh + + - name: Set up secondary sub-CA container + run: | + tests/bin/runner-init.sh + env: + IMAGE: pki-runner + NAME: secondary-subca + HOSTNAME: secondary-subca.example.com + + - name: Connect secondary sub-CA container to network + run: docker network connect example secondary-subca --alias secondary-subca.example.com + + - name: Install secondary sub-CA + run: | + # get CS.cfg from primary sub-CA before cloning + docker cp primary-subca:/etc/pki/pki-tomcat/ca/CS.cfg CS.cfg.primary + + # docs/installation/ca/Installing_CA_Clone.md + + # customize installation config file + docker exec primary-subca sed \ + -e "s,^\(pki_cert_chain_path\)=.*$,\1=$PKIDIR/root-ca_signing.crt," \ + -e "s,^\(pki_security_domain_hostname\)=.*$,\1=primary-subca.example.com," \ + -e "s,^\(pki_clone_uri\)=.*$,\1=https://primary-subca.example.com:8443," \ + -e "s,^\(pki_clone_pkcs12_path\)=.*$,\1=$PKIDIR/subca-certs.p12," \ + -e "s,^\(pki_clone_pkcs12_password\)=.*$,\1=Secret.123," \ + -e "$ a pki_ds_hostname=secondary-ds.example.com" \ + /usr/share/pki/server/examples/installation/ca-clone.cfg \ + | tee ca-clone.cfg + + docker exec secondary-subca pkispawn \ + -f $PKIDIR/ca-clone.cfg \ + -s CA \ + -v + + docker exec secondary-subca pki-server cert-find + + - name: Check CS.cfg in primary sub-CA after cloning + run: | + # get CS.cfg from primary sub-CA after cloning + docker cp primary-subca:/etc/pki/pki-tomcat/ca/CS.cfg CS.cfg.primary.after + + # normalize expected result: + # - remove params that cannot be compared + # - set dbs.enableSerialManagement to true (automatically enabled when cloned) + sed -e '/^dbs.beginRequestNumber=/d' \ + -e '/^dbs.endRequestNumber=/d' \ + -e '/^dbs.beginSerialNumber=/d' \ + -e '/^dbs.endSerialNumber=/d' \ + -e '/^dbs.beginReplicaNumber=/d' \ + -e '/^dbs.endReplicaNumber=/d' \ + -e '/^dbs.nextBeginReplicaNumber=/d' \ + -e '/^dbs.nextEndReplicaNumber=/d' \ + -e 's/^\(dbs.enableSerialManagement\)=.*$/\1=true/' \ + CS.cfg.primary \ + | sort > expected + + # normalize actual result: + # - remove params that cannot be compared + # - remove params added by bugs (fixed in PKI 11.5) + sed -e '/^dbs.beginRequestNumber=/d' \ + -e '/^dbs.endRequestNumber=/d' \ + -e '/^dbs.beginSerialNumber=/d' \ + -e '/^dbs.endSerialNumber=/d' \ + -e '/^dbs.beginReplicaNumber=/d' \ + -e '/^dbs.endReplicaNumber=/d' \ + -e '/^dbs.nextBeginReplicaNumber=/d' \ + -e '/^dbs.nextEndReplicaNumber=/d' \ + -e '/^auths.instance.flatFileAuth.authAttributes=/d' \ + -e '/^auths.instance.flatFileAuth.deferOnFailure=/d' \ + -e '/^auths.instance.flatFileAuth.keyAttributes=/d' \ + -e '/^ca.ocsp_signing.newNickname=/d' \ + -e '/^ca.signing.newNickname=/d' \ + CS.cfg.primary.after \ + | sort > actual + + diff expected actual + + - name: Check CS.cfg in secondary sub-CA + run: | + # get CS.cfg from secondary sub-CA + docker cp secondary-subca:/etc/pki/pki-tomcat/ca/CS.cfg CS.cfg.secondary + + # normalize expected result: + # - remove params that cannot be compared + # - replace primary-subca.example.com with secondary-subca.example.com + # - replace primary-ds.example.com with secondary-ds.example.com + # - set ca.crl.MasterCRL.enableCRLCache to false (automatically disabled in the clone) + # - set ca.crl.MasterCRL.enableCRLUpdates to false (automatically disabled in the clone) + # - add params for the clone + # - remove params added by bugs (fixed in PKI 11.5) + # - remove params no longer used in PKI 11.5 + sed -e '/^installDate=/d' \ + -e '/^dbs.beginRequestNumber=/d' \ + -e '/^dbs.endRequestNumber=/d' \ + -e '/^dbs.beginSerialNumber=/d' \ + -e '/^dbs.endSerialNumber=/d' \ + -e '/^dbs.beginReplicaNumber=/d' \ + -e '/^dbs.endReplicaNumber=/d' \ + -e '/^dbs.nextBeginRequestNumber=/d' \ + -e '/^dbs.nextEndRequestNumber=/d' \ + -e '/^dbs.nextBeginSerialNumber=/d' \ + -e '/^dbs.nextEndSerialNumber=/d' \ + -e '/^dbs.nextBeginReplicaNumber=/d' \ + -e '/^dbs.nextEndReplicaNumber=/d' \ + -e '/^ca.sslserver.cert=/d' \ + -e '/^ca.sslserver.certreq=/d' \ + -e 's/primary-subca.example.com/secondary-subca.example.com/' \ + -e 's/primary-ds.example.com/secondary-ds.example.com/' \ + -e 's/^\(ca.crl.MasterCRL.enableCRLCache\)=.*$/\1=false/' \ + -e 's/^\(ca.crl.MasterCRL.enableCRLUpdates\)=.*$/\1=false/' \ + -e '$ a ca.certStatusUpdateInterval=0' \ + -e '$ a ca.listenToCloneModifications=false' \ + -e '$ a master.ca.agent.host=primary-subca.example.com' \ + -e '$ a master.ca.agent.port=8443' \ + -e '/^auths.instance.flatFileAuth.authAttributes=/d' \ + -e '/^auths.instance.flatFileAuth.deferOnFailure=/d' \ + -e '/^auths.instance.flatFileAuth.keyAttributes=/d' \ + -e '/^ca.sslserver.defaultSigningAlgorithm=/d' \ + -e '/^hierarchy.select=/d' \ + -e '/^subsystem.select=/d' \ + CS.cfg.primary.after \ + | sort > expected + + # normalize actual result: + # - remove params that cannot be compared + # - normalize ca.sslserver.tokenname (fixed in PKI 11.5) + # - remove params no longer used in PKI 11.5 + sed -e '/^installDate=/d' \ + -e '/^dbs.beginRequestNumber=/d' \ + -e '/^dbs.endRequestNumber=/d' \ + -e '/^dbs.beginSerialNumber=/d' \ + -e '/^dbs.endSerialNumber=/d' \ + -e '/^dbs.beginReplicaNumber=/d' \ + -e '/^dbs.endReplicaNumber=/d' \ + -e '/^dbs.nextBeginRequestNumber=/d' \ + -e '/^dbs.nextEndRequestNumber=/d' \ + -e '/^dbs.nextBeginSerialNumber=/d' \ + -e '/^dbs.nextEndSerialNumber=/d' \ + -e '/^dbs.nextBeginReplicaNumber=/d' \ + -e '/^dbs.nextEndReplicaNumber=/d' \ + -e '/^ca.sslserver.cert=/d' \ + -e '/^ca.sslserver.certreq=/d' \ + -e 's/^\(ca.sslserver.tokenname\)=.*$/\1=internal/' \ + -e '/^hierarchy.select=/d' \ + -e '/^subsystem.select=/d' \ + CS.cfg.secondary \ + | sort > actual + + diff expected actual + + - name: Run PKI healthcheck + run: docker exec secondary-subca pki-healthcheck --failures-only + + - name: Check secondary sub-CA admin + run: | + # https://github.com/dogtagpki/pki/wiki/Importing-Admin-Certificate-into-PKI-CLI + + docker exec secondary-subca pki client-cert-import \ + --ca-cert $PKIDIR/root-ca_signing.crt \ + root-ca_signing + docker exec secondary-subca pki client-cert-import \ + --pkcs12 $PKIDIR/caadmin.p12 \ + --pkcs12-password Secret.123 + docker exec secondary-subca pki -n caadmin ca-user-show caadmin + + - name: Check users in primary sub-CA and secondary sub-CA + run: | + docker exec primary-subca pki -n caadmin ca-user-find | tee subca-users.primary + docker exec secondary-subca pki -n caadmin ca-user-find > subca-users.secondary + + diff subca-users.primary subca-users.secondary + + - name: Check certs in primary sub-CA and secondary sub-CA + run: | + docker exec primary-subca pki ca-cert-find | tee subca-certs.primary + docker exec secondary-subca pki ca-cert-find > subca-certs.secondary + + diff subca-certs.primary subca-certs.secondary + + - name: Gather artifacts from primary sub-CA containers + if: always() + run: | + tests/bin/ds-artifacts-save.sh primary-ds + tests/bin/pki-artifacts-save.sh primary-subca + continue-on-error: true + + - name: Gather artifacts from secondary sub-CA containers + if: always() + run: | + tests/bin/ds-artifacts-save.sh secondary-ds + tests/bin/pki-artifacts-save.sh secondary-subca + continue-on-error: true + + - name: Remove secondary sub-CA + run: docker exec secondary-subca pkidestroy -i pki-tomcat -s CA -v + + - name: Remove primary sub-CA + run: docker exec primary-subca pkidestroy -i pki-tomcat -s CA -v + + - name: Upload artifacts from primary DS + if: always() + uses: actions/upload-artifact@v3 + with: + name: subca-clone-primary-ds + path: | + /tmp/artifacts/primary-ds + + - name: Upload artifacts from primary sub-CA + if: always() + uses: actions/upload-artifact@v3 + with: + name: subca-clone-primary-subca + path: | + /tmp/artifacts/primary-subca + + - name: Upload artifacts from secondary DS + if: always() + uses: actions/upload-artifact@v3 + with: + name: subca-clone-secondary-ds + path: | + /tmp/artifacts/secondary-ds + + - name: Upload artifacts from secondary sub-CA + if: always() + uses: actions/upload-artifact@v3 + with: + name: subca-clone-secondary-subca + path: | + /tmp/artifacts/secondary-subca diff --git a/.gitignore b/.gitignore index f210651f03a..08c3caede3e 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ tests/artifacts/ tests/tests.retry base/util/test/PKICertImport/dbs target/ +.flattened-pom.xml