freeipa/ipatests/test_integration/test_pkinit_install.py
Christian Heimes dbebed2e3a Add PKINIT support to ipa-client-install
The ``ipa-client-install`` command now supports PKINIT for client
enrollment. Existing X.509 client certificates can be used to
authenticate a host.

Also restart KRB5 KDC during ``ipa-certupdate`` so KDC picks up new CA
certificates for PKINIT.

*Requirements*

- The KDC must trust the CA chain of the client certificate.
- The client must be able to verify the KDC's PKINIT cert.
- The host entry must exist. This limitation may be removed in the
  future.
- A certmap rule must match the host certificate and map it to a single
  host entry.

*Example*

```
ipa-client-install \
    --pkinit-identity=FILE:/path/to/cert.pem,/path/to/key.pem \
    --pkinit-anchor=/path/to/kdc-ca-bundle.pem
```

Fixes: https://pagure.io/freeipa/issue/9271
Fixes: https://pagure.io/freeipa/issue/9269
Signed-off-by: Christian Heimes <cheimes@redhat.com>
Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
2022-11-16 14:32:05 +02:00

101 lines
2.9 KiB
Python

#
# Copyright (C) 2022 FreeIPA Contributors see COPYING for license
#
"""
Module provides tests for ipa-client-install with PKINIT
"""
import os
from ipaplatform.paths import paths
from ipatests.test_integration.base import IntegrationTest
from ipatests.pytest_ipa.integration import tasks
class TestPkinitClientInstall(IntegrationTest):
num_clients = 1
certfile = "/etc/pki/tls/certs/client.pem"
keyfile = "/etc/pki/tls/private/client.key"
tmpbundle = "/tmp/kdc-ca-bundle.pme"
@classmethod
def install(cls, mh):
tasks.install_master(cls.master)
def add_certmaperule(self):
"""add certmap rule to map SAN dNSName to host entry"""
self.master.run_command(
[
"ipa",
"certmaprule-add",
"pkinit-host",
"--matchrule=<ISSUER>CN=Certificate Authority,.*",
"--maprule=(fqdn={subject_dns_name})",
]
)
def add_host(self):
"""Add host entry for client
Allow master to manage client so it can create a certificate.
"""
client = self.clients[0]
self.master.run_command(
["ipa", "host-add", "--force", client.hostname]
)
self.master.run_command(
[
"ipa",
"host-add-managedby",
f"--hosts={self.master.hostname}",
client.hostname,
]
)
def create_cert(self):
"""Create and copy certificate for client"""
client = self.clients[0]
self.master.run_command(
[
"mkdir",
"-p",
os.path.dirname(self.certfile),
os.path.dirname(self.keyfile),
]
)
self.master.run_command(
[
"ipa-getcert",
"request",
"-w",
# fmt: off
"-f", self.certfile,
"-k", self.keyfile,
"-N", client.hostname,
"-D", client.hostname,
"-K", f"host/{client.hostname}",
# fmt: on
]
)
# copy cert, key, and bundle to client
for filename in (self.certfile, self.keyfile):
data = self.master.get_file_contents(filename)
client.put_file_contents(filename, data)
cabundle = self.master.get_file_contents(paths.KDC_CA_BUNDLE_PEM)
client.put_file_contents(self.tmpbundle, cabundle)
def test_client_install_pkinit(self):
tasks.kinit_admin(self.master)
self.add_certmaperule()
self.add_host()
self.create_cert()
tasks.install_client(
self.master,
self.clients[0],
pkinit_identity=f"FILE:{self.certfile},{self.keyfile}",
extra_args=[f"--pkinit-anchor=FILE:{self.tmpbundle}"],
)