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..6dfac077965 --- /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/Creating-Self-Signed-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