pgreco / rpms / ipa

Forked from forks/areguera/rpms/ipa 4 years ago
Clone

Blame SOURCES/0156-Add-profiles-and-default-CA-ACL-on-migration.patch

2e9388
From 5fb869896c9ed6327f5f004022cdee42f758f78c Mon Sep 17 00:00:00 2001
2e9388
From: Fraser Tweedale <ftweedal@redhat.com>
2e9388
Date: Mon, 23 Nov 2015 12:09:32 +1100
2e9388
Subject: [PATCH] Add profiles and default CA ACL on migration
2e9388
2e9388
Profiles and the default CA ACL were not being added during replica
2e9388
install from pre-4.2 servers.  Update ipa-replica-install to add
2e9388
these if they are missing.
2e9388
2e9388
Also update the caacl plugin to prevent deletion of the default CA
2e9388
ACL and instruct the administrator to disable it instead.
2e9388
2e9388
To ensure that the cainstance installation can add profiles, supply
2e9388
the RA certificate as part of the instance configuration.
2e9388
Certmonger renewal setup is avoided at this point because the NSSDB
2e9388
gets reinitialised later in installation procedure.
2e9388
2e9388
Also move the addition of the default CA ACL from dsinstance
2e9388
installation to cainstance installation.
2e9388
2e9388
Fixes: https://fedorahosted.org/freeipa/ticket/5459
2e9388
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
2e9388
---
2e9388
 install/share/Makefile.am                    |   1 -
2e9388
 install/share/default-caacl.ldif             |  11 ---
2e9388
 install/updates/50-dogtag10-migration.update |   1 +
2e9388
 ipalib/plugins/caacl.py                      |   8 +++
2e9388
 ipaserver/install/ca.py                      |   5 +-
2e9388
 ipaserver/install/cainstance.py              | 100 ++++++++++++++++++++-------
2e9388
 ipaserver/install/dsinstance.py              |   4 --
2e9388
 ipaserver/install/server/replicainstall.py   |   3 +
2e9388
 ipaserver/install/server/upgrade.py          |  13 +---
2e9388
 9 files changed, 90 insertions(+), 56 deletions(-)
2e9388
 delete mode 100644 install/share/default-caacl.ldif
2e9388
2e9388
diff --git a/install/share/Makefile.am b/install/share/Makefile.am
2e9388
index d68c40e693a1d86c70d8ccd81ef2c915b2e1f61e..e4cca8708ab0042d6cb37eba31341e53e3cdac4d 100644
2e9388
--- a/install/share/Makefile.am
2e9388
+++ b/install/share/Makefile.am
2e9388
@@ -29,7 +29,6 @@ app_DATA =				\
2e9388
 	bootstrap-template.ldif		\
2e9388
 	caJarSigningCert.cfg.template	\
2e9388
 	default-aci.ldif		\
2e9388
-	default-caacl.ldif		\
2e9388
 	default-hbac.ldif		\
2e9388
 	default-smb-group.ldif		\
2e9388
 	default-trust-view.ldif		\
2e9388
diff --git a/install/share/default-caacl.ldif b/install/share/default-caacl.ldif
2e9388
deleted file mode 100644
2e9388
index f3cd5b4d4e3a79bc6638dc1ffdd7028596ded254..0000000000000000000000000000000000000000
2e9388
--- a/install/share/default-caacl.ldif
2e9388
+++ /dev/null
2e9388
@@ -1,11 +0,0 @@
2e9388
-# default CA ACL that grants use of caIPAserviceCert on top-level CA to all hosts and services
2e9388
-dn: ipauniqueid=autogenerate,cn=caacls,cn=ca,$SUFFIX
2e9388
-changetype: add
2e9388
-objectclass: ipaassociation
2e9388
-objectclass: ipacaacl
2e9388
-ipauniqueid: autogenerate
2e9388
-cn: hosts_services_caIPAserviceCert
2e9388
-ipaenabledflag: TRUE
2e9388
-ipamembercertprofile: cn=caIPAserviceCert,cn=certprofiles,cn=ca,$SUFFIX
2e9388
-hostcategory: all
2e9388
-servicecategory: all
2e9388
diff --git a/install/updates/50-dogtag10-migration.update b/install/updates/50-dogtag10-migration.update
2e9388
index 2ab9d15bd220540dbc6b3fcd7928fc15c42caf80..0070c308aefc39aa4c27a046d185ce6d268e6270 100644
2e9388
--- a/install/updates/50-dogtag10-migration.update
2e9388
+++ b/install/updates/50-dogtag10-migration.update
2e9388
@@ -16,3 +16,4 @@ addifexist:resourceACLS:certServer.ca.groups:execute:allow (execute) group="Admi
2e9388
 addifexist:resourceACLS:certServer.ca.users:execute:allow (execute) group="Administrators":Admins may execute user operations
2e9388
 replace:resourceACLS:certServer.securitydomain.domainxml:read,modify:allow (read) user="anybody";allow (modify) group="Subsystem Group":Anybody is allowed to read domain.xml but only Subsystem group is allowed to modify the domain.xml::certServer.securitydomain.domainxml:read,modify:allow (read) user="anybody";allow (modify) group="Subsystem Group" || group="Enterprise CA Administrators" || group="Enterprise KRA Administrators" || group="Enterprise RA Administrators" || group="Enterprise OCSP Administrators" || group="Enterprise TKS Administrators" || group="Enterprise TPS Administrators":Anybody is allowed to read domain.xml but only Subsystem group and Enterprise Administrators are allowed to modify the domain.xml
2e9388
 replace:resourceACLS:certServer.ca.connectorInfo:read,modify:allow (modify,read) group="Enterprise KRA Administrators":Only Enterprise Administrators are allowed to update the connector information::certServer.ca.connectorInfo:read,modify:allow (read) group="Enterprise KRA Administrators";allow (modify) group="Enterprise KRA Administrators" || group="Subsystem Group":Only Enterprise Administrators and Subsystem Group are allowed to update the connector information
2e9388
+addifexist:resourceACLS:certServer.profile.configuration:read,modify:allow (read,modify) group="Certificate Manager Agents":Certificate Manager agents may modify (create/update/delete) and read profiles
2e9388
diff --git a/ipalib/plugins/caacl.py b/ipalib/plugins/caacl.py
2e9388
index 247d6df143aef1fba9f0ee74a9f7d8386bef5180..64dbec16e11e9fa2a67287b195b4bd1180a379e7 100644
2e9388
--- a/ipalib/plugins/caacl.py
2e9388
+++ b/ipalib/plugins/caacl.py
2e9388
@@ -307,6 +307,14 @@ class caacl_del(LDAPDelete):
2e9388
 
2e9388
     msg_summary = _('Deleted CA ACL "%(value)s"')
2e9388
 
2e9388
+    def pre_callback(self, ldap, dn, *keys, **options):
2e9388
+        if keys[0] == 'hosts_services_caIPAserviceCert':
2e9388
+            raise errors.ProtectedEntryError(
2e9388
+                label=_("CA ACL"),
2e9388
+                key=keys[0],
2e9388
+                reason=_("default CA ACL can be only disabled"))
2e9388
+        return dn
2e9388
+
2e9388
 
2e9388
 @register()
2e9388
 class caacl_mod(LDAPUpdate):
2e9388
diff --git a/ipaserver/install/ca.py b/ipaserver/install/ca.py
2e9388
index 498cc48a742d1b2d862eb9dfdb18743cfb211b78..0de992cb0c15f8161aae4937699baae2a94d305a 100644
2e9388
--- a/ipaserver/install/ca.py
2e9388
+++ b/ipaserver/install/ca.py
2e9388
@@ -126,9 +126,10 @@ def install_step_0(standalone, replica_config, options):
2e9388
         if standalone:
2e9388
             api.Backend.ldap2.disconnect()
2e9388
 
2e9388
-        cainstance.install_replica_ca(replica_config, postinstall)
2e9388
+        cainstance.install_replica_ca(replica_config, postinstall,
2e9388
+                ra_p12=getattr(options, 'ra_p12', None))
2e9388
 
2e9388
-        if standalone:
2e9388
+        if standalone and not api.Backend.ldap2.isconnected():
2e9388
             api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')),
2e9388
                                       bind_pw=dm_password)
2e9388
 
2e9388
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
2e9388
index 3e3dce93de2b8ca48a3fe3ea5994ee92a1b0ce49..189876f3c0d980e78165d73eed86b2830ac8c5b8 100644
2e9388
--- a/ipaserver/install/cainstance.py
2e9388
+++ b/ipaserver/install/cainstance.py
2e9388
@@ -391,7 +391,7 @@ class CAInstance(DogtagInstance):
2e9388
                            cert_file=None, cert_chain_file=None,
2e9388
                            master_replication_port=None,
2e9388
                            subject_base=None, ca_signing_algorithm=None,
2e9388
-                           ca_type=None):
2e9388
+                           ca_type=None, ra_p12=None):
2e9388
         """Create a CA instance.
2e9388
 
2e9388
            For Dogtag 9, this may involve creating the pki-ca instance.
2e9388
@@ -465,7 +465,10 @@ class CAInstance(DogtagInstance):
2e9388
                 self.step("requesting RA certificate from CA", self.__request_ra_certificate)
2e9388
                 self.step("issuing RA agent certificate", self.__issue_ra_cert)
2e9388
                 self.step("adding RA agent as a trusted user", self.__create_ca_agent)
2e9388
-                self.step("authorizing RA to modify profiles", self.__configure_profiles_acl)
2e9388
+            elif ra_p12 is not None:
2e9388
+                self.step("importing RA certificate from PKCS #12 file",
2e9388
+                          lambda: self.import_ra_cert(ra_p12, configure_renewal=False))
2e9388
+            self.step("authorizing RA to modify profiles", configure_profiles_acl)
2e9388
             self.step("configure certmonger for renewals", self.configure_certmonger_renewal)
2e9388
             self.step("configure certificate renewals", self.configure_renewal)
2e9388
             if not self.clone:
2e9388
@@ -473,9 +476,12 @@ class CAInstance(DogtagInstance):
2e9388
             self.step("configure Server-Cert certificate renewal", self.track_servercert)
2e9388
             self.step("Configure HTTP to proxy connections",
2e9388
                       self.http_proxy)
2e9388
-            if not self.clone:
2e9388
-                self.step("restarting certificate server", self.restart_instance)
2e9388
-                self.step("Importing IPA certificate profiles", import_included_profiles)
2e9388
+            self.step("restarting certificate server", self.restart_instance)
2e9388
+            self.step("migrating certificate profiles to LDAP",
2e9388
+                      migrate_profiles_to_ldap)
2e9388
+            self.step("importing IPA certificate profiles",
2e9388
+                      import_included_profiles)
2e9388
+            self.step("adding default CA ACL", ensure_default_caacl)
2e9388
 
2e9388
         self.start_creation(runtime=210)
2e9388
 
2e9388
@@ -887,7 +893,7 @@ class CAInstance(DogtagInstance):
2e9388
 
2e9388
         export_kra_agent_pem()
2e9388
 
2e9388
-    def import_ra_cert(self, rafile):
2e9388
+    def import_ra_cert(self, rafile, configure_renewal=True):
2e9388
         """
2e9388
         Cloned RAs will use the same RA agent cert as the master so we
2e9388
         need to import from a PKCS#12 file.
2e9388
@@ -903,7 +909,8 @@ class CAInstance(DogtagInstance):
2e9388
         finally:
2e9388
             os.remove(agent_name)
2e9388
 
2e9388
-        self.configure_agent_renewal()
2e9388
+        if configure_renewal:
2e9388
+            self.configure_agent_renewal()
2e9388
 
2e9388
         export_kra_agent_pem()
2e9388
 
2e9388
@@ -953,10 +960,6 @@ class CAInstance(DogtagInstance):
2e9388
 
2e9388
         conn.disconnect()
2e9388
 
2e9388
-    def __configure_profiles_acl(self):
2e9388
-        """Allow the Certificate Manager Agents group to modify profiles."""
2e9388
-        configure_profiles_acl()
2e9388
-
2e9388
     def __run_certutil(self, args, database=None, pwd_file=None, stdin=None):
2e9388
         if not database:
2e9388
             database = self.ra_agent_db
2e9388
@@ -1491,7 +1494,7 @@ def replica_ca_install_check(config):
2e9388
         exit('IPA schema missing on master CA directory server')
2e9388
 
2e9388
 
2e9388
-def install_replica_ca(config, postinstall=False):
2e9388
+def install_replica_ca(config, postinstall=False, ra_p12=None):
2e9388
     """
2e9388
     Install a CA on a replica.
2e9388
 
2e9388
@@ -1533,7 +1536,7 @@ def install_replica_ca(config, postinstall=False):
2e9388
         ca.create_ra_agent_db = False
2e9388
     ca.configure_instance(config.host_name, config.domain_name,
2e9388
                           config.dirman_password, config.dirman_password,
2e9388
-                          pkcs12_info=(cafile,),
2e9388
+                          pkcs12_info=(cafile,), ra_p12=ra_p12,
2e9388
                           master_host=config.master_host_name,
2e9388
                           master_replication_port=config.ca_ds_port,
2e9388
                           subject_base=config.subject_base)
2e9388
@@ -1658,6 +1661,14 @@ def update_people_entry(dercert):
2e9388
     return True
2e9388
 
2e9388
 def ensure_ldap_profiles_container():
2e9388
+    ensure_entry(
2e9388
+        DN(('ou', 'certificateProfiles'), ('ou', 'ca'), ('o', 'ipaca')),
2e9388
+        objectclass=['top', 'organizationalUnit'],
2e9388
+        ou=['certificateProfiles'],
2e9388
+    )
2e9388
+
2e9388
+
2e9388
+def ensure_entry(dn, **attrs):
2e9388
     server_id = installutils.realm_to_serverid(api.env.realm)
2e9388
     dogtag_uri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % server_id
2e9388
 
2e9388
@@ -1665,40 +1676,39 @@ def ensure_ldap_profiles_container():
2e9388
     if not conn.isconnected():
2e9388
         conn.connect(autobind=True)
2e9388
 
2e9388
-    dn = DN(('ou', 'certificateProfiles'), ('ou', 'ca'), ('o', 'ipaca'))
2e9388
     try:
2e9388
         conn.get_entry(dn)
2e9388
     except errors.NotFound:
2e9388
         # entry doesn't exist; add it
2e9388
-        entry = conn.make_entry(
2e9388
-            dn,
2e9388
-            objectclass=['top', 'organizationalUnit'],
2e9388
-            ou=['certificateProfiles'],
2e9388
-        )
2e9388
+        entry = conn.make_entry(dn, **attrs)
2e9388
         conn.add_entry(entry)
2e9388
 
2e9388
     conn.disconnect()
2e9388
 
2e9388
 
2e9388
 def configure_profiles_acl():
2e9388
+    """Allow the Certificate Manager Agents group to modify profiles."""
2e9388
     server_id = installutils.realm_to_serverid(api.env.realm)
2e9388
     dogtag_uri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % server_id
2e9388
     updated = False
2e9388
 
2e9388
     dn = DN(('cn', 'aclResources'), ('o', 'ipaca'))
2e9388
-    rule = (
2e9388
+    new_rules = [
2e9388
         'certServer.profile.configuration:read,modify:allow (read,modify) '
2e9388
         'group="Certificate Manager Agents":'
2e9388
-        'Certificate Manager agents may modify (create/update/delete) and read profiles'
2e9388
-    )
2e9388
-    modlist = [(ldap.MOD_ADD, 'resourceACLS', [rule])]
2e9388
+        'Certificate Manager agents may modify (create/update/delete) and read profiles',
2e9388
+
2e9388
+        'certServer.ca.account:login,logout:allow (login,logout) '
2e9388
+        'user="anybody":Anybody can login and logout',
2e9388
+    ]
2e9388
 
2e9388
     conn = ldap2.ldap2(api, ldap_uri=dogtag_uri)
2e9388
     if not conn.isconnected():
2e9388
         conn.connect(autobind=True)
2e9388
-    rules = conn.get_entry(dn).get('resourceACLS', [])
2e9388
-    if rule not in rules:
2e9388
-        conn.conn.modify_s(str(dn), modlist)
2e9388
+    cur_rules = conn.get_entry(dn).get('resourceACLS', [])
2e9388
+    add_rules = [rule for rule in new_rules if rule not in cur_rules]
2e9388
+    if add_rules:
2e9388
+        conn.conn.modify_s(str(dn), [(ldap.MOD_ADD, 'resourceACLS', add_rules)])
2e9388
         updated = True
2e9388
 
2e9388
     conn.disconnect()
2e9388
@@ -1718,6 +1728,17 @@ def import_included_profiles():
2e9388
     if not conn.isconnected():
2e9388
         conn.connect(autobind=True)
2e9388
 
2e9388
+    ensure_entry(
2e9388
+        DN(('cn', 'ca'), api.env.basedn),
2e9388
+        objectclass=['top', 'nsContainer'],
2e9388
+        cn=['ca'],
2e9388
+    )
2e9388
+    ensure_entry(
2e9388
+        DN(api.env.container_certprofile, api.env.basedn),
2e9388
+        objectclass=['top', 'nsContainer'],
2e9388
+        cn=['certprofiles'],
2e9388
+    )
2e9388
+
2e9388
     api.Backend.ra_certprofile._read_password()
2e9388
     api.Backend.ra_certprofile.override_port = 8443
2e9388
 
2e9388
@@ -1823,6 +1844,33 @@ def _create_dogtag_profile(profile_id, profile_data):
2e9388
                 "(it is probably already enabled)")
2e9388
 
2e9388
 
2e9388
+def ensure_default_caacl():
2e9388
+    """Add the default CA ACL if missing."""
2e9388
+    if not api.Backend.ldap2.isconnected():
2e9388
+        try:
2e9388
+            api.Backend.ldap2.connect(autobind=True)
2e9388
+        except errors.PublicError as e:
2e9388
+            root_logger.error("Cannot connect to LDAP to add CA ACLs: %s", e)
2e9388
+            return
2e9388
+
2e9388
+    ensure_entry(
2e9388
+        DN(('cn', 'ca'), api.env.basedn),
2e9388
+        objectclass=['top', 'nsContainer'],
2e9388
+        cn=['ca'],
2e9388
+    )
2e9388
+    ensure_entry(
2e9388
+        DN(api.env.container_caacl, api.env.basedn),
2e9388
+        objectclass=['top', 'nsContainer'],
2e9388
+        cn=['certprofiles'],
2e9388
+    )
2e9388
+
2e9388
+    if not api.Command.caacl_find()['result']:
2e9388
+        api.Command.caacl_add(u'hosts_services_caIPAserviceCert',
2e9388
+            hostcategory=u'all', servicecategory=u'all')
2e9388
+        api.Command.caacl_add_profile(u'hosts_services_caIPAserviceCert',
2e9388
+            certprofile=(u'caIPAserviceCert',))
2e9388
+
2e9388
+
2e9388
 if __name__ == "__main__":
2e9388
     standard_logging_setup("install.log")
2e9388
     ds = dsinstance.DsInstance()
2e9388
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
2e9388
index f33a9e03a4148dde69fc61441c878f5126f8e455..d78158532c4c88d9aa9acf3c65d278f5151458d8 100644
2e9388
--- a/ipaserver/install/dsinstance.py
2e9388
+++ b/ipaserver/install/dsinstance.py
2e9388
@@ -310,7 +310,6 @@ class DsInstance(service.Service):
2e9388
         self.step("adding range check plugin", self.__add_range_check_plugin)
2e9388
         if hbac_allow:
2e9388
             self.step("creating default HBAC rule allow_all", self.add_hbac)
2e9388
-        self.step("creating default CA ACL rule", self.add_caacl)
2e9388
         self.step("adding entries for topology management", self.__add_topology_entries)
2e9388
 
2e9388
         self.__common_post_setup()
2e9388
@@ -745,9 +744,6 @@ class DsInstance(service.Service):
2e9388
     def add_hbac(self):
2e9388
         self._ldap_mod("default-hbac.ldif", self.sub_dict)
2e9388
 
2e9388
-    def add_caacl(self):
2e9388
-        self._ldap_mod("default-caacl.ldif", self.sub_dict)
2e9388
-
2e9388
     def change_admin_password(self, password):
2e9388
         root_logger.debug("Changing admin password")
2e9388
         dirname = config_dirname(self.serverid)
2e9388
diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
2e9388
index 6f9a6141fe9af44806244ce52df59c191dc966b0..6e9157cabc49161ba27983cbf1de1428d1b48b7d 100644
2e9388
--- a/ipaserver/install/server/replicainstall.py
2e9388
+++ b/ipaserver/install/server/replicainstall.py
2e9388
@@ -573,6 +573,9 @@ def install(installer):
2e9388
         options.domain_name = config.domain_name
2e9388
         options.host_name = config.host_name
2e9388
 
2e9388
+        if ipautil.file_exists(config.dir + "/cacert.p12"):
2e9388
+            options.ra_p12 = config.dir + "/ra.p12"
2e9388
+
2e9388
         ca.install(False, config, options)
2e9388
 
2e9388
     krb = install_krb(config, setup_pkinit=not options.no_pkinit)
2e9388
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
2e9388
index c8f744c392c7b859459bda63c1f397226553d4ba..945cb3ebd63767cb1d57083e1da7c5605ac5a2f9 100644
2e9388
--- a/ipaserver/install/server/upgrade.py
2e9388
+++ b/ipaserver/install/server/upgrade.py
2e9388
@@ -1321,18 +1321,7 @@ def add_default_caacl(ca):
2e9388
         return
2e9388
 
2e9388
     if ca.is_configured():
2e9388
-        if not api.Backend.ldap2.isconnected():
2e9388
-            try:
2e9388
-                api.Backend.ldap2.connect(autobind=True)
2e9388
-            except ipalib.errors.PublicError as e:
2e9388
-                root_logger.error("Cannot connect to LDAP to add CA ACLs: %s", e)
2e9388
-                return
2e9388
-
2e9388
-        if not api.Command.caacl_find()['result']:
2e9388
-            api.Command.caacl_add(u'hosts_services_caIPAserviceCert',
2e9388
-                hostcategory=u'all', servicecategory=u'all')
2e9388
-            api.Command.caacl_add_profile(u'hosts_services_caIPAserviceCert',
2e9388
-                certprofile=(u'caIPAserviceCert',))
2e9388
+        cainstance.ensure_default_caacl()
2e9388
 
2e9388
     sysupgrade.set_upgrade_state('caacl', 'add_default_caacl', True)
2e9388
 
2e9388
-- 
2e9388
2.4.3
2e9388