mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Fixed KRA backend.
The KRA backend has been simplified since most of the tasks have been moved somewhere else. The transport certificate will be installed on the client, and it is not needed by KRA backend. The KRA agent's PEM certificate is now generated during installation due to permission issue. The kra_host() for now is removed since the current ldap_enable() cannot register the KRA service, so it is using the kra_host environment variable. The KRA installer has been modified to use Dogtag's CLI to create KRA agent and setup the client authentication. The proxy settings have been updated to include KRA's URLs. Some constants have been renamed for clarity. The DOGTAG_AGENT_P12 has been renamed to DOGTAG_ADMIN_P12 since file actually contains the Dogtag admin's certificate and private key and it can be used to access both CA and KRA. The DOGTAG_AGENT_PEM has been renamed to KRA_AGENT_PEM since it can only be used for KRA. The Dogtag dependency has been updated to 10.2.1-0.1. https://fedorahosted.org/freeipa/ticket/4503 Reviewed-By: Petr Viktorin <pviktori@redhat.com>
This commit is contained in:
parent
e7edac30a1
commit
0b08043c37
@ -130,8 +130,8 @@ Requires(post): systemd-units
|
||||
Requires: selinux-policy >= %{selinux_policy_version}
|
||||
Requires(post): selinux-policy-base
|
||||
Requires: slapi-nis >= 0.54-1
|
||||
Requires: pki-ca >= 10.2.0-3
|
||||
Requires: pki-kra >= 10.2.0
|
||||
Requires: pki-ca >= 10.2.1-0.1
|
||||
Requires: pki-kra >= 10.2.1-0.1
|
||||
%if 0%{?rhel}
|
||||
Requires: subscription-manager
|
||||
%endif
|
||||
|
@ -19,7 +19,7 @@ ProxyRequests Off
|
||||
</LocationMatch>
|
||||
|
||||
# matches for agent port and eeca port
|
||||
<LocationMatch "^/ca/agent/ca/displayBySerial|^/ca/agent/ca/doRevoke|^/ca/agent/ca/doUnrevoke|^/ca/agent/ca/updateDomainXML|^/ca/eeca/ca/profileSubmitSSLClient|^/kra/agent/kra/connector|^/kra/rest/agent/keyrequests|^/kra/rest/agent/keys|^/ca/rest/admin/kraconnector/remove">
|
||||
<LocationMatch "^/ca/agent/ca/displayBySerial|^/ca/agent/ca/doRevoke|^/ca/agent/ca/doUnrevoke|^/ca/agent/ca/updateDomainXML|^/ca/eeca/ca/profileSubmitSSLClient|^/kra/agent/kra/connector|^/kra/rest/account|^/kra/rest/agent/keyrequests|^/kra/rest/agent/keys|^/ca/rest/admin/kraconnector/remove">
|
||||
NSSOptions +StdEnvVars +ExportCertData +StrictRequire +OptRenegotiate
|
||||
NSSVerifyClient require
|
||||
ProxyPassMatch ajp://localhost:$DOGTAG_PORT
|
||||
|
@ -138,8 +138,8 @@ class BasePathNamespace(object):
|
||||
HOME_DIR = "/home"
|
||||
ROOT_IPA_CACHE = "/root/.ipa_cache"
|
||||
ROOT_PKI = "/root/.pki"
|
||||
DOGTAG_AGENT_P12 = "/root/ca-agent.p12"
|
||||
DOGTAG_AGENT_PEM = "/etc/httpd/alias/agent.pem"
|
||||
DOGTAG_ADMIN_P12 = "/root/ca-agent.p12"
|
||||
KRA_AGENT_PEM = "/etc/httpd/alias/kra-agent.pem"
|
||||
CACERT_P12 = "/root/cacert.p12"
|
||||
ROOT_IPA_CSR = "/root/ipa.csr"
|
||||
ROOT_TMP_CA_P12 = "/root/tmp-ca.p12"
|
||||
|
@ -514,7 +514,7 @@ class CAInstance(DogtagInstance):
|
||||
config.set("CA", "pki_admin_nickname", "ipa-ca-agent")
|
||||
config.set("CA", "pki_admin_subject_dn",
|
||||
str(DN(('cn', 'ipa-ca-agent'), self.subject_base)))
|
||||
config.set("CA", "pki_client_admin_cert_p12", paths.DOGTAG_AGENT_P12)
|
||||
config.set("CA", "pki_client_admin_cert_p12", paths.DOGTAG_ADMIN_P12)
|
||||
|
||||
# Directory server
|
||||
config.set("CA", "pki_ds_ldap_port", str(self.ds_port))
|
||||
@ -979,7 +979,7 @@ class CAInstance(DogtagInstance):
|
||||
try:
|
||||
ipautil.run([paths.PK12UTIL,
|
||||
"-n", "ipa-ca-agent",
|
||||
"-o", paths.DOGTAG_AGENT_P12,
|
||||
"-o", paths.DOGTAG_ADMIN_P12,
|
||||
"-d", self.agent_db,
|
||||
"-k", pwd_name,
|
||||
"-w", pwd_name])
|
||||
|
@ -157,7 +157,8 @@ class Backup(admintool.AdminTool):
|
||||
paths.NTP_CONF,
|
||||
paths.SMB_CONF,
|
||||
paths.SAMBA_KEYTAB,
|
||||
paths.DOGTAG_AGENT_P12,
|
||||
paths.DOGTAG_ADMIN_P12,
|
||||
paths.KRA_AGENT_PEM,
|
||||
paths.CACERT_P12,
|
||||
paths.KRB5KDC_KDC_CONF,
|
||||
paths.SYSTEMD_IPA_SERVICE,
|
||||
|
@ -169,7 +169,7 @@ class KRAInstance(DogtagInstance):
|
||||
str(DN(('cn', 'ipa-ca-agent'), self.subject_base)))
|
||||
config.set("KRA", "pki_import_admin_cert", "True")
|
||||
config.set("KRA", "pki_admin_cert_file", paths.ADMIN_CERT_PATH)
|
||||
config.set("KRA", "pki_client_admin_cert_p12", paths.DOGTAG_AGENT_P12)
|
||||
config.set("KRA", "pki_client_admin_cert_p12", paths.DOGTAG_ADMIN_P12)
|
||||
|
||||
# Directory server
|
||||
config.set("KRA", "pki_ds_ldap_port", str(self.ds_port))
|
||||
@ -259,16 +259,81 @@ class KRAInstance(DogtagInstance):
|
||||
"""
|
||||
Add RA agent created for CA to KRA agent group.
|
||||
"""
|
||||
conn = ipaldap.IPAdmin(self.fqdn, self.ds_port)
|
||||
conn.do_simple_bind(DN(('cn', 'Directory Manager')), self.dm_password)
|
||||
|
||||
entry_dn = DN(('uid', "ipara"), ('ou', 'People'), ('o', 'ipaca'))
|
||||
dn = DN(('cn', 'Data Recovery Manager Agents'), ('ou', 'groups'),
|
||||
self.basedn)
|
||||
modlist = [(0, 'uniqueMember', '%s' % entry_dn)]
|
||||
conn.modify_s(dn, modlist)
|
||||
# import CA certificate into temporary security database
|
||||
args = ["/usr/bin/pki",
|
||||
"-d", self.agent_db,
|
||||
"-c", self.admin_password,
|
||||
"client-cert-import",
|
||||
"--pkcs12", paths.KRACERT_P12,
|
||||
"--pkcs12-password", self.admin_password]
|
||||
ipautil.run(args)
|
||||
|
||||
conn.unbind()
|
||||
# trust CA certificate
|
||||
args = ["/usr/bin/pki",
|
||||
"-d", self.agent_db,
|
||||
"-c", self.admin_password,
|
||||
"client-cert-mod", "Certificate Authority - %s" % api.env.realm,
|
||||
"--trust", "CT,c,"]
|
||||
ipautil.run(args)
|
||||
|
||||
# import Dogtag admin certificate into temporary security database
|
||||
args = ["/usr/bin/pki",
|
||||
"-d", self.agent_db,
|
||||
"-c", self.admin_password,
|
||||
"client-cert-import",
|
||||
"--pkcs12", paths.DOGTAG_ADMIN_P12,
|
||||
"--pkcs12-password", self.admin_password]
|
||||
ipautil.run(args)
|
||||
|
||||
# as Dogtag admin, create ipakra user in KRA
|
||||
args = ["/usr/bin/pki",
|
||||
"-d", self.agent_db,
|
||||
"-c", self.admin_password,
|
||||
"-n", "ipa-ca-agent",
|
||||
"kra-user-add", "ipakra",
|
||||
"--fullName", "IPA KRA User"]
|
||||
ipautil.run(args)
|
||||
|
||||
# as Dogtag admin, add ipakra into KRA agents group
|
||||
args = ["/usr/bin/pki",
|
||||
"-d", self.agent_db,
|
||||
"-c", self.admin_password,
|
||||
"-n", "ipa-ca-agent",
|
||||
"kra-user-membership-add", "ipakra", "Data Recovery Manager Agents"]
|
||||
ipautil.run(args)
|
||||
|
||||
# assign ipaCert to ipakra
|
||||
(file, filename) = tempfile.mkstemp()
|
||||
os.close(file)
|
||||
try:
|
||||
# export ipaCert without private key
|
||||
args = ["/usr/bin/pki",
|
||||
"-d", paths.HTTPD_ALIAS_DIR,
|
||||
"-C", paths.ALIAS_PWDFILE_TXT,
|
||||
"client-cert-show", "ipaCert",
|
||||
"--cert", filename]
|
||||
ipautil.run(args)
|
||||
|
||||
# as Dogtag admin, upload and assign ipaCert to ipakra
|
||||
args = ["/usr/bin/pki",
|
||||
"-d", self.agent_db,
|
||||
"-c", self.admin_password,
|
||||
"-n", "ipa-ca-agent",
|
||||
"kra-user-cert-add", "ipakra",
|
||||
"--input", filename]
|
||||
ipautil.run(args)
|
||||
|
||||
finally:
|
||||
os.remove(filename)
|
||||
|
||||
# export ipaCert with private key for client authentication
|
||||
args = ["/usr/bin/pki",
|
||||
"-d", paths.HTTPD_ALIAS_DIR,
|
||||
"-C", paths.ALIAS_PWDFILE_TXT,
|
||||
"client-cert-show", "ipaCert",
|
||||
"--client-cert", paths.KRA_AGENT_PEM]
|
||||
ipautil.run(args)
|
||||
|
||||
@staticmethod
|
||||
def update_cert_config(nickname, cert, dogtag_constants=None):
|
||||
|
@ -1890,122 +1890,36 @@ class kra(Backend):
|
||||
"""
|
||||
|
||||
def __init__(self, kra_port=443):
|
||||
if api.env.in_tree:
|
||||
self.sec_dir = os.path.join(api.env.dot_ipa, 'alias')
|
||||
pwd_file = os.path.join(self.sec_dir, '.pwd')
|
||||
self.pem_file = os.path.join(self.sec_dir, ".pemfile")
|
||||
else:
|
||||
self.sec_dir = paths.HTTPD_ALIAS_DIR
|
||||
pwd_file = paths.ALIAS_PWDFILE_TXT
|
||||
self.pem_file = paths.DOGTAG_AGENT_PEM
|
||||
|
||||
self.kra_port = kra_port
|
||||
self.transport_nick = "IPA KRA Transport Cert"
|
||||
self.password = ""
|
||||
with open(pwd_file, "r") as f:
|
||||
self.password = f.readline().strip()
|
||||
|
||||
self.keyclient = None
|
||||
super(kra, self).__init__()
|
||||
|
||||
def _create_pem_file(self):
|
||||
""" Create PEM file used by KRA plugin for authentication.
|
||||
|
||||
This function reads the IPA HTTPD database and extracts the
|
||||
Dogtag agent certificate and keys into a PKCS#12 temporary file.
|
||||
The PKCS#12 file is then converted into PEM format so that it
|
||||
can be used by python-requests to authenticate to the KRA.
|
||||
|
||||
:return: None
|
||||
def get_client(self):
|
||||
"""
|
||||
(p12_pwd_fd, p12_pwd_fname) = tempfile.mkstemp()
|
||||
(p12_fd, p12_fname) = tempfile.mkstemp()
|
||||
Returns an authenticated KRA client to access KRA services.
|
||||
|
||||
try:
|
||||
os.write(p12_pwd_fd, self.password)
|
||||
os.close(p12_pwd_fd)
|
||||
os.close(p12_fd)
|
||||
|
||||
certdb = CertDB(api.env.realm)
|
||||
certdb.export_pkcs12(p12_fname, p12_pwd_fname, "ipaCert")
|
||||
|
||||
certdb.install_pem_from_p12(p12_fname, self.password, self.pem_file)
|
||||
except:
|
||||
self.debug("Error when creating PEM file for KRA operations")
|
||||
raise
|
||||
finally:
|
||||
os.remove(p12_fname)
|
||||
os.remove(p12_pwd_fname)
|
||||
|
||||
def _transport_cert_present(self):
|
||||
""" Check if the client certDB contains the KRA transport certificate
|
||||
:return: True/False
|
||||
Raises a generic exception if KRA is not enabled.
|
||||
"""
|
||||
# certutil -L -d db_dir -n cert_nick
|
||||
certdb = CertDB(api.env.realm)
|
||||
return certdb.has_nickname(self.transport_nick)
|
||||
|
||||
def _setup(self):
|
||||
""" Do initial setup and crypto initialization of the KRA client
|
||||
if not api.env.enable_kra:
|
||||
# TODO: replace this with a more specific exception
|
||||
raise RuntimeError('KRA service is not enabled')
|
||||
|
||||
Creates a PEM file containing the KRA agent cert/keys to be used for
|
||||
authentication to the KRA (if it does not already exist), Sets up a
|
||||
connection to the KRA and initializes an NSS certificate database to
|
||||
store the transport certificate, Retrieves the transport certificate
|
||||
if it is not already present.
|
||||
"""
|
||||
#set up pem file if not present
|
||||
if not os.path.exists(self.pem_file):
|
||||
self._create_pem_file()
|
||||
crypto = cryptoutil.NSSCryptoProvider(
|
||||
paths.HTTPD_ALIAS_DIR,
|
||||
password_file=paths.ALIAS_PWDFILE_TXT)
|
||||
|
||||
# set up connection
|
||||
connection = PKIConnection('https',
|
||||
self.kra_host,
|
||||
str(self.kra_port),
|
||||
'kra')
|
||||
connection.set_authentication_cert(self.pem_file)
|
||||
# TODO: obtain KRA host & port from IPA service list or point to KRA load balancer
|
||||
# https://fedorahosted.org/freeipa/ticket/4557
|
||||
connection = PKIConnection(
|
||||
'https',
|
||||
api.env.kra_host,
|
||||
str(self.kra_port),
|
||||
'kra')
|
||||
|
||||
crypto = cryptoutil.NSSCryptoProvider(self.sec_dir, self.password)
|
||||
connection.set_authentication_cert(paths.KRA_AGENT_PEM)
|
||||
|
||||
#create kraclient
|
||||
kraclient = KRAClient(connection, crypto)
|
||||
|
||||
# get transport cert if needed
|
||||
if not self._transport_cert_present():
|
||||
transport_cert = kraclient.system_certs.get_transport_cert()
|
||||
crypto.import_cert(self.transport_nick, transport_cert, "u,u,u")
|
||||
|
||||
crypto.initialize()
|
||||
|
||||
self.keyclient = kraclient.keys
|
||||
self.keyclient.set_transport_cert(self.transport_nick)
|
||||
|
||||
@cachedproperty
|
||||
def kra_host(self):
|
||||
"""
|
||||
:return: host
|
||||
as str
|
||||
|
||||
Select our KRA host.
|
||||
"""
|
||||
ldap2 = self.api.Backend.ldap2
|
||||
if host_has_service(api.env.kra_host, ldap2, "kra"):
|
||||
return api.env.kra_host
|
||||
if api.env.host != api.env.kra_host:
|
||||
if host_has_service(api.env.host, ldap2, "kra"):
|
||||
return api.env.host
|
||||
host = select_any_master(ldap2, "kra")
|
||||
if host:
|
||||
return host
|
||||
else:
|
||||
return api.env.kra_host
|
||||
|
||||
def get_keyclient(self):
|
||||
"""Return a keyclient to perform key archival and retrieval.
|
||||
:return: pki.key.keyclient
|
||||
"""
|
||||
if self.keyclient is None:
|
||||
self._setup()
|
||||
return self.keyclient
|
||||
return KRAClient(connection, crypto)
|
||||
|
||||
api.register(kra)
|
||||
|
Loading…
Reference in New Issue
Block a user