URL: https://github.com/freeipa/freeipa/pull/852
Author: HonzaCholasta
 Title: #852: pkinit manage: introduce ipa-pkinit-manage
Action: opened

PR body:
"""
**server certinstall: update KDC master entry**

After the KDC certificate is installed, add the PKINIT enabled flag to the
KDC master entry.

**pkinit manage: introduce ipa-pkinit-manage**

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

**server upgrade: do not enable PKINIT by default**

Enabling PKINIT often fails during server upgrade when requesting the KDC
certificate.

Now that PKINIT can be enabled post-install using ipa-pkinit-manage, avoid
the upgrade failure by not enabling PKINIT by default.

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

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/852/head:pr852
git checkout pr852
From 7b0c3bc294a3437a05a69f67d7f88ddc89ec913d Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Mon, 5 Jun 2017 12:35:52 +0000
Subject: [PATCH 1/3] server certinstall: update KDC master entry

After the KDC certificate is installed, add the PKINIT enabled flag to the
KDC master entry.

https://pagure.io/freeipa/issue/7000
---
 ipaserver/install/ipa_server_certinstall.py | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/ipaserver/install/ipa_server_certinstall.py b/ipaserver/install/ipa_server_certinstall.py
index a14a84f188..9c8f6e81a8 100644
--- a/ipaserver/install/ipa_server_certinstall.py
+++ b/ipaserver/install/ipa_server_certinstall.py
@@ -34,7 +34,7 @@
                               verify_kdc_cert_validity)
 from ipapython.dn import DN
 from ipalib import api, errors
-from ipaserver.install import certs, dsinstance, installutils
+from ipaserver.install import certs, dsinstance, installutils, krbinstance
 
 
 class ServerCertInstall(admintool.AdminTool):
@@ -223,6 +223,13 @@ def install_kdc_cert(self):
         except RuntimeError as e:
             raise admintool.ScriptError(str(e))
 
+        krb = krbinstance.KrbInstance()
+        krb.init_info(
+            realm_name=api.env.realm,
+            host_name=api.env.host,
+        )
+        krb.pkinit_enable()
+
     def check_chain(self, pkcs12_filename, pkcs12_pin, nssdb):
         # create a temp nssdb
         with NSSDatabase() as tempnssdb:

From 1ab63da4148b17a089c87876b7af50feda77266c Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Mon, 5 Jun 2017 12:41:02 +0000
Subject: [PATCH 2/3] 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
---
 freeipa.spec.in                        |  2 +
 install/tools/Makefile.am              |  1 +
 install/tools/ipa-pkinit-manage        |  8 +++
 install/tools/man/Makefile.am          |  1 +
 install/tools/man/ipa-pkinit-manage.1  | 34 +++++++++++++
 ipaserver/install/ipa_pkinit_manage.py | 93 ++++++++++++++++++++++++++++++++++
 ipaserver/install/krbinstance.py       | 24 +++++++++
 7 files changed, 163 insertions(+)
 create mode 100755 install/tools/ipa-pkinit-manage
 create mode 100644 install/tools/man/ipa-pkinit-manage.1
 create mode 100644 ipaserver/install/ipa_pkinit_manage.py

diff --git a/freeipa.spec.in b/freeipa.spec.in
index 1446dfbb7c..a637d287c6 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -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
diff --git a/install/tools/Makefile.am b/install/tools/Makefile.am
index 493e5ff4a8..47ecc14d73 100644
--- a/install/tools/Makefile.am
+++ b/install/tools/Makefile.am
@@ -28,6 +28,7 @@ dist_sbin_SCRIPTS =		\
 	ipa-advise		\
 	ipa-cacert-manage	\
 	ipa-winsync-migrate	\
+	ipa-pkinit-manage	\
 	$(NULL)
 
 appdir = $(libexecdir)/ipa/
diff --git a/install/tools/ipa-pkinit-manage b/install/tools/ipa-pkinit-manage
new file mode 100755
index 0000000000..5b2413bd7c
--- /dev/null
+++ b/install/tools/ipa-pkinit-manage
@@ -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()
diff --git a/install/tools/man/Makefile.am b/install/tools/man/Makefile.am
index 0d06ec7306..2dac9ac716 100644
--- a/install/tools/man/Makefile.am
+++ b/install/tools/man/Makefile.am
@@ -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 =			\
diff --git a/install/tools/man/ipa-pkinit-manage.1 b/install/tools/man/ipa-pkinit-manage.1
new file mode 100644
index 0000000000..5018ce8aa3
--- /dev/null
+++ b/install/tools/man/ipa-pkinit-manage.1
@@ -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
diff --git a/ipaserver/install/ipa_pkinit_manage.py b/ipaserver/install/ipa_pkinit_manage.py
new file mode 100644
index 0000000000..428c0e3476
--- /dev/null
+++ b/ipaserver/install/ipa_pkinit_manage.py
@@ -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")
diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py
index a1053d55cc..6b51e65d1e 100644
--- a/ipaserver/install/krbinstance.py
+++ b/ipaserver/install/krbinstance.py
@@ -451,6 +451,30 @@ def pkinit_enable(self):
         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,

From 028d383e018b977e60f8d862f8de9b2efbd1e14a Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Mon, 5 Jun 2017 12:42:52 +0000
Subject: [PATCH 3/3] server upgrade: do not enable PKINIT by default

Enabling PKINIT often fails during server upgrade when requesting the KDC
certificate.

Now that PKINIT can be enabled post-install using ipa-pkinit-manage, avoid
the upgrade failure by not enabling PKINIT by default.

https://pagure.io/freeipa/issue/7000
---
 ipaserver/install/server/upgrade.py | 10 ++--------
 1 file changed, 2 insertions(+), 8 deletions(-)

diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index 3e2abefc21..870bc08c13 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -1523,14 +1523,8 @@ def add_default_caacl(ca):
 def setup_pkinit(krb):
     root_logger.info("[Setup PKINIT]")
 
-    pkinit_is_enabled = krbinstance.is_pkinit_enabled()
-    ca_is_enabled = api.Command.ca_is_enabled()['result']
-
-    if not pkinit_is_enabled:
-        if ca_is_enabled:
-            krb.issue_ipa_ca_signed_pkinit_certs()
-        else:
-            krb.issue_selfsigned_pkinit_certs()
+    if not krbinstance.is_pkinit_enabled():
+        krb.issue_selfsigned_pkinit_certs()
 
     aug = Augeas(flags=Augeas.NO_LOAD | Augeas.NO_MODL_AUTOLOAD,
                  loadpath=paths.USR_SHARE_IPA_DIR)
_______________________________________________
FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org
To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org

Reply via email to