From 85bdb045003657cd9cd6abb49b312eb57eb05f16 Mon Sep 17 00:00:00 2001 From: "Endi S. Dewata" Date: Mon, 9 Sep 2024 13:28:30 -0500 Subject: [PATCH] Update pkispawn to support ACME pkispawn has been modified to support installing ACME in a shared PKI server (e.g. with existing CA). New pkispawn params have been added to specify the ACME database, issuer, and realm. A sample configuration has been provided in acme.cfg. The pki_ds_setup, pki_security_domain_setup, and pki_registry_enable params in the default.cfg have been moved from [DEFAULT] into each subsystem's section so that ACME can skip DS setup, security domain setup, and registry setup by default. The templates for ACME database, issuer, and realm configs have been modified to no longer contain passwords. The passwords need to be specified during installation. Some code in acme.py has been moved into subsystem.py so that it can be reused. The basic ACME test and the test with PostgreSQL have been modified to install ACME using pkispawn. --- .github/workflows/acme-basic-test.yml | 33 ++- .github/workflows/acme-postgresql-test.yml | 39 ++-- .github/workflows/acme-switchover-test.yml | 9 +- base/acme/database/ds/database.conf | 2 +- base/acme/database/ldap/database.conf | 2 +- base/acme/database/openldap/database.conf | 2 +- base/acme/database/postgresql/database.conf | 2 +- base/acme/issuer/pki/issuer.conf | 2 +- base/acme/openshift/pki-acme-database.yaml | 6 +- base/acme/openshift/pki-acme-issuer.yaml | 2 +- base/acme/openshift/pki-acme-realm.yaml | 4 +- base/acme/realm/ds/realm.conf | 2 +- base/acme/realm/in-memory/realm.conf | 2 +- base/acme/realm/postgresql/realm.conf | 2 +- base/server/etc/default.cfg | 82 +++++++- base/server/examples/installation/acme.cfg | 15 ++ base/server/python/pki/server/cli/acme.py | 174 +++++----------- .../python/pki/server/deployment/__init__.py | 188 ++++++++++++++++++ .../python/pki/server/deployment/pkiconfig.py | 2 +- .../pki/server/deployment/pkimessages.py | 2 +- base/server/python/pki/server/pkispawn.py | 30 ++- base/server/python/pki/server/subsystem.py | 136 +++++++++++++ 22 files changed, 560 insertions(+), 178 deletions(-) create mode 100644 base/server/examples/installation/acme.cfg diff --git a/.github/workflows/acme-basic-test.yml b/.github/workflows/acme-basic-test.yml index 35a823ecbd3..0e6c468d7a8 100644 --- a/.github/workflows/acme-basic-test.yml +++ b/.github/workflows/acme-basic-test.yml @@ -100,17 +100,28 @@ jobs: - name: Install ACME in PKI container run: | - docker exec pki pki-server acme-create - docker exec pki pki-server acme-database-mod \ - --type ds \ - -D url=ldap://ds.example.com:3389 - docker exec pki pki-server acme-issuer-mod \ - --type pki \ - -D url=https://pki.example.com:8443 - docker exec pki pki-server acme-realm-mod \ - --type ds \ - -D url=ldap://ds.example.com:3389 - docker exec pki pki-server acme-deploy --wait + docker exec pki pkispawn \ + -f /usr/share/pki/server/examples/installation/acme.cfg \ + -s ACME \ + -D acme_database_url=ldap://ds.example.com:3389 \ + -D acme_issuer_url=https://pki.example.com:8443 \ + -D acme_realm_url=ldap://ds.example.com:3389 \ + -v + + - name: Check ACME database config + if: always() + run: | + docker exec pki cat /etc/pki/pki-tomcat/acme/database.conf + + - name: Check ACME issuer config + if: always() + run: | + docker exec pki cat /etc/pki/pki-tomcat/acme/issuer.conf + + - name: Check ACME realm config + if: always() + run: | + docker exec pki cat /etc/pki/pki-tomcat/acme/realm.conf - name: Check initial ACME accounts run: | diff --git a/.github/workflows/acme-postgresql-test.yml b/.github/workflows/acme-postgresql-test.yml index cdbdb321298..f00e543f146 100644 --- a/.github/workflows/acme-postgresql-test.yml +++ b/.github/workflows/acme-postgresql-test.yml @@ -149,19 +149,32 @@ jobs: - name: Install ACME in PKI container run: | - docker exec pki pki-server acme-create - docker exec pki pki-server acme-database-mod \ - --type postgresql \ - -Dpassword=mysecretpassword \ - -Durl='jdbc:postgresql://postgresql.example.com:5432/acme?ssl=true&sslmode=require' - docker exec pki pki-server acme-issuer-mod \ - --type pki \ - -D url=https://pki.example.com:8443 - docker exec pki pki-server acme-realm-mod \ - --type postgresql \ - -Dpassword=mysecretpassword \ - -Durl='jdbc:postgresql://postgresql.example.com:5432/acme?ssl=true&sslmode=require' - docker exec pki pki-server acme-deploy --wait + docker exec pki pkispawn \ + -f /usr/share/pki/server/examples/installation/acme.cfg \ + -s ACME \ + -D acme_database_type=postgresql \ + -D acme_database_url="jdbc:postgresql://postgresql.example.com:5432/acme?ssl=true&sslmode=require" \ + -D acme_database_password=mysecretpassword \ + -D acme_issuer_url=https://pki.example.com:8443 \ + -D acme_realm_type=postgresql \ + -D acme_realm_url="jdbc:postgresql://postgresql.example.com:5432/acme?ssl=true&sslmode=require" \ + -D acme_realm_password=mysecretpassword \ + -v + + - name: Check ACME database config + if: always() + run: | + docker exec pki cat /etc/pki/pki-tomcat/acme/database.conf + + - name: Check ACME issuer config + if: always() + run: | + docker exec pki cat /etc/pki/pki-tomcat/acme/issuer.conf + + - name: Check ACME realm config + if: always() + run: | + docker exec pki cat /etc/pki/pki-tomcat/acme/realm.conf - name: Run PKI healthcheck in PKI container run: docker exec pki pki-healthcheck --failures-only diff --git a/.github/workflows/acme-switchover-test.yml b/.github/workflows/acme-switchover-test.yml index bd9a81eba65..f7fbcb5848a 100644 --- a/.github/workflows/acme-switchover-test.yml +++ b/.github/workflows/acme-switchover-test.yml @@ -80,13 +80,16 @@ jobs: docker exec pki pki-server acme-create docker exec pki pki-server acme-database-mod \ --type ds \ - -D url=ldap://ds.example.com:3389 + -D url=ldap://ds.example.com:3389 \ + -D bindPassword=Secret.123 docker exec pki pki-server acme-issuer-mod \ --type pki \ - -D url=https://pki.example.com:8443 + -D url=https://pki.example.com:8443 \ + -D password=Secret.123 docker exec pki pki-server acme-realm-mod \ --type ds \ - -D url=ldap://ds.example.com:3389 + -D url=ldap://ds.example.com:3389 \ + -D bindPassword=Secret.123 docker exec pki bash -c "echo baseURL=http://server1.example.com:8080/acme >> /var/lib/pki/pki-tomcat/conf/acme/engine.conf" docker exec pki pki-server acme-deploy --wait diff --git a/base/acme/database/ds/database.conf b/base/acme/database/ds/database.conf index a43f4e0b430..802ae50cc11 100644 --- a/base/acme/database/ds/database.conf +++ b/base/acme/database/ds/database.conf @@ -2,5 +2,5 @@ class=org.dogtagpki.acme.database.DSDatabase url=ldap://localhost.localdomain:389 authType=BasicAuth bindDN=cn=Directory Manager -bindPassword=Secret.123 +bindPassword= baseDN=dc=acme,dc=pki,dc=example,dc=com diff --git a/base/acme/database/ldap/database.conf b/base/acme/database/ldap/database.conf index a30be64ef95..8611885867d 100644 --- a/base/acme/database/ldap/database.conf +++ b/base/acme/database/ldap/database.conf @@ -2,5 +2,5 @@ class=org.dogtagpki.acme.database.LDAPDatabase url=ldap://localhost.localdomain:389 authType=BasicAuth bindDN=cn=Directory Manager -bindPassword=Secret.123 +bindPassword= baseDN=dc=acme,dc=pki,dc=example,dc=com diff --git a/base/acme/database/openldap/database.conf b/base/acme/database/openldap/database.conf index ee589f12125..1c0c7370c53 100644 --- a/base/acme/database/openldap/database.conf +++ b/base/acme/database/openldap/database.conf @@ -2,5 +2,5 @@ class=org.dogtagpki.acme.database.OpenLDAPDatabase url=ldap://localhost.localdomain:389 authType=BasicAuth bindDN=cn=Manager,dc=example,dc=com -bindPassword=Secret.123 +bindPassword= baseDN=dc=acme,dc=pki,dc=example,dc=com diff --git a/base/acme/database/postgresql/database.conf b/base/acme/database/postgresql/database.conf index 16a00cd1be8..927927d9b79 100644 --- a/base/acme/database/postgresql/database.conf +++ b/base/acme/database/postgresql/database.conf @@ -1,4 +1,4 @@ class=org.dogtagpki.acme.database.PostgreSQLDatabase url=jdbc:postgresql://localhost.localdomain:5432/acme user=acme -password=Secret.123 +password= diff --git a/base/acme/issuer/pki/issuer.conf b/base/acme/issuer/pki/issuer.conf index 233d12ca897..26a3c60ef74 100644 --- a/base/acme/issuer/pki/issuer.conf +++ b/base/acme/issuer/pki/issuer.conf @@ -2,4 +2,4 @@ class=org.dogtagpki.acme.issuer.PKIIssuer url=https://localhost.localdomain:8443 profile=acmeServerCert username=caadmin -password=Secret.123 +password= diff --git a/base/acme/openshift/pki-acme-database.yaml b/base/acme/openshift/pki-acme-database.yaml index a182af69f69..6dd559cd369 100644 --- a/base/acme/openshift/pki-acme-database.yaml +++ b/base/acme/openshift/pki-acme-database.yaml @@ -14,7 +14,7 @@ stringData: # url: ldap://ds:389 # authType: BasicAuth # bindDN: cn=Directory Manager - # bindPassword: Secret.123 + # bindPassword: ... # baseDN: dc=acme,dc=pki,dc=example,dc=com # # OpenLDAP Database @@ -23,12 +23,12 @@ stringData: # url: ldap://openldap:389 # authType: BasicAuth # bindDN: cn=Manager,dc=example,dc=com - # bindPassword: Secret.123 + # bindPassword: ... # baseDN: dc=acme,dc=pki,dc=example,dc=com # # PostgreSQL Database # ------------------- # class: org.dogtagpki.acme.database.PostgreSQLDatabase - # password: Secret.123 + # password: ... # url: jdbc:postgresql://postgresql:5432/acme # user: acme diff --git a/base/acme/openshift/pki-acme-issuer.yaml b/base/acme/openshift/pki-acme-issuer.yaml index 138c5a9cb99..7961bb810ef 100644 --- a/base/acme/openshift/pki-acme-issuer.yaml +++ b/base/acme/openshift/pki-acme-issuer.yaml @@ -14,4 +14,4 @@ stringData: # url: https://pki-ca:8443 # profile: acmeServerCert # username: caadmin - # password: Secret.123 + # password: ... diff --git a/base/acme/openshift/pki-acme-realm.yaml b/base/acme/openshift/pki-acme-realm.yaml index 9199710f394..4adc7c73784 100644 --- a/base/acme/openshift/pki-acme-realm.yaml +++ b/base/acme/openshift/pki-acme-realm.yaml @@ -14,13 +14,13 @@ stringData: # url: ldap://ds:389 # authType: BasicAuth # bindDN: cn=Directory Manager - # bindPassword: Secret.123 + # bindPassword: ... # usersDN: ou=people,dc=acme,dc=pki,dc=example,dc=com # groupsDN: ou=groups,dc=acme,dc=pki,dc=example,dc=com # # PostgreSQL Realm # ---------------- # class: org.dogtagpki.acme.realm.PostgreSQLRealm - # password: Secret.123 + # password: ... # url: jdbc:postgresql://postgresql:5432/acme # user: acme diff --git a/base/acme/realm/ds/realm.conf b/base/acme/realm/ds/realm.conf index c2c5e484a18..eaf305b9b51 100644 --- a/base/acme/realm/ds/realm.conf +++ b/base/acme/realm/ds/realm.conf @@ -2,6 +2,6 @@ class=org.dogtagpki.acme.realm.DSRealm url=ldap://localhost.localdomain:389 authType=BasicAuth bindDN=cn=Directory Manager -bindPassword=Secret.123 +bindPassword= usersDN=ou=people,dc=acme,dc=pki,dc=example,dc=com groupsDN=ou=groups,dc=acme,dc=pki,dc=example,dc=com diff --git a/base/acme/realm/in-memory/realm.conf b/base/acme/realm/in-memory/realm.conf index 6dc4a01dbf0..12bfa76d251 100644 --- a/base/acme/realm/in-memory/realm.conf +++ b/base/acme/realm/in-memory/realm.conf @@ -1,3 +1,3 @@ class=org.dogtagpki.acme.realm.InMemoryRealm username=admin -password=Secret.123 +password= diff --git a/base/acme/realm/postgresql/realm.conf b/base/acme/realm/postgresql/realm.conf index 0e37e6ca576..0714c9d5811 100644 --- a/base/acme/realm/postgresql/realm.conf +++ b/base/acme/realm/postgresql/realm.conf @@ -1,4 +1,4 @@ class=org.dogtagpki.acme.realm.PostgreSQLRealm url=jdbc:postgresql://localhost.localdomain:5432/acme user=acme -password=Secret.123 +password= diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg index c806aa714cf..642fb019f19 100644 --- a/base/server/etc/default.cfg +++ b/base/server/etc/default.cfg @@ -33,6 +33,11 @@ sensitive_parameters= pki_server_database_password pki_server_pkcs12_password pki_token_password + acme_database_bind_password + acme_database_password + acme_issuer_password + acme_realm_bind_password + acme_realm_password pki_instance_name=pki-tomcat pki_http_port=8080 @@ -80,7 +85,6 @@ pki_ds_ldap_port=389 pki_ds_ldaps_port=636 pki_ds_password= pki_ds_remove_data=True -pki_ds_setup=True pki_ds_secure_connection=False pki_ds_secure_connection_ca_nickname=Directory Server CA certificate pki_ds_secure_connection_ca_pem_file= @@ -94,13 +98,14 @@ pki_issuing_ca_uri=https://%(pki_issuing_ca_hostname)s:%(pki_issuing_ca_https_po pki_issuing_ca=%(pki_issuing_ca_uri)s pki_replication_password= pki_status_request_timeout= -pki_security_domain_setup=True + pki_security_domain_hostname=%(pki_hostname)s pki_security_domain_https_port=8443 pki_security_domain_uri=https://%(pki_security_domain_hostname)s:%(pki_security_domain_https_port)s pki_security_domain_name=%(pki_dns_domainname)s Security Domain pki_security_domain_password= pki_security_domain_user=caadmin + #for supporting server cert SAN injection pki_san_inject=False pki_san_for_server_cert= @@ -247,8 +252,6 @@ CATALINA_HOME=/usr/share/tomcat pki_tomcat_bin_path=%(CATALINA_HOME)s/bin pki_tomcat_lib_path=%(CATALINA_HOME)s/lib -pki_registry_enable=True - ############################################################################### ## CA Configuration: ## ## ## @@ -329,9 +332,11 @@ pki_admin_uid=caadmin pki_audit_signing_nickname=auditSigningCert cert-%(pki_instance_name)s CA pki_audit_signing_subject_dn=cn=CA Audit Signing Certificate,ou=%(pki_instance_name)s,o=%(pki_security_domain_name)s +pki_ds_setup=True pki_ds_base_dn=o=%(pki_instance_name)s-CA pki_ds_database=%(pki_instance_name)s-CA pki_ds_hostname=%(pki_hostname)s + pki_subsystem_name=CA %(pki_hostname)s %(pki_https_port)s pki_share_db=False pki_master_crl_enable=True @@ -360,6 +365,9 @@ pki_request_id_generator=random # Cert request ID length in bits pki_request_id_length=128 +pki_security_domain_setup=True +pki_registry_enable=True + ############################################################################### ## KRA Configuration: ## ## ## @@ -441,9 +449,11 @@ pki_admin_uid=kraadmin pki_audit_signing_nickname=auditSigningCert cert-%(pki_instance_name)s KRA pki_audit_signing_subject_dn=cn=KRA Audit Signing Certificate,ou=%(pki_instance_name)s,o=%(pki_security_domain_name)s +pki_ds_setup=True pki_ds_base_dn=o=%(pki_instance_name)s-KRA pki_ds_database=%(pki_instance_name)s-KRA pki_ds_hostname=%(pki_hostname)s + pki_subsystem_name=KRA %(pki_hostname)s %(pki_https_port)s pki_share_db=True pki_share_dbuser_dn=uid=pkidbuser,ou=people,%(pki_ds_base_dn)s @@ -460,6 +470,9 @@ pki_request_id_generator=random # Key request ID length in bits pki_request_id_length=128 +pki_security_domain_setup=True +pki_registry_enable=True + ############################################################################### ## OCSP Configuration: ## ## ## @@ -528,13 +541,17 @@ pki_admin_uid=ocspadmin pki_audit_signing_nickname=auditSigningCert cert-%(pki_instance_name)s OCSP pki_audit_signing_subject_dn=cn=OCSP Audit Signing Certificate,ou=%(pki_instance_name)s,o=%(pki_security_domain_name)s +pki_ds_setup=True pki_ds_base_dn=o=%(pki_instance_name)s-OCSP pki_ds_database=%(pki_instance_name)s-OCSP pki_ds_hostname=%(pki_hostname)s + pki_subsystem_name=OCSP %(pki_hostname)s %(pki_https_port)s pki_share_db=True pki_share_dbuser_dn=uid=pkidbuser,ou=people,%(pki_ds_base_dn)s +pki_security_domain_setup=True +pki_registry_enable=True ############################################################################### ## TKS Configuration: ## @@ -552,13 +569,19 @@ pki_admin_subject_dn=cn=PKI Administrator,e=%(pki_admin_email)s,ou=%(pki_instanc pki_admin_uid=tksadmin pki_audit_signing_nickname=auditSigningCert cert-%(pki_instance_name)s TKS pki_audit_signing_subject_dn=cn=TKS Audit Signing Certificate,ou=%(pki_instance_name)s,o=%(pki_security_domain_name)s + +pki_ds_setup=True pki_ds_base_dn=o=%(pki_instance_name)s-TKS pki_ds_database=%(pki_instance_name)s-TKS pki_ds_hostname=%(pki_hostname)s + pki_subsystem_name=TKS %(pki_hostname)s %(pki_https_port)s pki_share_db=True pki_share_dbuser_dn=uid=pkidbuser,ou=people,%(pki_ds_base_dn)s +pki_security_domain_setup=True +pki_registry_enable=True + ############################################################################### ## TPS Configuration: ## ## ## @@ -574,9 +597,12 @@ pki_admin_subject_dn=cn=PKI Administrator,e=%(pki_admin_email)s,ou=%(pki_instanc pki_admin_uid=tpsadmin pki_audit_signing_nickname=auditSigningCert cert-%(pki_instance_name)s TPS pki_audit_signing_subject_dn=cn=TPS Audit Signing Certificate,ou=%(pki_instance_name)s,o=%(pki_security_domain_name)s + +pki_ds_setup=True pki_ds_base_dn=o=%(pki_instance_name)s-TPS pki_ds_database=%(pki_instance_name)s-TPS pki_ds_hostname=%(pki_hostname)s + pki_subsystem_name=TPS %(pki_hostname)s %(pki_https_port)s pki_authdb_hostname=%(pki_hostname)s pki_authdb_port=389 @@ -589,3 +615,51 @@ pki_import_shared_secret=False pki_share_db=True pki_share_dbuser_dn=uid=pkidbuser,ou=people,%(pki_ds_base_dn)s pki_source_phone_home_xml=/usr/share/pki/%(pki_subsystem_type)s/conf/phoneHome.xml + +pki_security_domain_setup=True +pki_registry_enable=True + +[ACME] +pki_ds_setup=False +pki_security_domain_setup=False +pki_registry_enable=False + +# Database params: +# - acme_database_type +# - acme_database_url +# - acme_database_auth_type +# - acme_database_bind_dn +# - acme_database_bind_password +# - acme_database_bind_nickname +# - acme_database_user +# - acme_database_password +# - acme_database_base_dn +# +# See /usr/share/pki/acme/database//database.conf + +# Issuer params: +# - acme_issuer_type +# - acme_issuer_url +# - acme_issuer_nickname +# - acme_issuer_extensions +# - acme_issuer_username +# - acme_issuer_password +# - acme_issuer_password_file +# - acme_issuer_profile +# +# See /usr/share/pki/acme/issuer//issuer.conf + +# Realm params: +# - acme_realm_type +# - acme_realm_url +# - acme_realm_auth_type +# - acme_realm_bind_dn +# - acme_realm_bind_password +# - acme_realm_nickname +# - acme_realm_user +# - acme_realm_username +# - acme_realm_password +# - acme_realm_users_dn +# - acme_realm_groups_dn +# +# See /usr/share/pki/acme/realm//realm.conf diff --git a/base/server/examples/installation/acme.cfg b/base/server/examples/installation/acme.cfg new file mode 100644 index 00000000000..3426740113d --- /dev/null +++ b/base/server/examples/installation/acme.cfg @@ -0,0 +1,15 @@ +[DEFAULT] +pki_server_database_password=Secret.123 + +[ACME] +acme_database_type=ds +acme_database_url=ldap://localhost.localdomain:3389 +acme_database_bind_password=Secret.123 + +acme_issuer_type=pki +acme_issuer_url=https://localhost.localdomain:8443 +acme_issuer_password=Secret.123 + +acme_realm_type=ds +acme_realm_url=ldap://localhost.localdomain:3389 +acme_realm_bind_password=Secret.123 diff --git a/base/server/python/pki/server/cli/acme.py b/base/server/python/pki/server/cli/acme.py index a082df73e3f..07a9202d7ed 100644 --- a/base/server/python/pki/server/cli/acme.py +++ b/base/server/python/pki/server/cli/acme.py @@ -17,34 +17,6 @@ import pki.server import pki.server.cli.subsystem -# TODO: auto-populate this map from /usr/share/pki/acme/database -DATABASE_CLASSES = { - 'ds': 'org.dogtagpki.acme.database.DSDatabase', - 'in-memory': 'org.dogtagpki.acme.database.InMemoryDatabase', - 'ldap': 'org.dogtagpki.acme.database.LDAPDatabase', - 'openldap': 'org.dogtagpki.acme.database.OpenLDAPDatabase', - 'postgresql': 'org.dogtagpki.acme.database.PostgreSQLDatabase' -} - -DATABASE_TYPES = {value: key for key, value in DATABASE_CLASSES.items()} - -# TODO: auto-populate this map from /usr/share/pki/acme/issuer -ISSUER_CLASSES = { - 'nss': 'org.dogtagpki.acme.issuer.NSSIssuer', - 'pki': 'org.dogtagpki.acme.issuer.PKIIssuer' -} - -ISSUER_TYPES = {value: key for key, value in ISSUER_CLASSES.items()} - -# TODO: auto-populate this map from /usr/share/pki/acme/realm -REALM_CLASSES = { - 'ds': 'org.dogtagpki.acme.realm.DSRealm', - 'in-memory': 'org.dogtagpki.acme.realm.InMemoryRealm', - 'postgresql': 'org.dogtagpki.acme.realm.PostgreSQLRealm' -} - -REALM_TYPES = {value: key for key, value in REALM_CLASSES.items()} - logger = logging.getLogger(__name__) @@ -72,7 +44,7 @@ def __init__(self): super().__init__('create', 'Create ACME subsystem') def print_help(self): - print('Usage: pki-server acme-create [OPTIONS] [name]') + print('Usage: pki-server acme-create [OPTIONS]') print() print(' -i, --instance Instance ID (default: pki-tomcat).') print(' --force Force creation.') @@ -84,7 +56,7 @@ def print_help(self): def execute(self, argv): try: - opts, args = getopt.gnu_getopt(argv, 'i:v', [ + opts, _ = getopt.gnu_getopt(argv, 'i:v', [ 'instance=', 'database=', 'issuer=', 'force', 'verbose', 'debug', 'help']) @@ -94,7 +66,6 @@ def execute(self, argv): self.print_help() sys.exit(1) - name = 'acme' instance_name = 'pki-tomcat' force = False @@ -120,9 +91,6 @@ def execute(self, argv): self.print_help() sys.exit(1) - if len(args) > 0: - name = args[0] - instance = pki.server.PKIServerFactory.create(instance_name) if not instance.exists(): @@ -130,34 +98,8 @@ def execute(self, argv): instance.load() - acme_conf_dir = os.path.join(instance.conf_dir, name) - instance.makedirs(acme_conf_dir, exist_ok=True) - - acme_share_dir = os.path.join(pki.server.PKIServer.SHARE_DIR, 'acme') - - database_template = os.path.join(acme_share_dir, 'conf', 'database.conf') - database_conf = os.path.join(acme_conf_dir, 'database.conf') - instance.copy( - database_template, - database_conf, - exist_ok=True, - force=force) - - issuer_template = os.path.join(acme_share_dir, 'conf', 'issuer.conf') - issuer_conf = os.path.join(acme_conf_dir, 'issuer.conf') - instance.copy( - issuer_template, - issuer_conf, - exist_ok=True, - force=force) - - realm_template = os.path.join(acme_share_dir, 'conf', 'realm.conf') - realm_conf = os.path.join(acme_conf_dir, 'realm.conf') - instance.copy( - realm_template, - realm_conf, - exist_ok=True, - force=force) + subsystem = pki.server.subsystem.ACMESubsystem(instance) + subsystem.create(force=force) class ACMERemoveCLI(pki.cli.CLI): @@ -661,7 +603,7 @@ def execute(self, argv): database_class = config.get('class') - database_type = DATABASE_TYPES.get(database_class) + database_type = pki.server.subsystem.ACME_DATABASE_TYPES.get(database_class) print(' Database Type: %s' % database_type) if database_type in ['ds', 'ldap', 'openldap']: @@ -724,7 +666,7 @@ def print_help(self): print() print(' -i, --instance Instance ID (default: pki-tomcat).') print(' --type Database type: {0}' - .format(', '.join(DATABASE_TYPES.values()))) + .format(', '.join(pki.server.subsystem.ACME_DATABASE_TYPES.values()))) print(' -D= Set property value.') print(' -v, --verbose Run in verbose mode.') print(' --debug Run in debug mode.') @@ -753,7 +695,7 @@ def execute(self, argv): elif o == '--type': database_type = a - if database_type not in DATABASE_TYPES.values(): + if database_type not in pki.server.subsystem.ACME_DATABASE_TYPES.values(): raise Exception('Invalid database type: {0}'.format(database_type)) elif o == '-D': @@ -784,19 +726,8 @@ def execute(self, argv): instance.load() - acme_conf_dir = os.path.join(instance.conf_dir, 'acme') - database_conf = os.path.join(acme_conf_dir, 'database.conf') - config = {} - - if database_type: - # if --type is specified, load the database.conf template - source = '/usr/share/pki/acme/database/{0}/database.conf'.format(database_type) - else: - # otherwise, load the database.conf from the instance - source = database_conf - - logger.info('Loading %s', source) - pki.util.load_properties(source, config) + subsystem = pki.server.subsystem.ACMESubsystem(instance) + config = subsystem.get_database_config(database_type=database_type) # if --type or -D is specified, use silent mode if database_type or props: @@ -806,7 +737,7 @@ def execute(self, argv): logger.info('- %s: %s', name, value) pki.util.set_property(config, name, value) - instance.store_properties(database_conf, config) + subsystem.update_database_config(config) return # otherwise, use interactive mode @@ -821,16 +752,19 @@ def execute(self, argv): print() print( 'Enter the type of the database. ' - 'Available types: %s.' % ', '.join(DATABASE_TYPES.values())) - database_type = DATABASE_TYPES.get(database_class) + 'Available types: %s.' % ', '.join(pki.server.subsystem.ACME_DATABASE_TYPES.values())) + database_type = pki.server.subsystem.ACME_DATABASE_TYPES.get(database_class) orig_database_type = database_type database_type = pki.util.read_text( ' Database Type', - options=DATABASE_TYPES.values(), + options=pki.server.subsystem.ACME_DATABASE_TYPES.values(), default=database_type, required=True) - pki.util.set_property(config, 'class', DATABASE_CLASSES.get(database_type)) + pki.util.set_property( + config, + 'class', + pki.server.subsystem.ACME_DATABASE_CLASSES.get(database_type)) if orig_database_type != database_type: source = '/usr/share/pki/acme/database/{0}/database.conf'.format(database_type) @@ -922,7 +856,7 @@ def execute(self, argv): ' Password', default=password, password=True, required=True) pki.util.set_property(config, 'password', password) - instance.store_properties(database_conf, config) + subsystem.update_database_config(config) class ACMEIssuerCLI(pki.cli.CLI): @@ -997,7 +931,7 @@ def execute(self, argv): issuer_class = config.get('class') - issuer_type = ISSUER_TYPES.get(issuer_class) + issuer_type = pki.server.subsystem.ACME_ISSUER_TYPES.get(issuer_class) print(' Issuer Type: %s' % issuer_type) if issuer_type == 'nss': @@ -1047,7 +981,7 @@ def print_help(self): print() print(' -i, --instance Instance ID (default: pki-tomcat).') print(' --type Issuer type: {0}' - .format(', '.join(ISSUER_TYPES.values()))) + .format(', '.join(pki.server.subsystem.ACME_ISSUER_TYPES.values()))) print(' -D= Set property value.') print(' -v, --verbose Run in verbose mode.') print(' --debug Run in debug mode.') @@ -1076,7 +1010,7 @@ def execute(self, argv): elif o == '--type': issuer_type = a - if issuer_type not in ISSUER_TYPES.values(): + if issuer_type not in pki.server.subsystem.ACME_ISSUER_TYPES.values(): raise Exception('Invalid issuer type: {0}'.format(issuer_type)) elif o == '-D': @@ -1107,19 +1041,8 @@ def execute(self, argv): instance.load() - acme_conf_dir = os.path.join(instance.conf_dir, 'acme') - issuer_conf = os.path.join(acme_conf_dir, 'issuer.conf') - config = {} - - if issuer_type: - # if --type is specified, load the issuer.conf template - source = '/usr/share/pki/acme/issuer/{0}/issuer.conf'.format(issuer_type) - else: - # otherwise, load the issuer.conf from the instance - source = issuer_conf - - logger.info('Loading %s', source) - pki.util.load_properties(source, config) + subsystem = pki.server.subsystem.ACMESubsystem(instance) + config = subsystem.get_issuer_config(issuer_type=issuer_type) # if --type or -D is specified, use silent mode if issuer_type or props: @@ -1129,7 +1052,7 @@ def execute(self, argv): logger.info('- %s: %s', name, value) pki.util.set_property(config, name, value) - instance.store_properties(issuer_conf, config) + subsystem.update_issuer_config(config) return # otherwise, use interactive mode @@ -1144,16 +1067,19 @@ def execute(self, argv): print() print( 'Enter the type of the certificate issuer. ' - 'Available types: %s.' % ', '.join(ISSUER_TYPES.values())) - issuer_type = ISSUER_TYPES.get(issuer_class) + 'Available types: %s.' % ', '.join(pki.server.subsystem.ACME_ISSUER_TYPES.values())) + issuer_type = pki.server.subsystem.ACME_ISSUER_TYPES.get(issuer_class) orig_issuer_type = issuer_type issuer_type = pki.util.read_text( ' Issuer Type', - options=ISSUER_TYPES.values(), + options=pki.server.subsystem.ACME_ISSUER_TYPES.values(), default=issuer_type, required=True) - pki.util.set_property(config, 'class', ISSUER_CLASSES.get(issuer_type)) + pki.util.set_property( + config, + 'class', + pki.server.subsystem.ACME_ISSUER_CLASSES.get(issuer_type)) if orig_issuer_type != issuer_type: source = '/usr/share/pki/acme/issuer/{0}/issuer.conf'.format(issuer_type) @@ -1223,7 +1149,7 @@ def execute(self, argv): profile = pki.util.read_text(' Certificate Profile', default=profile, required=True) pki.util.set_property(config, 'profile', profile) - instance.store_properties(issuer_conf, config) + subsystem.update_issuer_config(config) class ACMERealmCLI(pki.cli.CLI): @@ -1298,7 +1224,7 @@ def execute(self, argv): realm_class = config.get('class') - realm_type = REALM_TYPES.get(realm_class) + realm_type = pki.server.subsystem.ACME_REALM_TYPES.get(realm_class) print(' Realm Type: %s' % realm_type) if realm_type == 'in-memory': @@ -1371,7 +1297,7 @@ def print_help(self): print() print(' -i, --instance Instance ID (default: pki-tomcat).') print(' --type Realm type: {0}' - .format(', '.join(REALM_TYPES.values()))) + .format(', '.join(pki.server.subsystem.ACME_REALM_TYPES.values()))) print(' -D= Set property value.') print(' -v, --verbose Run in verbose mode.') print(' --debug Run in debug mode.') @@ -1400,7 +1326,7 @@ def execute(self, argv): elif o == '--type': realm_type = a - if realm_type not in REALM_TYPES.values(): + if realm_type not in pki.server.subsystem.ACME_REALM_TYPES.values(): raise Exception('Invalid realm type: {0}'.format(realm_type)) elif o == '-D': @@ -1431,19 +1357,8 @@ def execute(self, argv): instance.load() - acme_conf_dir = os.path.join(instance.conf_dir, 'acme') - realm_conf = os.path.join(acme_conf_dir, 'realm.conf') - config = {} - - if realm_type: - # if --type is specified, load the realm.conf template - source = '/usr/share/pki/acme/realm/{0}/realm.conf'.format(realm_type) - else: - # otherwise, load the realm.conf from the instance - source = realm_conf - - logger.info('Loading %s', source) - pki.util.load_properties(source, config) + subsystem = pki.server.subsystem.ACMESubsystem(instance) + config = subsystem.get_realm_config(realm_type=realm_type) # if --type or -D is specified, use silent mode if realm_type or props: @@ -1453,7 +1368,7 @@ def execute(self, argv): logger.info('- %s: %s', name, value) pki.util.set_property(config, name, value) - instance.store_properties(realm_conf, config) + subsystem.update_realm_config(config) return # otherwise, use interactive mode @@ -1468,16 +1383,19 @@ def execute(self, argv): print() print( 'Enter the type of the realm. ' - 'Available types: %s.' % ', '.join(REALM_TYPES.values())) - realm_type = REALM_TYPES.get(realm_class) + 'Available types: %s.' % ', '.join(pki.server.subsystem.ACME_REALM_TYPES.values())) + realm_type = pki.server.subsystem.ACME_REALM_TYPES.get(realm_class) orig_realm_type = realm_type realm_type = pki.util.read_text( ' Realm Type', - options=REALM_TYPES.values(), + options=pki.server.subsystem.ACME_REALM_TYPES.values(), default=realm_type, required=True) - pki.util.set_property(config, 'class', REALM_CLASSES.get(realm_type)) + pki.util.set_property( + config, + 'class', + pki.server.subsystem.ACME_REALM_CLASSES.get(realm_type)) if orig_realm_type != realm_type: source = '/usr/share/pki/acme/realm/{0}/realm.conf'.format(realm_type) @@ -1586,4 +1504,4 @@ def execute(self, argv): ' Password', default=password, password=True, required=True) pki.util.set_property(config, 'password', password) - instance.store_properties(realm_conf, config) + subsystem.update_realm_config(config) diff --git a/base/server/python/pki/server/deployment/__init__.py b/base/server/python/pki/server/deployment/__init__.py index 615904f5583..15690956b49 100644 --- a/base/server/python/pki/server/deployment/__init__.py +++ b/base/server/python/pki/server/deployment/__init__.py @@ -5183,10 +5183,198 @@ def remove_selinux_contexts(self): trans.finish() + def create_acme_subsystem(self): + ''' + See also pki-server acme-create. + ''' + + logger.info('Creating ACME subsystem') + + subsystem = pki.server.subsystem.ACMESubsystem(self.instance) + subsystem.create() + + return subsystem + + def configure_acme_database(self, subsystem): + ''' + See also pki-server acme-database-mod. + ''' + + logger.info('Configuring ACME database') + + database_type = self.mdict['acme_database_type'] + props = subsystem.get_database_config(database_type=database_type) + + database_class = pki.server.subsystem.ACME_DATABASE_CLASSES.get(database_type) + pki.util.set_property(props, 'class', database_class) + + if database_type in ['ds', 'ldap', 'openldap']: + + url = self.mdict.get('acme_database_url') + pki.util.set_property(props, 'url', url) + + auth_type = props.get('authType') + auth_type = self.mdict.get('acme_database_auth_type', auth_type) + pki.util.set_property(props, 'authType', auth_type) + + if auth_type == 'BasicAuth': + bind_dn = self.mdict.get('acme_database_bind_dn') + pki.util.set_property(props, 'bindDN', bind_dn) + + bind_password = self.mdict.get('acme_database_bind_password') + pki.util.set_property(props, 'bindPassword', bind_password) + + elif auth_type == 'SslClientAuth': + nickname = self.mdict.get('acme_database_nickname') + pki.util.set_property(props, 'nickname', nickname) + + base_dn = self.mdict.get('acme_database_base_dn') + pki.util.set_property(props, 'baseDN', base_dn) + + elif database_type == 'postgresql': + + url = self.mdict.get('acme_database_url') + pki.util.set_property(props, 'url', url) + + user = self.mdict.get('acme_database_user') + pki.util.set_property(props, 'user', user) + + password = self.mdict.get('acme_database_password') + pki.util.set_property(props, 'password', password) + + subsystem.update_database_config(props) + + def configure_acme_issuer(self, subsystem): + ''' + See also pki-server acme-issuer-mod. + ''' + + logger.info('Configuring ACME issuer') + + issuer_type = self.mdict['acme_issuer_type'] + props = subsystem.get_issuer_config(issuer_type=issuer_type) + + issuer_class = pki.server.subsystem.ACME_ISSUER_CLASSES.get(issuer_type) + pki.util.set_property(props, 'class', issuer_class) + + if issuer_type == 'nss': + + nickname = self.mdict.get('acme_issuer_nickname') + pki.util.set_property(props, 'nickname', nickname) + + extensions = self.mdict.get('acme_issuer_extensions') + pki.util.set_property(props, 'extensions', extensions) + + elif issuer_type == 'pki': + + url = self.mdict.get('acme_issuer_url') + pki.util.set_property(props, 'url', url) + + nickname = self.mdict.get('acme_issuer_nickname') + pki.util.set_property(props, 'nickname', nickname) + + username = self.mdict.get('acme_issuer_username') + pki.util.set_property(props, 'username', username) + + password = self.mdict.get('acme_issuer_password') + pki.util.set_property(props, 'password', password) + + password_file = self.mdict.get('acme_issuer_password_file') + pki.util.set_property(props, 'passwordFile', password_file) + + profile = self.mdict.get('acme_issuer_profile') + pki.util.set_property(props, 'profile', profile) + + subsystem.update_issuer_config(props) + + def configure_acme_realm(self, subsystem): + ''' + See also pki-server acme-realm-mod. + ''' + + logger.info('Configuring ACME realm') + + realm_type = self.mdict['acme_realm_type'] + props = subsystem.get_realm_config(realm_type=realm_type) + + realm_class = pki.server.subsystem.ACME_REALM_CLASSES.get(realm_type) + pki.util.set_property(props, 'class', realm_class) + + if realm_type == 'in-memory': + + username = self.mdict.get('acme_realm_username') + pki.util.set_property(props, 'username', username) + + password = self.mdict.get('acme_realm_password') + pki.util.set_property(props, 'password', password) + + elif realm_type == 'ds': + + url = self.mdict.get('acme_realm_url') + pki.util.set_property(props, 'url', url) + + auth_type = props.get('authType') + auth_type = self.mdict.get('acme_realm_auth_type', auth_type) + pki.util.set_property(props, 'authType', auth_type) + + if auth_type == 'BasicAuth': + bind_dn = self.mdict.get('acme_realm_bind_dn') + pki.util.set_property(props, 'bindDN', bind_dn) + + bind_password = self.mdict.get('acme_realm_bind_password') + pki.util.set_property(props, 'bindPassword', bind_password) + + elif auth_type == 'SslClientAuth': + nickname = self.mdict.get('acme_realm_nickname') + pki.util.set_property(props, 'nickname', nickname) + + users_dn = self.mdict.get('acme_realm_users_dn') + pki.util.set_property(props, 'usersDN', users_dn) + + groups_dn = self.mdict.get('acme_realm_groups_dn') + pki.util.set_property(props, 'groupsDN', groups_dn) + + elif realm_type == 'postgresql': + + url = self.mdict.get('acme_realm_url') + pki.util.set_property(props, 'url', url) + + user = self.mdict.get('acme_realm_user') + pki.util.set_property(props, 'user', user) + + password = self.mdict.get('acme_realm_password') + pki.util.set_property(props, 'password', password) + + subsystem.update_realm_config(props) + + def deploy_acme_webapp(self, subsystem): + ''' + See also pki-server acme-deploy. + ''' + + logger.info('Deploying ACME webapp') + + subsystem.enable(wait=True) + + def spawn_acme(self): + + subsystem = self.create_acme_subsystem() + self.instance.add_subsystem(subsystem) + + self.configure_acme_database(subsystem) + self.configure_acme_issuer(subsystem) + self.configure_acme_realm(subsystem) + + self.deploy_acme_webapp(subsystem) + def spawn(self): print('Installing ' + self.subsystem_type + ' into ' + self.instance.base_dir + '.') + if self.subsystem_type == 'ACME': + self.spawn_acme() + return + scriptlet = pki.server.deployment.scriptlets.initialization.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 34f2cb6a339..5793401436b 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"] +PKI_SUBSYSTEMS = ['CA', 'KRA', 'OCSP', 'TKS', 'TPS', 'ACME'] 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/pkimessages.py b/base/server/python/pki/server/deployment/pkimessages.py index dec464b5ef2..b327c845dab 100644 --- a/base/server/python/pki/server/deployment/pkimessages.py +++ b/base/server/python/pki/server/deployment/pkimessages.py @@ -349,7 +349,7 @@ PKI_CHECK_STATUS_MESSAGE = ''' To check the status of the subsystem: systemctl status pki-tomcatd@%s.service''' -PKI_ACCESS_URL = ''' +PKI_ACCESS_URL = '''\ The URL for the subsystem is: https://%s:%s/%s''' PKI_INSTANCE_RESTART_MESSAGE = ''' diff --git a/base/server/python/pki/server/pkispawn.py b/base/server/python/pki/server/pkispawn.py index 44971cbb3b0..43c76c38d52 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)', - options=['CA', 'KRA', 'OCSP', 'TKS', 'TPS'], + 'Subsystem (CA/KRA/OCSP/TKS/TPS/ACME)', + options=['CA', 'KRA', 'OCSP', 'TKS', 'TPS', 'ACME'], default='CA', case_sensitive=False).upper() print() else: @@ -669,6 +669,9 @@ def main(argv): elif deployer.subsystem_type == 'TPS': print_tps_step_one_information(parser.mdict, deployer.instance) + elif deployer.subsystem_type == 'ACME': + print_acme_install_information() + else: print_final_install_information(parser.mdict, deployer.instance) @@ -682,7 +685,15 @@ def validate_user_deployment_cfg(user_deployment_cfg): line = line.strip() if not line.startswith('['): continue - if line not in ['[DEFAULT]', '[Tomcat]', '[CA]', '[KRA]', '[OCSP]', '[TKS]', '[TPS]']: + if line not in [ + '[DEFAULT]', + '[Tomcat]', + '[CA]', + '[KRA]', + '[OCSP]', + '[TKS]', + '[TPS]', + '[ACME]']: raise Exception('Invalid deployment configuration section: %s' % line) @@ -919,6 +930,7 @@ def print_skip_configuration_information(mdict, instance): print(log.PKI_CHECK_STATUS_MESSAGE % instance.name) print(log.PKI_INSTANCE_RESTART_MESSAGE % instance.name) + print() print(log.PKI_ACCESS_URL % (mdict['pki_hostname'], mdict['pki_https_port'], deployer.subsystem_type.lower())) @@ -929,6 +941,17 @@ def print_skip_configuration_information(mdict, instance): print(log.PKI_SPAWN_INFORMATION_FOOTER) +def print_acme_install_information(): + + print(log.PKI_SPAWN_INFORMATION_HEADER) + + print(log.PKI_ACCESS_URL % (deployer.mdict['pki_hostname'], + deployer.mdict['pki_https_port'], + deployer.subsystem_type.lower())) + + print(log.PKI_SPAWN_INFORMATION_FOOTER) + + def print_final_install_information(mdict, instance): print(log.PKI_SPAWN_INFORMATION_HEADER) @@ -970,6 +993,7 @@ def print_final_install_information(mdict, instance): print(log.PKI_CHECK_STATUS_MESSAGE % instance.name) print(log.PKI_INSTANCE_RESTART_MESSAGE % instance.name) + print() print(log.PKI_ACCESS_URL % (mdict['pki_hostname'], mdict['pki_https_port'], deployer.subsystem_type.lower())) diff --git a/base/server/python/pki/server/subsystem.py b/base/server/python/pki/server/subsystem.py index 9352264e695..dfa5cc28961 100644 --- a/base/server/python/pki/server/subsystem.py +++ b/base/server/python/pki/server/subsystem.py @@ -46,6 +46,34 @@ SELFTEST_CRITICAL = 'critical' +# TODO: auto-populate this map from /usr/share/pki/acme/database +ACME_DATABASE_CLASSES = { + 'ds': 'org.dogtagpki.acme.database.DSDatabase', + 'in-memory': 'org.dogtagpki.acme.database.InMemoryDatabase', + 'ldap': 'org.dogtagpki.acme.database.LDAPDatabase', + 'openldap': 'org.dogtagpki.acme.database.OpenLDAPDatabase', + 'postgresql': 'org.dogtagpki.acme.database.PostgreSQLDatabase' +} + +ACME_DATABASE_TYPES = {value: key for key, value in ACME_DATABASE_CLASSES.items()} + +# TODO: auto-populate this map from /usr/share/pki/acme/issuer +ACME_ISSUER_CLASSES = { + 'nss': 'org.dogtagpki.acme.issuer.NSSIssuer', + 'pki': 'org.dogtagpki.acme.issuer.PKIIssuer' +} + +ACME_ISSUER_TYPES = {value: key for key, value in ACME_ISSUER_CLASSES.items()} + +# TODO: auto-populate this map from /usr/share/pki/acme/realm +ACME_REALM_CLASSES = { + 'ds': 'org.dogtagpki.acme.realm.DSRealm', + 'in-memory': 'org.dogtagpki.acme.realm.InMemoryRealm', + 'postgresql': 'org.dogtagpki.acme.realm.PostgreSQLRealm' +} + +ACME_REALM_TYPES = {value: key for key, value in ACME_REALM_CLASSES.items()} + logger = logging.getLogger(__name__) @@ -2721,6 +2749,114 @@ def __init__(self, instance): super().__init__(instance, 'tps') +class ACMESubsystem(PKISubsystem): + + def __init__(self, instance): + super().__init__(instance, 'acme') + + @property + def database_conf(self): + return os.path.join(self.conf_dir, 'database.conf') + + @property + def issuer_conf(self): + return os.path.join(self.conf_dir, 'issuer.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, 'acme', 'conf') + + self.instance.copy( + os.path.join(default_conf_dir, 'database.conf'), + self.database_conf, + exist_ok=exist_ok, + force=force) + + self.instance.copy( + os.path.join(default_conf_dir, 'issuer.conf'), + self.issuer_conf, + exist_ok=exist_ok, + force=force) + + self.instance.copy( + os.path.join(default_conf_dir, 'realm.conf'), + self.realm_conf, + exist_ok=exist_ok, + force=force) + + def get_database_config(self, database_type=None): + + template_dir = os.path.join(pki.server.PKIServer.SHARE_DIR, 'acme', 'database') + + if database_type: + # if database type is specified, load the database.conf template + database_conf = os.path.join(template_dir, database_type, 'database.conf') + else: + # otherwise, load the current database.conf in the instance + database_conf = self.database_conf + + logger.info('Loading %s', database_conf) + config = {} + pki.util.load_properties(database_conf, config) + + return config + + def update_database_config(self, config): + + logger.info('Updating %s', self.database_conf) + self.instance.store_properties(self.database_conf, config) + + def get_issuer_config(self, issuer_type=None): + + template_dir = os.path.join(pki.server.PKIServer.SHARE_DIR, 'acme', 'issuer') + + if issuer_type: + # if issuer type is specified, load the issuer.conf template + issuer_conf = os.path.join(template_dir, issuer_type, 'issuer.conf') + else: + # otherwise, load the current issuer.conf in the instance + issuer_conf = self.issuer_conf + + logger.info('Loading %s', issuer_conf) + config = {} + pki.util.load_properties(issuer_conf, config) + + return config + + def update_issuer_config(self, config): + + logger.info('Updating %s', self.issuer_conf) + self.instance.store_properties(self.issuer_conf, config) + + def get_realm_config(self, realm_type=None): + + template_dir = os.path.join(pki.server.PKIServer.SHARE_DIR, 'acme', 'realm') + + if realm_type: + # if realm type is specified, load the realm.conf template + realm_conf = os.path.join(template_dir, realm_type, 'realm.conf') + 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) + + class PKISubsystemFactory(object): @classmethod