diff --git a/.github/workflows/ca-clone-replicated-ds-test.yml b/.github/workflows/ca-clone-replicated-ds-test.yml new file mode 100644 index 00000000000..84fde901dcd --- /dev/null +++ b/.github/workflows/ca-clone-replicated-ds-test.yml @@ -0,0 +1,391 @@ +name: CA clone with replicated DS +# https://github.com/dogtagpki/pki/wiki/Installing-CA-Clone-with-Replicated-DS + +on: + workflow_call: + inputs: + db-image: + required: false + type: string + +jobs: + test: + name: Test + runs-on: ubuntu-latest + env: + SHARED: /tmp/workdir/pki + steps: + - name: Clone repository + uses: actions/checkout@v3 + + - name: Retrieve PKI images + uses: actions/cache@v3 + with: + key: pki-images-${{ github.sha }} + path: pki-images.tar + + - name: Load PKI images + run: docker load --input pki-images.tar + + - name: Create network + run: docker network create example + + - name: Set up primary DS container + run: | + tests/bin/ds-container-create.sh primaryds + env: + IMAGE: ${{ inputs.db-image }} + HOSTNAME: primaryds.example.com + PASSWORD: Secret.123 + + - name: Connect primary DS container to network + run: docker network connect example primaryds --alias primaryds.example.com + + - name: Set up primary PKI container + run: | + tests/bin/runner-init.sh primary + env: + HOSTNAME: primary.example.com + + - name: Connect primary PKI container to network + run: docker network connect example primary --alias primary.example.com + + # https://github.com/dogtagpki/pki/blob/master/docs/installation/ca/Installing_CA.md + - name: Install primary CA + run: | + docker exec primary pkispawn \ + -f /usr/share/pki/server/examples/installation/ca.cfg \ + -s CA \ + -D pki_ds_url=ldap://primaryds.example.com:3389 \ + -D pki_cert_id_generator=random \ + -D pki_request_id_generator=random \ + -D pki_client_admin_cert_p12=$SHARED/caadmin.p12 \ + -v + + - name: Check primary CA admin user + run: | + docker exec primary pki-server cert-export ca_signing \ + --cert-file $SHARED/ca_signing.crt + docker exec primary pki client-cert-import ca_signing \ + --ca-cert $SHARED/ca_signing.crt + docker exec primary pki pkcs12-import \ + --pkcs12 $SHARED/caadmin.p12 \ + --pkcs12-password Secret.123 + docker exec primary pki -n caadmin ca-user-show caadmin + + - name: Set up secondary DS container + run: | + tests/bin/ds-container-create.sh secondaryds + env: + IMAGE: ${{ inputs.db-image }} + HOSTNAME: secondaryds.example.com + PASSWORD: Secret.123 + + - name: Connect secondary DS container to network + run: docker network connect example secondaryds --alias secondaryds.example.com + + # https://github.com/dogtagpki/389-ds-base/wiki/Configuring-DS-Replication-with-DS-Tools + - name: Preparing DS backend + run: | + # check backends in primary DS + docker exec primaryds dsconf \ + -D "cn=Directory Manager" \ + -w Secret.123 \ + ldap://primaryds.example.com:3389 \ + backend suffix list + + # create backend for CA in secondary DS + docker exec secondaryds dsconf \ + -D "cn=Directory Manager" \ + -w Secret.123 \ + ldap://secondaryds.example.com:3389 \ + backend create \ + --suffix=dc=ca,dc=pki,dc=example,dc=com \ + --be-name=ca + + - name: Enable replication on primary DS + run: | + docker exec primaryds dsconf \ + -D "cn=Directory Manager" \ + -w Secret.123 \ + ldap://primaryds.example.com:3389 \ + replication enable \ + --suffix=dc=ca,dc=pki,dc=example,dc=com \ + --role=supplier \ + --replica-id=1 \ + --bind-dn="cn=Replication Manager,cn=config" \ + --bind-passwd=Secret.123 + + - name: Enable replication on secondary DS + run: | + docker exec secondaryds dsconf \ + -D "cn=Directory Manager" \ + -w Secret.123 \ + ldap://secondaryds.example.com:3389 \ + replication enable \ + --suffix=dc=ca,dc=pki,dc=example,dc=com \ + --role=supplier \ + --replica-id=2 \ + --bind-dn="cn=Replication Manager,cn=config" \ + --bind-passwd=Secret.123 + + - name: Create replication manager on primary DS + run: | + docker exec primaryds dsconf \ + -D "cn=Directory Manager" \ + -w Secret.123 \ + ldap://primaryds.example.com:3389 \ + repl-agmt create \ + --suffix=dc=ca,dc=pki,dc=example,dc=com \ + --host=secondaryds.example.com \ + --port=3389 \ + --conn-protocol=LDAP \ + --bind-dn="cn=Replication Manager,cn=config" \ + --bind-passwd=Secret.123 \ + --bind-method=SIMPLE \ + primaryds-to-secondaryds + + - name: Create replication manager on secondary DS + run: | + docker exec secondaryds dsconf \ + -D "cn=Directory Manager" \ + -w Secret.123 \ + ldap://secondaryds.example.com:3389 \ + repl-agmt create \ + --suffix=dc=ca,dc=pki,dc=example,dc=com \ + --host=primaryds.example.com \ + --port=3389 \ + --conn-protocol=LDAP \ + --bind-dn="cn=Replication Manager,cn=config" \ + --bind-passwd=Secret.123 \ + --bind-method=SIMPLE \ + secondaryds-to-primaryds + + - name: Initializing replication agreement + run: | + # start initialization + docker exec primaryds dsconf \ + -D "cn=Directory Manager" \ + -w Secret.123 \ + ldap://primaryds.example.com:3389 \ + repl-agmt init \ + --suffix=dc=ca,dc=pki,dc=example,dc=com \ + primaryds-to-secondaryds + + # wait for initialization to complete + counter=0 + while [[ "$counter" -lt 30 ]]; do + sleep 1 + + docker exec primaryds dsconf \ + -D "cn=Directory Manager" \ + -w Secret.123 \ + ldap://primaryds.example.com:3389 \ + repl-agmt init-status \ + --suffix=dc=ca,dc=pki,dc=example,dc=com \ + primaryds-to-secondaryds \ + > >(tee stdout) 2> >(tee stderr >&2) || true + + STDOUT=$(cat stdout) + if [ "$STDOUT" = "Agreement successfully initialized." ]; then + break + fi + + counter=$((counter+1)) + done + + - name: Check entries in primary DS and secondary DS + run: | + # get DNs from primary DS + docker exec primaryds ldapsearch \ + -H ldap://primaryds.example.com:3389 \ + -x \ + -D "cn=Directory Manager" \ + -w Secret.123 \ + -b "dc=ca,dc=pki,dc=example,dc=com" \ + -o ldif_wrap=no \ + -LLL \ + dn \ + | sed -ne 's/^dn: \(.*\)$/\1/p' | sort | tee primaryds.dn + + # get DNs from secondary DS + docker exec secondaryds ldapsearch \ + -H ldap://secondaryds.example.com:3389 \ + -x \ + -D "cn=Directory Manager" \ + -w Secret.123 \ + -b "dc=ca,dc=pki,dc=example,dc=com" \ + -o ldif_wrap=no \ + -LLL \ + dn \ + | sed -ne 's/^dn: \(.*\)$/\1/p' | sort > secondaryds.dn + + diff primaryds.dn secondaryds.dn + + - name: Export certs and keys from primary CA + run: | + docker exec primary pki-server ca-clone-prepare \ + --pkcs12-file $SHARED/ca-certs.p12 \ + --pkcs12-password Secret.123 + + docker exec primary pki-server cert-export ca_signing \ + --cert-file $SHARED/ca_signing.crt + + - name: Set up secondary PKI container + run: | + tests/bin/runner-init.sh secondary + env: + HOSTNAME: secondary.example.com + + - name: Connect secondary PKI container to network + run: docker network connect example secondary --alias secondary.example.com + + # https://github.com/dogtagpki/pki/wiki/Installing-CA-Clone-with-Existing-DS + - name: Install secondary CA + run: | + # get CS.cfg from primary CA before cloning + docker cp primary:/etc/pki/pki-tomcat/ca/CS.cfg CS.cfg.primary + + docker exec secondary pkispawn \ + -f /usr/share/pki/server/examples/installation/ca-clone.cfg \ + -s CA \ + -D pki_cert_chain_path=$SHARED/ca_signing.crt \ + -D pki_clone_pkcs12_path=$SHARED/ca-certs.p12 \ + -D pki_clone_pkcs12_password=Secret.123 \ + -D pki_ds_url=ldap://secondaryds.example.com:3389 \ + -D pki_ds_setup=False \ + -D pki_cert_id_generator=random \ + -D pki_request_id_generator=random \ + -v + + - name: Check system certs in primary CA and secondary CA + run: | + # get system certs from primary CA (except sslserver) + docker exec primary pki-server cert-show ca_signing > system-certs.primary + echo >> system-certs.primary + docker exec primary pki-server cert-show ca_ocsp_signing >> system-certs.primary + echo >> system-certs.primary + docker exec primary pki-server cert-show ca_audit_signing >> system-certs.primary + echo >> system-certs.primary + docker exec primary pki-server cert-show subsystem >> system-certs.primary + + # get system certs from secondary CA (except sslserver) + docker exec secondary pki-server cert-show ca_signing > system-certs.secondary + echo >> system-certs.secondary + docker exec secondary pki-server cert-show ca_ocsp_signing >> system-certs.secondary + echo >> system-certs.secondary + docker exec secondary pki-server cert-show ca_audit_signing >> system-certs.secondary + echo >> system-certs.secondary + docker exec secondary pki-server cert-show subsystem >> system-certs.secondary + + cat system-certs.primary + diff system-certs.primary system-certs.secondary + + - name: Check CS.cfg in primary CA after cloning + run: | + # get CS.cfg from primary CA after cloning + docker cp primary:/etc/pki/pki-tomcat/ca/CS.cfg CS.cfg.primary.after + + diff CS.cfg.primary CS.cfg.primary.after + + - name: Check CS.cfg in secondary CA + run: | + # get CS.cfg from secondary CA + docker cp secondary:/etc/pki/pki-tomcat/ca/CS.cfg CS.cfg.secondary + + # normalize expected result: + # - remove params that cannot be compared + # - replace primary.example.com with secondary.example.com + # - replace primaryds.example.com with secondaryds.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 + sed -e '/^installDate=/d' \ + -e '/^ca.sslserver.cert=/d' \ + -e '/^ca.sslserver.certreq=/d' \ + -e 's/primary.example.com/secondary.example.com/' \ + -e 's/primaryds.example.com/secondaryds.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.example.com' \ + -e '$ a master.ca.agent.port=8443' \ + CS.cfg.primary.after \ + | sort > expected + + # normalize actual result: + # - remove params that cannot be compared + sed -e '/^installDate=/d' \ + -e '/^ca.sslserver.cert=/d' \ + -e '/^ca.sslserver.certreq=/d' \ + CS.cfg.secondary \ + | sort > actual + + diff expected actual + + - name: Check secondary CA admin user + run: | + docker exec secondary pki client-cert-import ca_signing \ + --ca-cert $SHARED/ca_signing.crt + docker exec secondary pki pkcs12-import \ + --pkcs12 $SHARED/caadmin.p12 \ + --pkcs12-password Secret.123 + docker exec secondary pki -n caadmin ca-user-show caadmin + + - name: Check users in primary CA and secondary CA + run: | + docker exec primary pki -n caadmin ca-user-find | tee ca-users.primary + docker exec secondary pki -n caadmin ca-user-find > ca-users.secondary + + diff ca-users.primary ca-users.secondary + + - name: Check certs in primary CA and secondary CA + run: | + docker exec primary pki ca-cert-find | tee ca-certs.primary + docker exec secondary pki ca-cert-find > ca-certs.secondary + + diff ca-certs.primary ca-certs.secondary + + - name: Check security domain in primary CA and secondary CA + run: | + docker exec primary pki securitydomain-show | tee sd.primary + docker exec secondary pki securitydomain-show > sd.secondary + + diff sd.primary sd.secondary + + - name: Gather artifacts from primary containers + if: always() + run: | + tests/bin/ds-artifacts-save.sh --output=/tmp/artifacts/primary primaryds + tests/bin/pki-artifacts-save.sh primary + continue-on-error: true + + - name: Gather artifacts from secondary containers + if: always() + run: | + tests/bin/ds-artifacts-save.sh --output=/tmp/artifacts/secondary secondaryds + tests/bin/pki-artifacts-save.sh secondary + continue-on-error: true + + - name: Remove CA from secondary PKI container + run: docker exec secondary pkidestroy -i pki-tomcat -s CA -v + + - name: Remove CA from primary PKI container + run: docker exec primary pkidestroy -i pki-tomcat -s CA -v + + - name: Upload artifacts from primary containers + if: always() + uses: actions/upload-artifact@v3 + with: + name: ca-clone-replicated-ds-primary + path: | + /tmp/artifacts/primary + + - name: Upload artifacts from secondary containers + if: always() + uses: actions/upload-artifact@v3 + with: + name: ca-clone-replicated-ds-secondary + path: | + /tmp/artifacts/secondary diff --git a/.github/workflows/ca-clone-tests.yml b/.github/workflows/ca-clone-tests.yml index 3879b8b49f7..79f0b4ef14f 100644 --- a/.github/workflows/ca-clone-tests.yml +++ b/.github/workflows/ca-clone-tests.yml @@ -41,3 +41,10 @@ jobs: uses: ./.github/workflows/ca-clone-shared-ds-test.yml with: db-image: ${{ needs.init.outputs.db-image }} + + ca-clone-replicated-ds-test: + name: CA clone with replicated DS + needs: [init, build] + uses: ./.github/workflows/ca-clone-replicated-ds-test.yml + with: + db-image: ${{ needs.init.outputs.db-image }}