diff --git a/.github/workflows/est-ds-realm-test.yml b/.github/workflows/est-ds-realm-test.yml new file mode 100644 index 00000000000..de577f54f98 --- /dev/null +++ b/.github/workflows/est-ds-realm-test.yml @@ -0,0 +1,233 @@ +name: EST with ds realm + +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 DS container + run: | + tests/bin/ds-create.sh \ + --image=${{ env.DB_IMAGE }} \ + --hostname=ds.example.com \ + --password=Secret.123 \ + --network=example \ + --network-alias=ds.example.com \ + ds + + - name: Set up PKI container + run: | + tests/bin/runner-init.sh \ + --hostname=pki.example.com \ + --network=example \ + --network-alias=ca.example.com \ + pki + + - name: Install CA + run: | + docker exec pki pkispawn \ + -f /usr/share/pki/server/examples/installation/ca.cfg \ + -s CA \ + -D pki_ds_url=ldap://ds.example.com:3389 \ + -v + + - name: Initialize PKI client + run: | + docker exec pki pki-server cert-export ca_signing --cert-file ca_signing.crt + + docker exec pki pki nss-cert-import \ + --cert ca_signing.crt \ + --trust CT,C,C \ + ca_signing + + docker exec pki pki pkcs12-import \ + --pkcs12 /root/.dogtag/pki-tomcat/ca_admin_cert.p12 \ + --pkcs12-password Secret.123 + + docker exec pki pki info + + - name: Add CA EST user + run: | + docker exec pki pki -n caadmin ca-group-add "EST RA Agents" + docker exec pki pki -n caadmin ca-user-add \ + est-ra-1 --fullName "EST RA 1" --password Secret.est + docker exec pki pki -n caadmin ca-group-member-add "EST RA Agents" est-ra-1 + + - name: Configure CA est profile + run: | + docker exec pki pki -n caadmin ca-profile-add \ + --raw /usr/share/pki/ca/profiles/ca/estServiceCert.cfg + docker exec pki pki -n caadmin ca-profile-enable estServiceCert + docker exec pki pki-server restart --wait + + - name: Install EST + run: | + docker exec pki pkispawn \ + -f /usr/share/pki/server/examples/installation/est.cfg \ + -s EST \ + -D est_realm_url=ldap://ds.example.com:3389 \ + -v + + - name: Check EST backend config + if: always() + run: | + docker exec pki cat /etc/pki/pki-tomcat/est/backend.conf + + - name: Check EST authorizer config + if: always() + run: | + docker exec pki cat /etc/pki/pki-tomcat/est/authorizer.conf + + - name: Check EST realm config + if: always() + run: | + docker exec pki cat /etc/pki/pki-tomcat/est/realm.conf + + - name: Check webapps + run: | + docker exec pki pki-server webapp-find | tee output + + # CA instance should have ROOT, ca, and pki webapps + echo "ROOT" > expected + echo "ca" >> expected + echo "est" >> expected + echo "pki" >> expected + sed -n 's/^ *Webapp ID: *\(.*\)$/\1/p' output > actual + diff expected actual + + docker exec pki pki-server webapp-show ROOT + docker exec pki pki-server webapp-show ca + docker exec pki pki-server webapp-show est + docker exec pki pki-server webapp-show pki + + - name: Create EST users + run: | + docker exec -i pki ldapadd -x -H ldap://ds.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 + objectClass: cmsuser + uid: est-test-user + sn: EST TEST USER + cn: EST TEST USER + usertype: undefined + 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: Test CA certs + run: | + docker exec pki curl -o cacert.p7 -k https://pki.example.com:8443/.well-known/est/cacerts + docker exec pki openssl base64 -d --in cacert.p7 --out cacert.p7.der + docker exec pki openssl pkcs7 --in cacert.p7.der -inform DER -print_certs -out cacert.pem + docker exec pki openssl x509 -in cacert.pem -text -noout | tee actual + docker exec pki openssl x509 -in ca_signing.crt -text -noout | tee expected + diff expected actual + + - name: Install est client + run: | + docker exec pki dnf copr enable -y @pki/libest + docker exec pki dnf install -y libest + + - name: Enroll certificate + run: | + docker exec -e EST_OPENSSL_CACERT=cacert.pem pki estclient -e -s pki.example.com -p 8443 \ + --common-name test.example.com -o . -u est-test-user -h Secret.123 + + docker exec pki openssl base64 -d --in cert-0-0.pkcs7 --out cert-0-0.pkcs7.der + docker exec pki openssl pkcs7 -in cert-0-0.pkcs7.der -inform DER -print_certs -out cert.pem + docker exec pki 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 pki pki-server est-undeploy --wait + docker exec pki pki-server est-remove + + - name: Remove CA + run: docker exec pki pkidestroy -i pki-tomcat -s CA -v + + - name: Check DS server systemd journal + if: always() + run: | + docker exec ds journalctl -x --no-pager -u dirsrv@localhost.service + + - name: Check DS container logs + if: always() + run: | + docker logs ds + + - name: Check PKI server systemd journal + if: always() + run: | + docker exec pki journalctl -x --no-pager -u pki-tomcatd@pki-tomcat.service + + - name: Check CA debug log + if: always() + run: | + docker exec pki find /var/lib/pki/pki-tomcat/logs/ca -name "debug.*" -exec cat {} \; + + - name: Check EST debug log + if: always() + run: | + docker exec pki find /var/lib/pki/pki-tomcat/logs/est -name "debug.*" -exec cat {} \; + + - name: Gather artifacts + if: always() + run: | + tests/bin/ds-artifacts-save.sh ds + tests/bin/pki-artifacts-save.sh pki + continue-on-error: true + + - name: Upload artifacts + if: always() + uses: actions/upload-artifact@v4 + with: + name: est-ds-basic + path: /tmp/artifacts diff --git a/.github/workflows/est-tests.yml b/.github/workflows/est-tests.yml index 0f195a24a61..4d052e56ad9 100644 --- a/.github/workflows/est-tests.yml +++ b/.github/workflows/est-tests.yml @@ -40,3 +40,9 @@ jobs: ansible-playbook -e 'pki_subsystem="est"' tests/ansible/pki-playbook.yml env: ANSIBLE_CONFIG: ${{ github.workspace }}/tests/ansible/ansible.cfg + + + est-ds-realm-test: + name: EST with ds realm + needs: build + uses: ./.github/workflows/est-ds-realm-test.yml diff --git a/base/est/CMakeLists.txt b/base/est/CMakeLists.txt index 4cace31f0d2..1a100ce71fd 100644 --- a/base/est/CMakeLists.txt +++ b/base/est/CMakeLists.txt @@ -96,3 +96,23 @@ install( DESTINATION ${DATA_INSTALL_DIR}/est/webapps/est/WEB-INF/lib ) + +install( + DIRECTORY + shared/ + DESTINATION + ${SHARE_INSTALL_PREFIX}/${APPLICATION_NAME}/${PROJECT_NAME}/conf/ + PATTERN + "CMakeLists.txt" EXCLUDE +) + +install( + FILES + bin/estauthz + DESTINATION + ${SHARE_INSTALL_PREFIX}/${APPLICATION_NAME}/${PROJECT_NAME}/bin/ + PERMISSIONS + OWNER_EXECUTE OWNER_WRITE OWNER_READ + GROUP_EXECUTE GROUP_READ + WORLD_EXECUTE WORLD_READ +) diff --git a/base/est/bin/estauthz b/base/est/bin/estauthz new file mode 100755 index 00000000000..3fce98cfa1c --- /dev/null +++ b/base/est/bin/estauthz @@ -0,0 +1,7 @@ +#!/usr/bin/python3 +import json, sys +ALLOWED_ROLE = 'estclient' +obj = json.loads(sys.stdin.read()) +if not ALLOWED_ROLE in obj['authzData']['principal']['roles']: + print(f'Principal does not have required role {ALLOWED_ROLE!r}') + sys.exit(1) diff --git a/base/est/conf/realm.conf b/base/est/conf/realm.conf deleted file mode 100644 index ccfb9d62813..00000000000 --- a/base/est/conf/realm.conf +++ /dev/null @@ -1 +0,0 @@ -class=org.apache.catalina.realm.MemoryRealm diff --git a/base/est/shared/authorizer.conf b/base/est/shared/authorizer.conf new file mode 100644 index 00000000000..702baf67bd8 --- /dev/null +++ b/base/est/shared/authorizer.conf @@ -0,0 +1,2 @@ +class=org.dogtagpki.est.ExternalProcessRequestAuthorizer +executable=/usr/share/pki/est/bin/estauthz diff --git a/base/est/shared/backend.conf b/base/est/shared/backend.conf new file mode 100644 index 00000000000..83eeeaa7f64 --- /dev/null +++ b/base/est/shared/backend.conf @@ -0,0 +1,5 @@ +class=org.dogtagpki.est.DogtagRABackend +url=https://fedora:8443 +profile=estServiceCert +username=est-ra-1 +password=est4ever diff --git a/base/est/shared/realm/ds.conf b/base/est/shared/realm/ds.conf new file mode 100644 index 00000000000..150bebfa934 --- /dev/null +++ b/base/est/shared/realm/ds.conf @@ -0,0 +1,7 @@ +class=com.netscape.cms.realm.PKILDAPRealm +url=ldap://localhost.localdomain:389 +authType=BasicAuth +bindDN=cn=Directory Manager +bindPassword=Secret.123 +usersDN=ou=people,dc=est,dc=pki,dc=example,dc=com +groupsDN=ou=groups,dc=est,dc=pki,dc=example,dc=com \ No newline at end of file diff --git a/base/est/shared/realm/in-memory.conf b/base/est/shared/realm/in-memory.conf new file mode 100644 index 00000000000..6182f91923d --- /dev/null +++ b/base/est/shared/realm/in-memory.conf @@ -0,0 +1,4 @@ +class=com.netscape.cms.realm.PKIInMemoryRealm +username=admin +password=Secret.123 +roles=estclient \ No newline at end of file diff --git a/base/est/shared/realm/postgresql.conf b/base/est/shared/realm/postgresql.conf new file mode 100644 index 00000000000..8be846d45a5 --- /dev/null +++ b/base/est/shared/realm/postgresql.conf @@ -0,0 +1,5 @@ +class=com.netscape.cms.realm.PKIPostgreSQLRealm +url=jdbc:postgresql://localhost.localdomain:5432/est +user=est +password=Secret.123 +statements=/usr/share/pki/est/conf/realm/statements.conf \ No newline at end of file diff --git a/base/est/shared/realm/statements.conf b/base/est/shared/realm/statements.conf new file mode 100644 index 00000000000..f8cc8132942 --- /dev/null +++ b/base/est/shared/realm/statements.conf @@ -0,0 +1,31 @@ +getUserByID=\ +SELECT \ + "id", "full_name", "password" \ +FROM \ + "users" \ +WHERE \ + "id" = ? + +getUserByCertID=\ +SELECT \ + u."id", u."full_name", u."password" \ +FROM \ + "users" u, "user_certs" uc \ +WHERE \ + u."id" = uc."user_id" AND uc."cert_id" = ? + +getUserCerts=\ +SELECT \ + "data" \ +FROM \ + "user_certs" \ +WHERE \ + "user_id" = ? + +getUserRoles=\ +SELECT \ + "group_id" \ +FROM \ + "group_members" \ +WHERE \ + "user_id" = ? \ No newline at end of file diff --git a/base/est/webapps/est/index.jsp b/base/est/webapps/est/index.jsp new file mode 100644 index 00000000000..79dca917a14 --- /dev/null +++ b/base/est/webapps/est/index.jsp @@ -0,0 +1,25 @@ + + + + Enrollment over Secure Transport + + + + + diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg index 642fb019f19..d16f63d2754 100644 --- a/base/server/etc/default.cfg +++ b/base/server/etc/default.cfg @@ -38,6 +38,9 @@ sensitive_parameters= acme_issuer_password acme_realm_bind_password acme_realm_password + est_realm_bind_password + est_realm_password + est_ca_password pki_instance_name=pki-tomcat pki_http_port=8080 @@ -663,3 +666,27 @@ pki_registry_enable=False # - acme_realm_groups_dn # # See /usr/share/pki/acme/realm//realm.conf +[EST] +pki_ds_setup=False +pki_security_domain_setup=False +pki_registry_enable=False +pki_ca_uri=https://%(pki_hostname)s:%(pki_https_port)s +est_ca_profile=estServiceCert +est_ca_user_name= +est_ca_user_password= +est_ca_user_password_file= +est_ca_user_certificate= +est_realm_type= +est_realm_custom= +est_realm_url= +est_realm_auth_type=BasicAuth +est_realm_bind_dn=cn=Directory Manager +est_realm_bind_password= +est_realm_nickname= +est_realm_user= +est_realm_username= +est_realm_password= +est_realm_users_dn=ou=people,dc=est,dc=pki,dc=example,dc=com +est_realm_groups_dn=ou=groups,dc=est,dc=pki,dc=example,dc=com +est_realm_statements=/usr/share/pki/est/conf/realm/statements.conf +est_authorizer_exec_path=/usr/share/pki/est/bin/estauthz diff --git a/base/server/examples/installation/est.cfg b/base/server/examples/installation/est.cfg new file mode 100644 index 00000000000..3a64da4694e --- /dev/null +++ b/base/server/examples/installation/est.cfg @@ -0,0 +1,9 @@ +[DEFAULT] +pki_server_database_password=Secret.123 + +[EST] +est_realm_type=ds +est_realm_url=ldap://localhost.localdomain:3389 +est_realm_bind_password=Secret.123 +est_ca_user_name=est-ra-1 +est_ca_user_password=Secret.est diff --git a/base/server/python/pki/server/deployment/__init__.py b/base/server/python/pki/server/deployment/__init__.py index 84e189915c8..80a1e5f230b 100644 --- a/base/server/python/pki/server/deployment/__init__.py +++ b/base/server/python/pki/server/deployment/__init__.py @@ -5357,7 +5357,7 @@ def deploy_acme_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( @@ -5376,15 +5376,135 @@ def spawn_acme(self): self.deploy_acme_webapp(subsystem) + def create_est_subsystem(self): + ''' + See also pki-server est-create. + ''' + + logger.info('Creating EST subsystem') + + subsystem = pki.server.subsystem.ESTSubsystem(self.instance) + subsystem.create() + return subsystem + + def configure_est_backend(self, subsystem): + logger.info('Configuring EST backend') + props = subsystem.get_backend_config(True) + ca_uri = self.mdict.get('pki_ca_uri') + pki.util.set_property(props, 'url', ca_uri) + + profile = self.mdict.get('est_ca_profile') + pki.util.set_property(props, 'profile', profile) + + username = self.mdict.get('est_ca_user_name') + pki.util.set_property(props, 'username', username) + + password = self.mdict.get('est_ca_user_password') + pki.util.set_property(props, 'password', password) + + password_file = self.mdict.get('est_ca_user_password_file') + pki.util.set_property(props, 'passwordFile', password_file) + + nickname = self.mdict.get('est_ca_user_certificate') + pki.util.set_property(props, 'nickname', nickname) + subsystem.update_backend_config(props) + + def configure_est_authorizer(self, subsystem): + + logger.info('Configuring EST authorizer') + props = subsystem.get_authorizer_config(True) + + authorizer_exec = self.mdict.get('est_authorizer_exec_path') + pki.util.set_property(props, 'executable', authorizer_exec) + subsystem.update_authorizer_config(props) + + def configure_est_realm(self, subsystem): + logger.info('Configuring EST realm') + + if self.mdict['est_realm_custom']: + subsystem.replace_realm_config(self.mdict['est_realm_custom']) + return + + realm_type = self.mdict['est_realm_type'] + props = subsystem.get_realm_config(realm_type=realm_type) + + if realm_type == 'in-memory': + + username = self.mdict.get('est_realm_username') + pki.util.set_property(props, 'username', username) + + password = self.mdict.get('est_realm_password') + pki.util.set_property(props, 'password', password) + + elif realm_type == 'ds': + + url = self.mdict.get('est_realm_url') + pki.util.set_property(props, 'url', url) + + auth_type = props.get('authType') + auth_type = self.mdict.get('est_realm_auth_type', auth_type) + pki.util.set_property(props, 'authType', auth_type) + + if auth_type == 'BasicAuth': + bind_dn = self.mdict.get('est_realm_bind_dn') + pki.util.set_property(props, 'bindDN', bind_dn) + + bind_password = self.mdict.get('est_realm_bind_password') + pki.util.set_property(props, 'bindPassword', bind_password) + + elif auth_type == 'SslClientAuth': + nickname = self.mdict.get('est_realm_nickname') + pki.util.set_property(props, 'nickname', nickname) + + users_dn = self.mdict.get('est_realm_users_dn') + pki.util.set_property(props, 'usersDN', users_dn) + + groups_dn = self.mdict.get('est_realm_groups_dn') + pki.util.set_property(props, 'groupsDN', groups_dn) + + elif realm_type == 'postgresql': + + url = self.mdict.get('est_realm_url') + pki.util.set_property(props, 'url', url) + + user = self.mdict.get('est_realm_user') + pki.util.set_property(props, 'user', user) + + password = self.mdict.get('est_realm_password') + pki.util.set_property(props, 'password', password) + + statements = self.mdict.get('est_realm_statements') + pki.util.set_property(props, 'statements', statements) + subsystem.update_realm_config(props) + + def deploy_est_webapp(self, subsystem): + ''' + See also pki-server est-deploy. + ''' + + logger.info('Deploying EST webapp') if len(self.instance.get_subsystems()) == 1: - # if this is the first subsystem, start the server - self.instance.start( + # 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( wait=True, max_wait=self.startup_timeout, timeout=self.request_timeout) - def spawn(self): + def spawn_est(self): + subsystem = self.create_est_subsystem() + self.instance.add_subsystem(subsystem) + + self.configure_est_backend(subsystem) + self.configure_est_authorizer(subsystem) + self.configure_est_realm(subsystem) + self.deploy_est_webapp(subsystem) + + def spawn(self): print('Installing ' + self.subsystem_type + ' into ' + self.instance.base_dir + '.') scriptlet = pki.server.deployment.scriptlets.initialization.PkiScriptlet() @@ -5406,6 +5526,10 @@ def spawn(self): self.spawn_acme() return + if self.subsystem_type == 'EST': + self.spawn_est() + return + scriptlet = pki.server.deployment.scriptlets.subsystem_layout.PkiScriptlet() scriptlet.deployer = self scriptlet.instance = self.instance diff --git a/base/server/python/pki/server/deployment/pkiconfig.py b/base/server/python/pki/server/deployment/pkiconfig.py index 5793401436b..ae6be596fd8 100644 --- a/base/server/python/pki/server/deployment/pkiconfig.py +++ b/base/server/python/pki/server/deployment/pkiconfig.py @@ -36,7 +36,7 @@ PKI_DEPLOYMENT_DEFAULT_UID = 17 PKI_DEPLOYMENT_DEFAULT_USER = "pkiuser" -PKI_SUBSYSTEMS = ['CA', 'KRA', 'OCSP', 'TKS', 'TPS', 'ACME'] +PKI_SUBSYSTEMS = ['CA', 'KRA', 'OCSP', 'TKS', 'TPS', 'ACME', 'EST'] PKI_BASE_RESERVED_NAMES = ["alias", "bin", "ca", "common", "conf", "kra", "lib", "logs", "ocsp", "temp", "tks", "tps", "webapps", "work"] diff --git a/base/server/python/pki/server/deployment/scriptlets/initialization.py b/base/server/python/pki/server/deployment/scriptlets/initialization.py index 5639b2448ff..b3d2e89f72c 100644 --- a/base/server/python/pki/server/deployment/scriptlets/initialization.py +++ b/base/server/python/pki/server/deployment/scriptlets/initialization.py @@ -41,8 +41,9 @@ def verify_sensitive_data(self, deployer): configuration_file = deployer.configuration_file # Verify existence of Admin Password (except for Clones) - if configuration_file.subsystem != 'ACME' and \ - not configuration_file.clone: + if (configuration_file.subsystem != 'ACME' and + configuration_file.subsystem != 'EST' and not + configuration_file.clone): configuration_file.confirm_data_exists('pki_admin_password') # If HSM, verify absence of all PKCS #12 backup parameters @@ -64,7 +65,8 @@ def verify_sensitive_data(self, deployer): configuration_file.confirm_data_exists('pki_client_database_password') # Verify existence of Client PKCS #12 Password for Admin Cert - if configuration_file.subsystem != 'ACME': + if (configuration_file.subsystem != 'ACME' and + configuration_file.subsystem != 'EST'): configuration_file.confirm_data_exists('pki_client_pkcs12_password') if configuration_file.clone: diff --git a/base/server/python/pki/server/pkispawn.py b/base/server/python/pki/server/pkispawn.py index 43c76c38d52..f104416c9bf 100644 --- a/base/server/python/pki/server/pkispawn.py +++ b/base/server/python/pki/server/pkispawn.py @@ -190,8 +190,8 @@ def main(argv): parser.indent = 0 deployer.subsystem_type = parser.read_text( - 'Subsystem (CA/KRA/OCSP/TKS/TPS/ACME)', - options=['CA', 'KRA', 'OCSP', 'TKS', 'TPS', 'ACME'], + 'Subsystem (CA/KRA/OCSP/TKS/TPS/ACME/EST)', + options=['CA', 'KRA', 'OCSP', 'TKS', 'TPS', 'ACME', 'EST'], default='CA', case_sensitive=False).upper() print() else: @@ -672,6 +672,9 @@ def main(argv): elif deployer.subsystem_type == 'ACME': print_acme_install_information() + elif deployer.subsystem_type == 'EST': + print_est_install_information() + else: print_final_install_information(parser.mdict, deployer.instance) @@ -693,7 +696,8 @@ def validate_user_deployment_cfg(user_deployment_cfg): '[OCSP]', '[TKS]', '[TPS]', - '[ACME]']: + '[ACME]', + '[EST]']: raise Exception('Invalid deployment configuration section: %s' % line) @@ -952,6 +956,16 @@ def print_acme_install_information(): print(log.PKI_SPAWN_INFORMATION_FOOTER) +def print_est_install_information(): + + print(log.PKI_SPAWN_INFORMATION_HEADER) + + print(log.PKI_ACCESS_URL % (deployer.mdict['pki_hostname'], + deployer.mdict['pki_https_port'], + '.well-known/%s' % deployer.subsystem_type.lower())) + print(log.PKI_SPAWN_INFORMATION_FOOTER) + + def print_final_install_information(mdict, instance): print(log.PKI_SPAWN_INFORMATION_HEADER) diff --git a/base/server/python/pki/server/subsystem.py b/base/server/python/pki/server/subsystem.py index dfa5cc28961..3908f93becd 100644 --- a/base/server/python/pki/server/subsystem.py +++ b/base/server/python/pki/server/subsystem.py @@ -2857,6 +2857,116 @@ def update_realm_config(self, config): self.instance.store_properties(self.realm_conf, config) +class ESTSubsystem(PKISubsystem): + + def __init__(self, instance): + super().__init__(instance, 'est') + + @property + def backend_conf(self): + return os.path.join(self.conf_dir, 'backend.conf') + + @property + def authorizer_conf(self): + return os.path.join(self.conf_dir, 'authorizer.conf') + + @property + def realm_conf(self): + return os.path.join(self.conf_dir, 'realm.conf') + + def create(self, exist_ok=False, force=False): + + self.instance.makedirs(self.conf_dir, exist_ok=exist_ok) + + default_conf_dir = os.path.join(pki.server.PKIServer.SHARE_DIR, 'est', 'conf') + + self.instance.copy( + os.path.join(default_conf_dir, 'backend.conf'), + self.backend_conf, + exist_ok=exist_ok, + force=force) + + self.instance.copy( + os.path.join(default_conf_dir, 'authorizer.conf'), + self.authorizer_conf, + exist_ok=exist_ok, + force=force) + + def get_backend_config(self, default=False): + + if default: + backend_conf = os.path.join( + pki.server.PKIServer.SHARE_DIR, + 'est', + 'conf', + 'backend.conf') + else: + backend_conf = self.backend_conf + + logger.info('Loading %s', backend_conf) + config = {} + pki.util.load_properties(backend_conf, config) + return config + + def update_backend_config(self, config): + + logger.info('Updating %s', self.backend_conf) + self.instance.store_properties(self.backend_conf, config) + + def get_authorizer_config(self, default=False): + + if default: + authorizer_conf = os.path.join( + pki.server.PKIServer.SHARE_DIR, + 'est', + 'conf', + 'authorizer.conf') + else: + authorizer_conf = self.authorizer_conf + + logger.info('Loading %s', authorizer_conf) + config = {} + pki.util.load_properties(authorizer_conf, config) + + return config + + def update_authorizer_config(self, config): + + logger.info('Updating %s', self.authorizer_conf) + self.instance.store_properties(self.authorizer_conf, config) + + def get_realm_config(self, realm_type=None): + + template_dir = os.path.join(pki.server.PKIServer.SHARE_DIR, 'est', 'conf', 'realm') + + if realm_type: + # if realm type is specified, load the realm.conf template + realm_conf = os.path.join(template_dir, '%s.conf' % realm_type) + else: + # otherwise, load the current realm.conf in the instance + realm_conf = self.realm_conf + + logger.info('Loading %s', realm_conf) + config = {} + pki.util.load_properties(realm_conf, config) + + return config + + def update_realm_config(self, config): + + logger.info('Updating %s', self.realm_conf) + self.instance.store_properties(self.realm_conf, config) + + def replace_realm_config(self, realm_path): + + logger.info('Replace %s', self.realm_conf) + self.instance.copy( + realm_path, + self.realm_conf, + exist_ok=False, + force=True) + + class PKISubsystemFactory(object): @classmethod