diff --git a/.github/workflows/est-ds-realm-separate-test.yml b/.github/workflows/est-ds-realm-separate-test.yml new file mode 100644 index 00000000000..5a704f48eca --- /dev/null +++ b/.github/workflows/est-ds-realm-separate-test.yml @@ -0,0 +1,243 @@ +name: EST with ds realm on separate instance + +on: workflow_call + +env: + DB_IMAGE: ${{ vars.DB_IMAGE || 'quay.io/389ds/dirsrv' }} + +jobs: + # docs/installation/ca/Installing_CA.md + test: + name: Test + runs-on: ubuntu-latest + env: + SHARED: /tmp/workdir/pki + steps: + - name: Clone repository + uses: actions/checkout@v4 + + - name: Retrieve PKI images + uses: actions/cache@v4 + 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 CA DS container + run: | + tests/bin/ds-create.sh \ + --image=${{ env.DB_IMAGE }} \ + --hostname=cads.example.com \ + --password=Secret.123 \ + --network=example \ + --network-alias=cads.example.com \ + cads + + - name: Set up CA container + run: | + tests/bin/runner-init.sh \ + --hostname=ca.example.com \ + --network=example \ + --network-alias=ca.example.com \ + ca + + - name: Install CA + run: | + docker exec ca pkispawn \ + -f /usr/share/pki/server/examples/installation/ca.cfg \ + -s CA \ + -D pki_ds_url=ldap://cads.example.com:3389 \ + -v + + - name: Initialize PKI client + run: | + docker exec ca pki-server cert-export ca_signing --cert-file $SHARED/ca_signing.crt + + docker exec ca pki nss-cert-import \ + --cert $SHARED/ca_signing.crt \ + --trust CT,C,C \ + ca_signing + + docker exec ca pki pkcs12-import \ + --pkcs12 /root/.dogtag/pki-tomcat/ca_admin_cert.p12 \ + --pkcs12-password Secret.123 + + docker exec ca pki info + + - name: Create EST server certificates in p12 + run: | + docker exec ca pki nss-cert-request --csr estSSLServer.csr \ + --ext /usr/share/pki/server/certs/sslserver.conf --subject 'CN=est.example.com' + + docker exec ca pki ca-cert-request-submit --csr-file estSSLServer.csr --profile caServerCert | tee output + REQUEST_ID=$(sed -n "s/^\s*Request ID:\s*\(\S*\)$/\1/p" output) + + docker exec ca pki -n caadmin ca-cert-request-approve $REQUEST_ID --force | tee output + CERT_ID=$(sed -n "s/^\s*Certificate ID:\s*\(\S*\)$/\1/p" output) + + docker exec ca pki -n caadmin ca-cert-export --output-file estSSLServer.crt $CERT_ID + docker exec ca pki nss-cert-import --cert estSSLServer.crt sslserver + + docker exec ca pk12util -d /root/.dogtag/nssdb -o $SHARED/est_server.p12 -n sslserver -W Secret.123 + + - name: Add CA EST user + run: | + docker exec ca pki -n caadmin ca-group-add "EST RA Agents" + docker exec ca pki -n caadmin ca-user-add \ + est-ra-1 --fullName "EST RA 1" --password Secret.est + docker exec ca pki -n caadmin ca-group-member-add "EST RA Agents" est-ra-1 + + - name: Configure CA est profile + run: | + docker exec ca pki -n caadmin ca-profile-add \ + --raw /usr/share/pki/ca/profiles/ca/estServiceCert.cfg + docker exec ca pki -n caadmin ca-profile-enable estServiceCert + docker exec ca pki-server restart --wait + + - name: Set up EST DS container + run: | + tests/bin/ds-create.sh \ + --image=${{ env.DB_IMAGE }} \ + --hostname=estds.example.com \ + --password=Secret.123 \ + --network=example \ + --network-alias=estds.example.com \ + estds + + - name: Create EST users + run: | + docker exec -i estds ldapadd -x -H ldap://estds.example.com:3389 \ + -D "cn=Directory Manager" -w Secret.123 << EOF + dn: dc=est,dc=pki,dc=example,dc=com + objectClass: domain + dc: est + + dn: ou=people,dc=est,dc=pki,dc=example,dc=com + ou: people + objectClass: top + objectClass: organizationalUnit + + dn: ou=groups,dc=est,dc=pki,dc=example,dc=com + ou: groups + objectClass: top + objectClass: organizationalUnit + + dn: uid=est-test-user,ou=people,dc=est,dc=pki,dc=example,dc=com + objectClass: top + objectClass: person + objectClass: organizationalPerson + objectClass: inetOrgPerson + uid: est-test-user + sn: EST TEST USER + cn: EST TEST USER + userPassword: Secret.123 + + dn: cn=estclient,ou=groups,dc=est,dc=pki,dc=example,dc=com + objectClass: top + objectClass: groupOfUniqueNames + cn: estclient + uniqueMember: uid=est-test-user,ou=People,dc=est,dc=pki,dc=example,dc=com + EOF + + - name: Set up EST container + run: | + tests/bin/runner-init.sh \ + --hostname=est.example.com \ + --network=example \ + --network-alias=est.example.com \ + est + + - name: Install EST + run: | + docker exec est pkispawn \ + -f /usr/share/pki/server/examples/installation/est.cfg \ + -s EST \ + -D est_realm_url=ldap://estds.example.com:3389 \ + -D pki_ca_uri=https://ca.example.com:8443 \ + -D pki_server_pkcs12_path=$SHARED/est_server.p12 \ + -D pki_server_pkcs12_password=Secret.123 \ + -v + - name: Test CA certs + run: | + docker exec est curl -o cacert.p7 -k https://est.example.com:8443/.well-known/est/cacerts + + docker exec est openssl base64 -d --in cacert.p7 --out cacert.p7.der + docker exec est openssl pkcs7 --in cacert.p7.der -inform DER -print_certs -out cacert.pem + docker exec est openssl x509 -in cacert.pem -text -noout | tee actual + docker exec est openssl x509 -in $SHARED/ca_signing.crt -text -noout | tee expected + diff expected actual + + - name: Install est client + run: | + docker exec est dnf copr enable -y @pki/libest + docker exec est dnf install -y libest + + - name: Enroll certificate + run: | + docker exec -e EST_OPENSSL_CACERT=cacert.pem est estclient -e -s est.example.com -p 8443 \ + --common-name test.example.com -o . -u est-test-user -h Secret.123 + + docker exec est openssl base64 -d --in cert-0-0.pkcs7 --out cert-0-0.pkcs7.der + docker exec est openssl pkcs7 -in cert-0-0.pkcs7.der -inform DER -print_certs -out cert.pem + docker exec est openssl x509 -in cert.pem -subject -noout | tee actual + echo "subject=CN=test.example.com" > expected + diff expected actual + + - name: Remove EST + run: | + docker exec est pki-server est-undeploy --wait + docker exec est pki-server est-remove + + - name: Remove CA + run: docker exec ca pkidestroy -i pki-tomcat -s CA -v + + - name: Check CA DS server systemd journal + if: always() + run: | + docker exec cads journalctl -x --no-pager -u dirsrv@localhost.service + + - name: Check CA DS container logs + if: always() + run: | + docker logs cads + + - name: Check CA PKI server systemd journal + if: always() + run: | + docker exec ca journalctl -x --no-pager -u pki-tomcatd@pki-tomcat.service + + - name: Check EST PKI server systemd journal + if: always() + run: | + docker exec est journalctl -x --no-pager -u pki-tomcatd@pki-tomcat.service + + - name: Check CA debug log + if: always() + run: | + docker exec ca find /var/lib/pki/pki-tomcat/logs/ca -name "debug.*" -exec cat {} \; + + - name: Check EST debug log + if: always() + run: | + docker exec est find /var/lib/pki/pki-tomcat/logs/est -name "debug.*" -exec cat {} \; + + - name: Gather artifacts + if: always() + run: | + tests/bin/ds-artifacts-save.sh cads + tests/bin/ds-artifacts-save.sh estds + tests/bin/pki-artifacts-save.sh ca + tests/bin/pki-artifacts-save.sh est + continue-on-error: true + + - name: Upload artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: est-ds-separate + path: /tmp/artifacts diff --git a/.github/workflows/est-tests.yml b/.github/workflows/est-tests.yml index 4d052e56ad9..142067972c3 100644 --- a/.github/workflows/est-tests.yml +++ b/.github/workflows/est-tests.yml @@ -46,3 +46,8 @@ jobs: name: EST with ds realm needs: build uses: ./.github/workflows/est-ds-realm-test.yml + + est-ds-realm-separate-test: + name: EST with ds realm on a separate instance + needs: build + uses: ./.github/workflows/est-ds-realm-separate-test.yml diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg index d16f63d2754..b6631111a17 100644 --- a/base/server/etc/default.cfg +++ b/base/server/etc/default.cfg @@ -669,7 +669,7 @@ pki_registry_enable=False [EST] pki_ds_setup=False pki_security_domain_setup=False -pki_registry_enable=False +pki_registry_enable=True pki_ca_uri=https://%(pki_hostname)s:%(pki_https_port)s est_ca_profile=estServiceCert est_ca_user_name= diff --git a/base/server/python/pki/server/deployment/__init__.py b/base/server/python/pki/server/deployment/__init__.py index 80a1e5f230b..9ef3c2af5fc 100644 --- a/base/server/python/pki/server/deployment/__init__.py +++ b/base/server/python/pki/server/deployment/__init__.py @@ -5385,6 +5385,10 @@ def create_est_subsystem(self): subsystem = pki.server.subsystem.ESTSubsystem(self.instance) subsystem.create() + subsystem.create_conf(exist_ok=True) + subsystem.create_registry(exist_ok=True) + subsystem.create_logs(exist_ok=True) + subsystem.add_est_config(exist_ok=True, force=True) return subsystem def configure_est_backend(self, subsystem): @@ -5486,7 +5490,6 @@ def deploy_est_webapp(self, subsystem): if len(self.instance.get_subsystems()) == 1: # if this is the first subsystem, deploy the subsystem without waiting subsystem.enable() - self.instance.start() else: # otherwise, deploy the subsystem and wait until it starts subsystem.enable( @@ -5528,12 +5531,11 @@ def spawn(self): if self.subsystem_type == 'EST': self.spawn_est() - return - - scriptlet = pki.server.deployment.scriptlets.subsystem_layout.PkiScriptlet() - scriptlet.deployer = self - scriptlet.instance = self.instance - scriptlet.spawn(self) + else: + scriptlet = pki.server.deployment.scriptlets.subsystem_layout.PkiScriptlet() + scriptlet.deployer = self + scriptlet.instance = self.instance + scriptlet.spawn(self) scriptlet = pki.server.deployment.scriptlets.security_databases.PkiScriptlet() scriptlet.deployer = self @@ -5555,10 +5557,11 @@ def spawn(self): scriptlet.instance = self.instance scriptlet.spawn(self) - scriptlet = pki.server.deployment.scriptlets.configuration.PkiScriptlet() - scriptlet.deployer = self - scriptlet.instance = self.instance - scriptlet.spawn(self) + if self.subsystem_type != 'EST': + scriptlet = pki.server.deployment.scriptlets.configuration.PkiScriptlet() + scriptlet.deployer = self + scriptlet.instance = self.instance + scriptlet.spawn(self) scriptlet = pki.server.deployment.scriptlets.finalization.PkiScriptlet() scriptlet.deployer = self diff --git a/base/server/python/pki/server/subsystem.py b/base/server/python/pki/server/subsystem.py index 3908f93becd..f57c7e1d28a 100644 --- a/base/server/python/pki/server/subsystem.py +++ b/base/server/python/pki/server/subsystem.py @@ -2874,9 +2874,10 @@ def authorizer_conf(self): def realm_conf(self): return os.path.join(self.conf_dir, 'realm.conf') - def create(self, exist_ok=False, force=False): + def create(self, exist_ok=False): + self.instance.makedirs(self.base_dir, exist_ok=exist_ok) - self.instance.makedirs(self.conf_dir, exist_ok=exist_ok) + def add_est_config(self, exist_ok=False, force=False): default_conf_dir = os.path.join(pki.server.PKIServer.SHARE_DIR, 'est', 'conf') @@ -2966,6 +2967,47 @@ def replace_realm_config(self, realm_path): exist_ok=False, force=True) + def is_ready(self, secure_connection=True, timeout=None): + """ + Wait for EST subsystem to become ready to serve requests. + Since EST do not implement yet status API the check is done agaist the web app + + :param startup_timeout: Total timeout. Unsuccessful status requests will + be retried until this timeout is exceeded. Default: None. + :param request_timeout: Connect/receive timeout for each individual + status request. Default: None. + """ + + server_config = self.instance.get_server_config() + + if secure_connection: + protocol = 'https' + port = server_config.get_secure_port() + + else: + protocol = 'http' + port = server_config.get_unsecure_port() + + # When waiting for a connection to come alive, don't bother verifying + # the certificate at this stage. + connection = pki.client.PKIConnection( + protocol=protocol, + hostname=socket.getfqdn(), + port=port, + accept='application/json', + trust_env=False, + verify=False) + + response = connection.get( + '/est/', + timeout=timeout + ) + if response.status_code == 200: + logger.info('Subsystem status: running') + else: + logger.info('Subsystem status: error') + return response.status_code == 200 + class PKISubsystemFactory(object):