diff --git a/roles/ipaserver/library/ipaserver_set_ds_password.py b/roles/ipaserver/library/ipaserver_set_ds_password.py index 007730241ed22b3d63bf728b588e89880cde7e4e..4b5b3b35ee3994aca8d69dc609bd82af16e4e309 100644 --- a/roles/ipaserver/library/ipaserver_set_ds_password.py +++ b/roles/ipaserver/library/ipaserver_set_ds_password.py @@ -127,7 +127,7 @@ def main(): no_hbac_allow=dict(required=False, type='bool', default=False), no_pkinit=dict(required=False, type='bool', default=False), dirsrv_config_file=dict(required=False), - _dirsrv_pkcs12_info=dict(required=False), + _dirsrv_pkcs12_info=dict(required=False, type='list'), # ssl certificate dirsrv_cert_files=dict(required=False, type='list', default=[]), subject_base=dict(required=False), diff --git a/roles/ipaserver/library/ipaserver_setup_ca.py b/roles/ipaserver/library/ipaserver_setup_ca.py index faaf66018a7cbffcde3ead96d53fac88af258473..42b81c0a952875d5ecb76bdf0c2b7073657d7e2e 100644 --- a/roles/ipaserver/library/ipaserver_setup_ca.py +++ b/roles/ipaserver/library/ipaserver_setup_ca.py @@ -191,7 +191,7 @@ def main(): no_pkinit=dict(required=False, type='bool', default=False), dirsrv_config_file=dict(required=False), dirsrv_cert_files=dict(required=False, type='list'), - _dirsrv_pkcs12_info=dict(required=False), + _dirsrv_pkcs12_info=dict(required=False, type='list'), # certificate system external_ca=dict(required=False, type='bool', default=False), external_ca_type=dict(required=False), @@ -322,18 +322,20 @@ def main(): csr_generated=True) else: # Put the CA cert where other instances expect it - x509.write_certificate(options._http_ca_cert, paths.IPA_CA_CRT) + with open(paths.IPA_CA_CRT, "w") as http_ca_cert_file: + http_ca_cert_file.write(options._http_ca_cert) os.chmod(paths.IPA_CA_CRT, 0o444) if not options.no_pkinit: - x509.write_certificate(options._http_ca_cert, - paths.KDC_CA_BUNDLE_PEM) + with open(paths.KDC_CA_BUNDLE_PEM, "w") as http_ca_cert_file: + http_ca_cert_file.write(options._http_ca_cert) else: with open(paths.KDC_CA_BUNDLE_PEM, 'w'): pass os.chmod(paths.KDC_CA_BUNDLE_PEM, 0o444) - x509.write_certificate(options._http_ca_cert, paths.CA_BUNDLE_PEM) + with open(paths.CA_BUNDLE_PEM, "w") as http_ca_cert_file: + http_ca_cert_file.write(options._http_ca_cert) os.chmod(paths.CA_BUNDLE_PEM, 0o444) with redirect_stdout(ansible_log): diff --git a/roles/ipaserver/library/ipaserver_setup_ds.py b/roles/ipaserver/library/ipaserver_setup_ds.py index fc49d62a246bcd23b12e7bdade8a3c0243244f00..3fc9d50ad2ceb3a6ba02d4f232b3021f97395346 100644 --- a/roles/ipaserver/library/ipaserver_setup_ds.py +++ b/roles/ipaserver/library/ipaserver_setup_ds.py @@ -126,7 +126,7 @@ def main(): dirsrv_config_file=dict(required=False), # ssl certificate dirsrv_cert_files=dict(required=False, type='list', default=[]), - _dirsrv_pkcs12_info=dict(required=False), + _dirsrv_pkcs12_info=dict(required=False, type='list'), # certificate system external_cert_files=dict(required=False, type='list', default=[]), subject_base=dict(required=False), diff --git a/roles/ipaserver/library/ipaserver_setup_http.py b/roles/ipaserver/library/ipaserver_setup_http.py index f5479f5d152250a565fef71841aa21c02092ff54..4d9a54d6585f634c6850b5af321e1b85434da6fa 100644 --- a/roles/ipaserver/library/ipaserver_setup_http.py +++ b/roles/ipaserver/library/ipaserver_setup_http.py @@ -199,8 +199,8 @@ def main(): # _update_hosts_file=dict(required=False, type='bool', # default=False), - _dirsrv_pkcs12_info=dict(required=False), - _http_pkcs12_info=dict(required=False), + _dirsrv_pkcs12_info=dict(required=False, type='list'), + _http_pkcs12_info=dict(required=False, type='list'), ), ) diff --git a/roles/ipaserver/library/ipaserver_setup_krb.py b/roles/ipaserver/library/ipaserver_setup_krb.py index d86714672cff3864943aacaacb02a27ebcb212e2..1101d8d0cdf178583857b5deadac5179abccd351 100644 --- a/roles/ipaserver/library/ipaserver_setup_krb.py +++ b/roles/ipaserver/library/ipaserver_setup_krb.py @@ -160,7 +160,7 @@ def main(): no_reverse=dict(required=False, type='bool', default=False), auto_forwarders=dict(required=False, type='bool', default=False), - _pkinit_pkcs12_info=dict(required=False), + _pkinit_pkcs12_info=dict(required=False, type='list'), ), ) diff --git a/roles/ipaserver/library/ipaserver_test.py b/roles/ipaserver/library/ipaserver_test.py index 71afabcf6e7ee4b18ef0eb631e77af26da7ff9b7..4bbc5b55182205d057aeeed296f8ad32ba6fcf3d 100644 --- a/roles/ipaserver/library/ipaserver_test.py +++ b/roles/ipaserver/library/ipaserver_test.py @@ -967,37 +967,25 @@ def main(): if options.http_pin is None: ansible_module.fail_json( msg="Apache Server private key unlock password required") - http_pkcs12_file, http_pin, http_ca_cert = load_pkcs12( - cert_files=options.http_cert_files, - key_password=options.http_pin, - key_nickname=options.http_cert_name, - ca_cert_files=options.ca_cert_files, - host_name=host_name) - http_pkcs12_info = (http_pkcs12_file.name, http_pin) + http_pkcs12_info = [options.http_cert_files[0], options.http_pin] + with open(options.ca_cert_files[0]) as http_ca_cert_file: + http_ca_cert = http_ca_cert_file.read() if options.dirsrv_cert_files: if options.dirsrv_pin is None: ansible_module.fail_json( msg="Directory Server private key unlock password required") - dirsrv_pkcs12_file, dirsrv_pin, dirsrv_ca_cert = load_pkcs12( - cert_files=options.dirsrv_cert_files, - key_password=options.dirsrv_pin, - key_nickname=options.dirsrv_cert_name, - ca_cert_files=options.ca_cert_files, - host_name=host_name) - dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin) + dirsrv_pkcs12_info = [options.dirsrv_cert_files[0], options.dirsrv_pin] + with open(options.ca_cert_files[0]) as dirsrv_ca_cert_file: + dirsrv_ca_cert = dirsrv_ca_cert_file.read() if options.pkinit_cert_files: if options.pkinit_pin is None: ansible_module.fail_json( msg="Kerberos KDC private key unlock password required") - pkinit_pkcs12_file, pkinit_pin, pkinit_ca_cert = load_pkcs12( - cert_files=options.pkinit_cert_files, - key_password=options.pkinit_pin, - key_nickname=options.pkinit_cert_name, - ca_cert_files=options.ca_cert_files, - realm_name=realm_name) - pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin) + pkinit_pkcs12_info = [options.pkinit_cert_files[0], options.pkinit_pin] + with open(options.ca_cert_files[0]) as pkinit_ca_cert_file: + pkinit_ca_cert = pkinit_ca_cert_file.read() if options.http_cert_files and options.dirsrv_cert_files and \ http_ca_cert != dirsrv_ca_cert: diff --git a/roles/ipaserver/tasks/install.yml b/roles/ipaserver/tasks/install.yml index 85df9a7dd92610a133be9dffc92aef4629837cfe..343ce2a6739585d8e5297b9b95e21a128b293ebd 100644 --- a/roles/ipaserver/tasks/install.yml +++ b/roles/ipaserver/tasks/install.yml @@ -286,6 +286,7 @@ reverse_zones: "{{ result_ipaserver_prepare.reverse_zones }}" no_reverse: "{{ ipaserver_no_reverse }}" auto_forwarders: "{{ ipaserver_auto_forwarders }}" + _http_ca_cert: "{{ result_ipaserver_test._http_ca_cert }}" register: result_ipaserver_setup_ca - name: Copy /root/ipa.csr to "{{ inventory_hostname }}-ipa.csr" diff --git a/tests/ca-less/certificates/pkinit/extensions.conf b/tests/ca-less/certificates/pkinit/extensions.conf new file mode 100644 index 0000000000000000000000000000000000000000..cbff73bef1ed6cf35caf01ec8347627155983b27 --- /dev/null +++ b/tests/ca-less/certificates/pkinit/extensions.conf @@ -0,0 +1,20 @@ +[kdc_cert] +basicConstraints=CA:FALSE +keyUsage=nonRepudiation,digitalSignature,keyEncipherment,keyAgreement +extendedKeyUsage=1.3.6.1.5.2.3.5 +subjectKeyIdentifier=hash +authorityKeyIdentifier=keyid,issuer +issuerAltName=issuer:copy +subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:kdc_princ_name + +[kdc_princ_name] +realm=EXP:0,GeneralString:${ENV::REALM} +principal_name=EXP:1,SEQUENCE:kdc_principal_seq + +[kdc_principal_seq] +name_type=EXP:0,INTEGER:1 +name_string=EXP:1,SEQUENCE:kdc_principals + +[kdc_principals] +princ1=GeneralString:krbtgt +princ2=GeneralString:${ENV::REALM} diff --git a/tests/ca-less/generate-certificates.sh b/tests/ca-less/generate-certificates.sh new file mode 100755 index 0000000000000000000000000000000000000000..5fcf3b554c6336f29b93379e90bb62b2419ae637 --- /dev/null +++ b/tests/ca-less/generate-certificates.sh @@ -0,0 +1,129 @@ +#!/usr/bin/env bash + +ROOT_CA_DIR="certificates/root-ca" +DIRSRV_CERTS_DIR="certificates/dirsrv" +HTTPD_CERTS_DIR="certificates/httpd" +PKINIT_CERTS_DIR="certificates/pkinit" +PKCS12_PASSWORD="SomePKCS12password" + +# generate_ipa_pkcs12_certificate \ +# $cert_name $ipa_fqdn $certs_dir $root_ca_cert $root_ca_private_key extensions_file extensions_name +function generate_ipa_pkcs12_certificate { + + cert_name=$1 + ipa_fqdn=$2 + certs_dir=$3 + root_ca_cert=$4 + root_ca_private_key=$5 + extensions_file=$6 + extensions_name=$7 + + # Generate CSR and private key + openssl req -new -newkey rsa:4096 -nodes \ + -subj "/C=US/ST=Test/L=Testing/O=Default/CN=${ipa_fqdn}" \ + -keyout ${certs_dir}/private.key \ + -out ${certs_dir}/request.csr + + # Sign CSR to generate PEM certificate + if [ -z "${extensions_file}" ]; then + openssl x509 -req -days 365 -sha256 \ + -CAcreateserial \ + -CA ${root_ca_cert} \ + -CAkey ${root_ca_private_key} \ + -in ${certs_dir}/request.csr \ + -out ${certs_dir}/cert.pem + else + openssl x509 -req -days 365 -sha256 \ + -CAcreateserial \ + -CA ${ROOT_CA_DIR}/cert.pem \ + -CAkey ${ROOT_CA_DIR}/private.key \ + -extfile ${extensions_file} \ + -extensions ${extensions_name} \ + -in ${certs_dir}/request.csr \ + -out ${certs_dir}/cert.pem + fi + + # Convert certificate to PKCS12 format + openssl pkcs12 -export \ + -name ${cert_name} \ + -certfile ${root_ca_cert} \ + -in ${certs_dir}/cert.pem \ + -inkey ${certs_dir}/private.key \ + -passout "pass:${PKCS12_PASSWORD}" \ + -out ${certs_dir}/cert.p12 +} + +master=$1 +if [ -z "$master" ]; then + echo "ERROR: master is not set" + echo + echo "usage: $0 master-fqdn replica-fqdn domain" + exit 0; +fi + +replica=$2 +if [ -z "$master" ]; then + echo "ERROR: replica is not set" + echo + echo "usage: $0 master-fqdn replica-fqdn domain" + exit 0; +fi + +domain=$3 +if [ -z "$domain" ]; then + echo "ERROR: domain is not set" + echo + echo "usage: $0 master-fqdn replica-fqdn domain" + exit 0; +fi + +# Generate root CA +if [ ! -f "${ROOT_CA_DIR}/cert.pem" ]; then + openssl genrsa \ + -out ${ROOT_CA_DIR}/private.key 4096 + + openssl req -new -x509 -sha256 -nodes -days 3650 \ + -subj "/C=US/ST=Test/L=Testing/O=Default" \ + -key ${ROOT_CA_DIR}/private.key \ + -out ${ROOT_CA_DIR}/cert.pem +fi + +# [ipaserver] Generate a certificate for the Directory Server +if [ ! -f "${DIRSRV_CERTS_DIR}/ipaserver/cert.p12" ]; then + generate_ipa_pkcs12_certificate \ + "dirsrv-cert" \ + $master \ + "${DIRSRV_CERTS_DIR}/ipaserver" \ + "${ROOT_CA_DIR}/cert.pem" \ + "${ROOT_CA_DIR}/private.key" +else + echo "[ipaserver] Certificate for the Directory Server already exists." +fi + +# [ipaserver] Generate a certificate for the Apache server +if [ ! -f "${HTTPD_CERTS_DIR}/ipaserver/cert.p12" ]; then + generate_ipa_pkcs12_certificate \ + "httpd-cert" \ + $master \ + "${HTTPD_CERTS_DIR}/ipaserver" \ + "${ROOT_CA_DIR}/cert.pem" \ + "${ROOT_CA_DIR}/private.key" +else + echo "[ipaserver] Certificate for the Apache server already exists." +fi + +# [ipaserver] Generate a certificate for the KDC PKINIT +if [ ! -f "${PKINIT_CERTS_DIR}/ipaserver/cert.p12" ]; then + export REALM=${domain^^} + + generate_ipa_pkcs12_certificate \ + "pkinit-cert" \ + $master \ + "${PKINIT_CERTS_DIR}/ipaserver" \ + "${ROOT_CA_DIR}/cert.pem" \ + "${ROOT_CA_DIR}/private.key" \ + "${PKINIT_CERTS_DIR}/extensions.conf" \ + "kdc_cert" +else + echo "[ipaserver] Certificate for the KDC PKINIT already exists." +fi \ No newline at end of file diff --git a/tests/ca-less/install_server_without_ca.yml b/tests/ca-less/install_server_without_ca.yml new file mode 100644 index 0000000000000000000000000000000000000000..bf04e504655a2551137e1b1c80047e89fe5132d5 --- /dev/null +++ b/tests/ca-less/install_server_without_ca.yml @@ -0,0 +1,39 @@ +--- +- name: Test ipaserver installation without CA + hosts: ipaserver + become: true + vars: + # Root CA certificate + ipaserver_ca_cert_files: + - /root/freeipa/certificates/root-ca.crt + # Directory server certificates + ipaserver_dirsrv_cert_name: dirsrv-cert + ipaserver_dirsrv_cert_files: + - /root/freeipa/certificates/dirsrv.p12 + ipaserver_dirsrv_pin: SomePKCS12password + # Apache certificates + ipaserver_http_cert_name: httpd-cert + ipaserver_http_cert_files: + - /root/freeipa/certificates/httpd.p12 + ipaserver_http_pin: SomePKCS12password + # PKINIT configuration + ipaserver_no_pkinit: no + ipaserver_pkinit_cert_name: pkinit-cert + ipaserver_pkinit_cert_files: + - /root/freeipa/certificates/pkinit.p12 + ipaserver_pkinit_pin: SomePKCS12password + pre_tasks: + - name: Copy certificates + copy: + src: "{{ playbook_dir }}/certificates/{{ item }}/ipaserver/cert.p12" + dest: "/root/freeipa/certificates/{{ item }}.p12" + owner: root + group: root + mode: "0644" + with_items: + - dirsrv + - httpd + - pkinit + roles: + - role: ipaserver + state: present \ No newline at end of file diff --git a/tests/ca-less/inventory b/tests/ca-less/inventory new file mode 100644 index 0000000000000000000000000000000000000000..bf1df32cd7c4ff84379edea458079ef9abf00657 --- /dev/null +++ b/tests/ca-less/inventory @@ -0,0 +1,10 @@ +[ipaserver] +ipaserver.test.local + +[ipaserver:vars] +ipaserver_domain=test.local +ipaserver_realm=TEST.LOCAL +ipaadmin_password=SomeADMINpassword +ipadm_password=SomeDMpassword +ipaserver_install_packages=yes +ipaserver_setup_dns=no \ No newline at end of file