Skip to content

Commit

Permalink
Add test for CA clone with replicated DS
Browse files Browse the repository at this point in the history
A new test has been added to test installing CA with DS,
cloning the DS, then cloning the CA using the existing
DS clone.

This process allows DS cloning to happen separately from
CA cloning which could prevent pkispawn from timing out
due to long DS cloning process with large database.

https://github.com/dogtagpki/pki/wiki/Installing-CA-Clone-with-Replicated-DS
  • Loading branch information
edewata committed Aug 10, 2023
1 parent 1c07ef8 commit 3723b0c
Show file tree
Hide file tree
Showing 2 changed files with 398 additions and 0 deletions.
391 changes: 391 additions & 0 deletions .github/workflows/ca-clone-replicated-ds-test.yml
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit 3723b0c

Please sign in to comment.