mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
test_caless: add pkinit option and test it
change "caless-create-pki" so pkinit certificates can be generated. See https://web.mit.edu/kerberos/krb5-1.13/doc/admin/pkinit.html for details. add pkinit option to the ipa installer and test both master and replica install with pkinit. https://pagure.io/freeipa/issue/6854 Signed-off-by: Michal Reznik <mreznik@redhat.com> Reviewed-By: Stanislav Laznicka <slaznick@redhat.com>
This commit is contained in:
committed by
Martin Basti
parent
96ca62f81d
commit
f7c4039e41
@@ -1,14 +1,32 @@
|
||||
#!/bin/bash -e
|
||||
#
|
||||
# Copyright (C) 2017 FreeIPA Contributors see COPYING for license
|
||||
#
|
||||
|
||||
profile_ca=(-t CT,C,C -v 120)
|
||||
profile_server=(-t ,, -v 12)
|
||||
profile_ca_request_options=(-1 -2 -4)
|
||||
profile_ca_request_input="\$'0\n1\n5\n6\n9\ny\ny\n\ny\n1\n7\nfile://'\$(readlink -f \$dbdir)/\$ca.crl\$'\n-1\n-1\n-1\nn\nn\n'"
|
||||
profile_ca_create_options=(-v 120)
|
||||
profile_ca_add_options=(-t CT,C,C)
|
||||
profile_server_request_options=(-4)
|
||||
profile_server_request_input="\$'1\n7\nfile://'\$(readlink -f \$dbdir)/\$ca.crl\$'\n-1\n-1\n-1\nn\nn\n'"
|
||||
profile_server_create_options=(-v 12)
|
||||
profile_server_add_options=(-t ,,)
|
||||
|
||||
crl_path=${crl_path-$(readlink -f $dbdir)}
|
||||
write_chain() {
|
||||
local nick="$1"
|
||||
|
||||
serial_number=0
|
||||
chain=`certutil -O -d $dbdir -n "$nick" |
|
||||
sed -e '/^\s*$/d' -e "s/\s*\"\(.*\)\" \[.*/\1/g"`
|
||||
|
||||
while read -r name; do
|
||||
# OpenSSL requires a reverse order to what we get from NSS
|
||||
echo -e "`certutil -L -d "$dbdir" -n "$name" -a`\n`cat $dbdir/$nick.pem`
|
||||
" > "$dbdir/$nick.pem"
|
||||
done <<< "$chain"
|
||||
}
|
||||
|
||||
gen_cert() {
|
||||
local profile="$1" nick="$2" subject="$3" ca options pwfile noise csr crt
|
||||
local profile="$1" nick="$2" subject="$3" ca request_options request_input create_options serial add_options pwfile noise csr crt
|
||||
shift 3
|
||||
|
||||
echo "gen_cert(profile=$profile nick=$nick subject=$subject)"
|
||||
@@ -18,13 +36,20 @@ gen_cert() {
|
||||
ca="$nick"
|
||||
fi
|
||||
|
||||
eval "options=(\"\${profile_$profile[@]}\")"
|
||||
eval "request_options=(\"\${profile_${profile}_request_options[@]}\")"
|
||||
eval "eval request_input=\"\${profile_${profile}_request_input}\""
|
||||
|
||||
eval "create_options=(\"\${profile_${profile}_create_options[@]}\")"
|
||||
if [ "$ca" = "$nick" ]; then
|
||||
options=("${options[@]}" -x -m 1)
|
||||
create_options=("${create_options[@]}" -x -m 1)
|
||||
else
|
||||
options=("${options[@]}" -c "$ca")
|
||||
eval "serial_${ca//\//_}=\$((\${serial_${ca//\//_}:-1}+1))"
|
||||
eval "serial=\$serial_${ca//\//_}"
|
||||
create_options=("${create_options[@]}" -c "$ca" -m "$serial")
|
||||
fi
|
||||
|
||||
eval "add_options=(\"\${profile_${profile}_add_options[@]}\")"
|
||||
|
||||
pwfile="$(mktemp)"
|
||||
echo "$dbpassword" >"$pwfile"
|
||||
|
||||
@@ -38,22 +63,14 @@ gen_cert() {
|
||||
|
||||
csr="$(mktemp)"
|
||||
crt="$(mktemp)"
|
||||
certutil -R -d "$dbdir" -s "$subject" -f "$pwfile" -z "$noise" -o "$csr" -4 -2 >/dev/null <<EOF
|
||||
y
|
||||
0
|
||||
N
|
||||
1
|
||||
7
|
||||
file://$crl_path/$ca.crl
|
||||
-1
|
||||
-1
|
||||
-1
|
||||
n
|
||||
n
|
||||
EOF
|
||||
serial_number=$(($serial_number+1))
|
||||
certutil -C -d "$dbdir" -f "$pwfile" -m "$serial_number" -i "$csr" -o "$crt" "${options[@]}" "$@"
|
||||
certutil -A -d "$dbdir" -n "$nick" -f "$pwfile" -i "$crt" "${options[@]}"
|
||||
|
||||
certutil -R -d "$dbdir" -s "$subject" -f "$pwfile" -z "$noise" -o "$csr" "${request_options[@]}" >/dev/null <<<"$request_input"
|
||||
certutil -C -d "$dbdir" -f "$pwfile" -i "$csr" -o "$crt" "${create_options[@]}" "$@"
|
||||
certutil -A -d "$dbdir" -n "$nick" -f "$pwfile" -i "$crt" "${add_options[@]}"
|
||||
|
||||
mkdir -p "$(dirname $dbdir/$nick.pem)"
|
||||
write_chain "$nick"
|
||||
pk12util -o "$dbdir/$nick.p12" -n "$nick" -d "$dbdir" -k "$pwfile" -w "$pwfile"
|
||||
|
||||
rm -f "$pwfile" "$noise" "$csr" "$crt"
|
||||
}
|
||||
@@ -102,6 +119,49 @@ gen_server_certs() {
|
||||
revoke_cert "$nick-revoked"
|
||||
}
|
||||
|
||||
gen_pkinit_extensions() {
|
||||
echo "[kdc_cert]
|
||||
basicConstraints=CA:FALSE
|
||||
keyUsage=nonRepudiation,digitalSignature,keyEncipherment,keyAgreement
|
||||
extendedKeyUsage=TLS Web Server Authentication, 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:${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:${realm}" > "$dbdir/ext.kdc"
|
||||
}
|
||||
|
||||
gen_pkinit_cert() {
|
||||
local nick="$1" subj="$2" outname="$3"
|
||||
shift 3
|
||||
|
||||
openssl genrsa -out "$dbdir/$nick/kdc.key" 2048 > /dev/null
|
||||
openssl req -new -out "$dbdir/$nick/kdc.req" -key "$dbdir/$nick/kdc.key" \
|
||||
-subj "$subj"
|
||||
|
||||
openssl pkcs12 -in "$dbdir/$nick.p12" -passin "pass:$dbpassword" \
|
||||
-nodes -nocerts -out "$dbdir/$nick.key" > /dev/null
|
||||
|
||||
openssl x509 -req -in "$dbdir/$nick/kdc.req" \
|
||||
-CAkey "$dbdir/$nick.key" -CA "$dbdir/$nick.pem" \
|
||||
-out "$dbdir/$nick/kdc.crt" -days 365 \
|
||||
-extfile "$dbdir/ext.kdc" -extensions kdc_cert -CAcreateserial > /dev/null
|
||||
|
||||
rm "$dbdir/$nick/kdc.req"
|
||||
|
||||
openssl pkcs12 -export -in "$dbdir/$nick/kdc.crt" \
|
||||
-inkey "$dbdir/$nick/kdc.key" -password "pass:$dbpassword" \
|
||||
-out "$dbdir/$nick/$outname.p12" -chain -CAfile "$dbdir/$nick.pem"
|
||||
}
|
||||
|
||||
gen_subtree() {
|
||||
local nick="$1" org="$2"
|
||||
shift 2
|
||||
@@ -110,6 +170,8 @@ gen_subtree() {
|
||||
|
||||
gen_cert ca "$nick" "CN=CA,O=$org" "$@"
|
||||
gen_cert server "$nick/wildcard" "CN=*.$domain,O=$org"
|
||||
gen_pkinit_cert "$nick" "/O=$realm/CN=$server1" "pkinit-server"
|
||||
gen_pkinit_cert "$nick" "/O=$realm/CN=$server2" "pkinit-replica"
|
||||
gen_server_certs "$nick/server" "$server1" "$org"
|
||||
gen_server_certs "$nick/replica" "$server2" "$org"
|
||||
gen_server_certs "$nick/client" "$client" "$org"
|
||||
@@ -117,6 +179,7 @@ gen_subtree() {
|
||||
|
||||
gen_cert server server-selfsign "CN=$server1,O=Self-signed"
|
||||
gen_cert server replica-selfsign "CN=$server2,O=Self-signed"
|
||||
gen_pkinit_extensions
|
||||
gen_cert server noca "CN=$server1,O=No-CA"
|
||||
gen_subtree ca1 'Example Organization'
|
||||
gen_subtree ca1/subca 'Subsidiary Example Organization'
|
||||
|
||||
@@ -63,11 +63,11 @@ def ipa_certs_cleanup(host):
|
||||
raiseonerr=False)
|
||||
# A workaround for https://fedorahosted.org/freeipa/ticket/4639
|
||||
result = host.run_command(['certutil', '-L', '-d',
|
||||
paths.HTTPD_ALIAS_DIR])
|
||||
paths.HTTPD_ALIAS_DIR], raiseonerr=False)
|
||||
for rawcert in result.stdout_text.split('\n')[4: -1]:
|
||||
cert = rawcert.split(' ')[0]
|
||||
host.run_command(['certutil', '-D', '-d', paths.HTTPD_ALIAS_DIR,
|
||||
'-n', cert])
|
||||
'-n', cert], raiseonerr=False)
|
||||
|
||||
|
||||
def server_install_teardown(func):
|
||||
@@ -125,10 +125,12 @@ class CALessBase(IntegrationTest):
|
||||
client_hostname = 'unused-client.test'
|
||||
cls.env = {
|
||||
'domain': cls.master.domain.name,
|
||||
'realm': cls.master.domain.name.upper(),
|
||||
'server1': cls.master.hostname,
|
||||
'server2': replica_hostname,
|
||||
'client': client_hostname,
|
||||
'dbdir': 'nssdb',
|
||||
'dbpassword': cls.cert_password,
|
||||
'crl_path': cls.crl_path,
|
||||
'dirman_password': cls.master.config.dirman_password,
|
||||
}
|
||||
@@ -156,8 +158,9 @@ class CALessBase(IntegrationTest):
|
||||
def install_server(cls, host=None,
|
||||
http_pkcs12='server.p12', dirsrv_pkcs12='server.p12',
|
||||
http_pkcs12_exists=True, dirsrv_pkcs12_exists=True,
|
||||
http_pin=_DEFAULT, dirsrv_pin=_DEFAULT,
|
||||
root_ca_file='root.pem', unattended=True,
|
||||
http_pin=_DEFAULT, dirsrv_pin=_DEFAULT, pkinit_pin=None,
|
||||
root_ca_file='root.pem', pkinit_pkcs12_exists=False,
|
||||
pkinit_pkcs12='pkinit-server.p12', unattended=True,
|
||||
stdin_text=None):
|
||||
"""Install a CA-less server
|
||||
|
||||
@@ -165,16 +168,29 @@ class CALessBase(IntegrationTest):
|
||||
"""
|
||||
if host is None:
|
||||
host = cls.master
|
||||
|
||||
extra_args = ['--http-cert-file', http_pkcs12,
|
||||
'--dirsrv-cert-file', dirsrv_pkcs12,
|
||||
'--ca-cert-file', root_ca_file,
|
||||
'--ip-address', host.ip]
|
||||
|
||||
if http_pin is _DEFAULT:
|
||||
http_pin = cls.cert_password
|
||||
if dirsrv_pin is _DEFAULT:
|
||||
dirsrv_pin = cls.cert_password
|
||||
if pkinit_pin is _DEFAULT:
|
||||
pkinit_pin = cls.cert_password
|
||||
tasks.prepare_host(host)
|
||||
files_to_copy = ['root.pem']
|
||||
if http_pkcs12_exists:
|
||||
files_to_copy.append(http_pkcs12)
|
||||
if dirsrv_pkcs12_exists:
|
||||
files_to_copy.append(dirsrv_pkcs12)
|
||||
|
||||
if pkinit_pkcs12_exists:
|
||||
extra_args.extend(['--pkinit-cert-file', pkinit_pkcs12])
|
||||
else:
|
||||
extra_args.append('--no-pkinit')
|
||||
for filename in set(files_to_copy):
|
||||
cls.copy_cert(host, filename)
|
||||
|
||||
@@ -183,15 +199,12 @@ class CALessBase(IntegrationTest):
|
||||
host.run_command(args + ["ca1"], raiseonerr=False)
|
||||
host.run_command(args + ["ca1/server"], raiseonerr=False)
|
||||
|
||||
extra_args = ['--http-cert-file', http_pkcs12,
|
||||
'--dirsrv-cert-file', dirsrv_pkcs12,
|
||||
'--ca-cert-file', root_ca_file,
|
||||
'--ip-address', host.ip]
|
||||
|
||||
if http_pin is not None:
|
||||
extra_args.extend(['--http-pin', http_pin])
|
||||
if dirsrv_pin is not None:
|
||||
extra_args.extend(['--dirsrv-pin', dirsrv_pin])
|
||||
if pkinit_pin is not None:
|
||||
extra_args.extend(['--pkinit-pin', dirsrv_pin])
|
||||
return tasks.install_master(host, extra_args=extra_args,
|
||||
unattended=unattended,
|
||||
stdin_text=stdin_text,
|
||||
@@ -201,12 +214,19 @@ class CALessBase(IntegrationTest):
|
||||
def copy_cert(cls, host, filename):
|
||||
host.transport.put_file(os.path.join(cls.cert_dir, filename),
|
||||
os.path.join(host.config.test_dir, filename))
|
||||
@classmethod
|
||||
def copy_pkinit_cert(cls, host, pkinit_nick):
|
||||
filename = pkinit_nick.split('/')[-1]
|
||||
host.transport.put_file(os.path.join(cls.cert_dir, 'nssdb', pkinit_nick),
|
||||
os.path.join(host.config.test_dir, filename))
|
||||
|
||||
|
||||
def prepare_replica(self, _replica_number=0, replica=None, master=None,
|
||||
http_pkcs12='replica.p12', dirsrv_pkcs12='replica.p12',
|
||||
http_pkcs12_exists=True, dirsrv_pkcs12_exists=True,
|
||||
http_pin=_DEFAULT, dirsrv_pin=_DEFAULT,
|
||||
root_ca_file='root.pem', unattended=True,
|
||||
http_pin=_DEFAULT, dirsrv_pin=_DEFAULT, pkinit_pin=None,
|
||||
root_ca_file='root.pem', pkinit_pkcs12_exists=False,
|
||||
pkinit_pkcs12='pkinit-replica.p12', unattended=True,
|
||||
stdin_text=None, domain_level=None):
|
||||
"""Prepare a CA-less replica
|
||||
|
||||
@@ -223,6 +243,9 @@ class CALessBase(IntegrationTest):
|
||||
http_pin = self.cert_password
|
||||
if dirsrv_pin is _DEFAULT:
|
||||
dirsrv_pin = self.cert_password
|
||||
if pkinit_pin is _DEFAULT:
|
||||
pkinit_pin = self.cert_password
|
||||
|
||||
if domain_level is None:
|
||||
domain_level = tasks.domainlevel(master)
|
||||
files_to_copy = ['root.pem']
|
||||
@@ -250,11 +273,18 @@ class CALessBase(IntegrationTest):
|
||||
extra_args.extend(['--http-cert-file', http_pkcs12])
|
||||
if dirsrv_pkcs12_exists:
|
||||
extra_args.extend(['--dirsrv-cert-file', dirsrv_pkcs12])
|
||||
if pkinit_pkcs12_exists and domain_level != DOMAIN_LEVEL_0:
|
||||
extra_args.extend(['--pkinit-cert-file', pkinit_pkcs12])
|
||||
else:
|
||||
extra_args.append('--no-pkinit')
|
||||
|
||||
if http_pin is not None:
|
||||
extra_args.extend(['--http-pin', http_pin])
|
||||
if dirsrv_pin is not None:
|
||||
extra_args.extend(['--dirsrv-pin', dirsrv_pin])
|
||||
if pkinit_pin is not None:
|
||||
extra_args.extend(['--pkinit-pin', dirsrv_pin])
|
||||
|
||||
if domain_level == DOMAIN_LEVEL_0:
|
||||
result = tasks.replica_prepare(master, replica,
|
||||
extra_args=extra_args,
|
||||
@@ -1468,3 +1498,27 @@ class TestCertinstall(CALessBase):
|
||||
result = self.certinstall('d', 'ca1/server',
|
||||
args=args, stdin_text=stdin_text)
|
||||
assert_error(result, "no such option: --dirsrv-pin")
|
||||
|
||||
|
||||
class TestPKINIT(CALessBase):
|
||||
num_replicas = 1
|
||||
|
||||
@classmethod
|
||||
def install(cls, mh):
|
||||
super(TestPKINIT, cls).install(mh)
|
||||
cls.export_pkcs12('ca1/server')
|
||||
cls.copy_pkinit_cert(cls.master, 'ca1/pkinit-server.p12')
|
||||
with open(cls.pem_filename, 'w') as f:
|
||||
f.write(cls.get_pem('ca1'))
|
||||
result = cls.install_server(pkinit_pkcs12_exists=True,
|
||||
pkinit_pin=_DEFAULT)
|
||||
assert result.returncode == 0
|
||||
|
||||
@replica_install_teardown
|
||||
def test_server_replica_install_pkinit(self):
|
||||
self.export_pkcs12('ca1/replica', filename='replica.p12')
|
||||
self.copy_pkinit_cert(self.replicas[0], 'ca1/pkinit-replica.p12')
|
||||
result = self.prepare_replica(pkinit_pkcs12_exists=True,
|
||||
pkinit_pin=_DEFAULT)
|
||||
assert result.returncode == 0
|
||||
self.verify_installation()
|
||||
|
||||
Reference in New Issue
Block a user