pkinit manage: introduce ipa-pkinit-manage

Add the ipa-pkinit-manage tool to allow enabling / disabling PKINIT after
the initial server install.

https://pagure.io/freeipa/issue/7000

Reviewed-By: Martin Babinsky <mbabinsk@redhat.com>
This commit is contained in:
Jan Cholasta 2017-06-05 12:41:02 +00:00 committed by Martin Babinsky
parent e131905f3e
commit 92276c1e88
7 changed files with 163 additions and 0 deletions

View File

@ -1196,6 +1196,7 @@ fi
%{_sbindir}/ipa-advise
%{_sbindir}/ipa-cacert-manage
%{_sbindir}/ipa-winsync-migrate
%{_sbindir}/ipa-pkinit-manage
%{_libexecdir}/certmonger/dogtag-ipa-ca-renew-agent-submit
%{_libexecdir}/certmonger/ipa-server-guard
%dir %{_libexecdir}/ipa
@ -1259,6 +1260,7 @@ fi
%{_mandir}/man1/ipa-otptoken-import.1*
%{_mandir}/man1/ipa-cacert-manage.1*
%{_mandir}/man1/ipa-winsync-migrate.1*
%{_mandir}/man1/ipa-pkinit-manage.1*
%files -n python2-ipaserver

View File

@ -28,6 +28,7 @@ dist_sbin_SCRIPTS = \
ipa-advise \
ipa-cacert-manage \
ipa-winsync-migrate \
ipa-pkinit-manage \
$(NULL)
appdir = $(libexecdir)/ipa/

View File

@ -0,0 +1,8 @@
#! /usr/bin/python2 -E
#
# Copyright (C) 2017 FreeIPA Contributors see COPYING for license
#
from ipaserver.install.ipa_pkinit_manage import PKINITManage
PKINITManage.run_cli()

View File

@ -27,6 +27,7 @@ dist_man1_MANS = \
ipa-otptoken-import.1 \
ipa-cacert-manage.1 \
ipa-winsync-migrate.1 \
ipa-pkinit-manage.1 \
$(NULL)
dist_man8_MANS = \

View File

@ -0,0 +1,34 @@
.\"
.\" Copyright (C) 2017 FreeIPA Contributors see COPYING for license
.\"
.TH "ipa-pkinit-manage" "1" "Jun 05 2017" "FreeIPA" "FreeIPA Manual Pages"
.SH "NAME"
ipa\-pkinit\-manage \- Enables or disables PKINIT
.SH "SYNOPSIS"
ipa\-pkinit\-manage [options] <enable|disable|status>
.SH "DESCRIPTION"
Run the command with the \fBenable\fR option to enable PKINIT.
Run the command with the \fBdisable\fR option to disable PKINIT.
Run the command with the \fBstatus\fR to determine the current status of PKINIT.
.SH "OPTIONS"
.TP
\fB\-\-version\fR
Show the program's version and exit.
.TP
\fB\-h\fR, \fB\-\-help\fR
Show the help for this program.
.TP
\fB\-v\fR, \fB\-\-verbose\fR
Print debugging information.
.TP
\fB\-q\fR, \fB\-\-quiet\fR
Output only errors.
.TP
\fB\-\-log\-file\fR=\fIFILE\fR
Log to the given file.
.SH "EXIT STATUS"
0 if the command was successful
1 if an error occurred

View File

@ -0,0 +1,93 @@
#
# Copyright (C) 2017 FreeIPA Contributors see COPYING for license
#
from __future__ import print_function
from ipalib import api
from ipaplatform.paths import paths
from ipapython.admintool import AdminTool
from ipaserver.install.krbinstance import KrbInstance, is_pkinit_enabled
class PKINITManage(AdminTool):
command_name = "ipa-pkinit-manage"
usage = "%prog <enable|disable|status>"
description = "Manage PKINIT."
def validate_options(self):
super(PKINITManage, self).validate_options(needs_root=True)
option_parser = self.option_parser
if not self.args:
option_parser.error("action not specified")
elif len(self.args) > 1:
option_parser.error("too many arguments")
action = self.args[0]
if action not in {'enable', 'disable', 'status'}:
option_parser.error("unrecognized action '{}'".format(action))
def run(self):
api.bootstrap(in_server=True, confdir=paths.ETC_IPA)
api.finalize()
api.Backend.ldap2.connect()
try:
action = self.args[0]
if action == 'enable':
self.enable()
elif action == 'disable':
self.disable()
elif action == 'status':
self.status()
finally:
api.Backend.ldap2.disconnect()
return 0
def _setup(self, setup_pkinit):
config = api.Command.config_show()['result']
ca_enabled = api.Command.ca_is_enabled()['result']
krb = KrbInstance()
krb.init_info(
realm_name=api.env.realm,
host_name=api.env.host,
setup_pkinit=setup_pkinit,
subject_base=config['ipacertificatesubjectbase'][0],
)
if bool(is_pkinit_enabled()) is not bool(setup_pkinit):
try:
krb.stop_tracking_certs()
except RuntimeError as e:
if ca_enabled:
self.log.warning(
"Failed to stop tracking certificates: %s", e)
krb.enable_ssl()
if setup_pkinit:
krb.pkinit_enable()
else:
krb.pkinit_disable()
def enable(self):
if not api.Command.ca_is_enabled()['result']:
self.log.error("Cannot enable PKINIT in CA-less deployment")
self.log.error("Use ipa-server-certinstall to install KDC "
"certificate manually")
raise RuntimeError("Cannot enable PKINIT in CA-less deployment")
self._setup(True)
def disable(self):
self._setup(False)
def status(self):
if is_pkinit_enabled():
print("PKINIT is enabled")
else:
print("PKINIT is disabled")

View File

@ -451,6 +451,30 @@ class KrbInstance(service.Service):
service.set_service_entry_config(
'KDC', self.fqdn, [PKINIT_ENABLED], self.suffix)
def pkinit_disable(self):
"""
unadvertise enabled PKINIT feature in master's KDC entry in LDAP
"""
ldap = api.Backend.ldap2
dn = DN(('cn', 'KDC'),
('cn', self.fqdn),
('cn', 'masters'),
('cn', 'ipa'),
('cn', 'etc'),
self.suffix)
entry = ldap.get_entry(dn, ['ipaConfigString'])
config = entry.setdefault('ipaConfigString', [])
config = [value for value in config
if value.lower() != PKINIT_ENABLED.lower()]
entry['ipaConfigString'][:] = config
try:
ldap.update_entry(entry)
except errors.EmptyModlist:
pass
def _install_pkinit_ca_bundle(self):
ca_certs = certstore.get_ca_certs(self.api.Backend.ldap2,
self.api.env.basedn,