URL: https://github.com/freeipa/freeipa/pull/5325
Author: tiran
 Title: #5325: LDAP autobind authenticateAsDN for BIND named
Action: opened

PR body:
"""
Use new nsslapd-ldapiautoauthdnattr feature to switch BIND named from
GSSAPI bind to EXTERNAL LDAPI bind.

Requires 389-DS build https://copr.fedorainfracloud.org/coprs/build/1811023

- [ ] Requires new build of 389-DS
- [ ] Add new OIDs to FreeIPA's OID registry

Fixes: https://pagure.io/freeipa/issue/8544
See: https://github.com/389ds/389-ds-base/issues/4381
Signed-off-by: Christian Heimes <chei...@redhat.com>
"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/5325/head:pr5325
git checkout pr5325
From 95281b18d8912cdd18769b5c5b9e8049ba36df9e Mon Sep 17 00:00:00 2001
From: Christian Heimes <chei...@redhat.com>
Date: Fri, 4 Dec 2020 12:18:22 +0100
Subject: [PATCH] LDAP autobind authenticateAsDN for BIND named

Use new nsslapd-ldapiautoauthdnattr feature to switch BIND named from
GSSAPI bind to EXTERNAL LDAPI bind.

Requires 389-DS build https://copr.fedorainfracloud.org/coprs/build/1811023

Fixes: https://pagure.io/freeipa/issue/8544
See: https://github.com/389ds/389-ds-base/issues/4381
Signed-off-by: Christian Heimes <chei...@redhat.com>
---
 freeipa.spec.in                             | 11 +++----
 install/share/60basev3.ldif                 |  2 ++
 install/share/bind.named.conf.template      |  3 +-
 install/updates/20-autobind.update          |  8 +++++
 install/updates/49-autobind-services.update |  6 ++++
 install/updates/Makefile.am                 |  1 +
 ipapython/ipaldap.py                        |  2 ++
 ipaserver/install/bindinstance.py           | 10 ++++++-
 ipaserver/install/ipa_restore.py            |  8 ++++-
 ipaserver/install/ldapupdate.py             |  3 ++
 ipaserver/install/server/upgrade.py         |  7 +++++
 ipaserver/install/service.py                | 33 ++++++++++++++++++---
 12 files changed, 79 insertions(+), 15 deletions(-)
 create mode 100644 install/updates/49-autobind-services.update

diff --git a/freeipa.spec.in b/freeipa.spec.in
index c0c82be2aa8..be177eef0a5 100755
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -73,10 +73,8 @@
 %global selinux_policy_version 3.14.3-52
 %global slapi_nis_version 0.56.4
 %global python_ldap_version 3.1.0-1
-# python3-lib389
-# Fix for "Installation fails: Replica Busy"
-# https://pagure.io/389-ds-base/issue/49818
-%global ds_version 1.4.2.4-6
+# authenticate as DN feature
+%global ds_version 2.0.1-20201203
 # Fix for TLS 1.3 PHA, RHBZ#1775158
 %global httpd_version 2.4.37-21
 %global bind_version 9.11.20-6
@@ -101,9 +99,8 @@
 
 # fix for segfault in python3-ldap, https://pagure.io/freeipa/issue/7324
 %global python_ldap_version 3.1.0-1
-# 1.4.3 moved nsslapd-db-locks to cn=bdb sub-entry
-# https://pagure.io/freeipa/issue/8515
-%global ds_version 1.4.3
+# authenticat as DN feature
+%global ds_version 2.0.1-20201203
 
 # Fix for TLS 1.3 PHA, RHBZ#1775146
 %global httpd_version 2.4.41-9
diff --git a/install/share/60basev3.ldif b/install/share/60basev3.ldif
index efc6c8afb60..f1b909bcc11 100644
--- a/install/share/60basev3.ldif
+++ b/install/share/60basev3.ldif
@@ -58,6 +58,7 @@ attributeTypes: (2.16.840.1.113730.3.8.11.70 NAME 'ipaPermTargetTo' DESC 'Destin
 attributeTypes: (2.16.840.1.113730.3.8.11.71 NAME 'ipaPermTargetFrom' DESC 'Source location from where moving an entry IPA permission ACI' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE X-ORIGIN 'IPA v4.0' )
 attributeTypes: ( 2.16.840.1.113730.3.8.11.75 NAME 'ipaNTAdditionalSuffixes' DESC 'Suffix for the user principal name associated with the domain' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15)
 attributeTypes: (2.16.840.1.113730.3.8.11.77 NAME 'ipaDomainResolutionOrder' DESC 'List of domains used to resolve a short name' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE X-ORIGIN 'IPA v4.5')
+attributeTypes: (2.16.840.1.113730.3.8.11.78 NAME 'ipaAuthenticateAsDN' DESC 'LDAPI autobind as DN' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE X-ORIGIN 'IPA v4.10' )
 attributeTypes: (2.16.840.1.113730.3.8.18.2.1 NAME 'ipaVaultType' DESC 'IPA vault type' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'IPA v4.2')
 attributeTypes: (2.16.840.1.113730.3.8.18.2.2 NAME 'ipaVaultSalt' DESC 'IPA vault salt' EQUALITY octetStringMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.40 X-ORIGIN 'IPA v4.2' )
 # FIXME: https://bugzilla.redhat.com/show_bug.cgi?id=1267782
@@ -86,5 +87,6 @@ objectClasses: (2.16.840.1.113730.3.8.12.25 NAME 'ipaPrivateKeyObject' DESC 'Wra
 objectClasses: (2.16.840.1.113730.3.8.12.26 NAME 'ipaSecretKeyObject' DESC 'Wrapped secret keys' SUP top AUXILIARY MUST ( ipaSecretKey $ ipaWrappingKey $ ipaWrappingMech ) X-ORIGIN 'IPA v4.1' )
 objectClasses: (2.16.840.1.113730.3.8.12.34 NAME 'ipaSecretKeyRefObject' DESC 'Indirect storage for encoded key material' SUP top AUXILIARY MUST ( ipaSecretKeyRef ) X-ORIGIN 'IPA v4.1' )
 objectClasses: (2.16.840.1.113730.3.8.12.39 NAME 'ipaNameResolutionData' DESC 'Data used to resolve short names to fully-qualified form' SUP top AUXILIARY MAY ( ipaDomainResolutionOrder ) X-ORIGIN 'IPA v4.5')
+objectClasses: (2.16.840.1.113730.3.8.12.40 NAME 'ipaAutobind' DESC 'LDAPI autobind by uid+gid entry' SUP top STRUCTURAL MUST ( cn $ uidNumber $ gidNumber $ ipaAuthenticateAsDN ) MAY ( description ) X-ORIGIN 'IPA v4.10')
 objectClasses: (2.16.840.1.113730.3.8.18.1.1 NAME 'ipaVault' DESC 'IPA vault' SUP top STRUCTURAL MUST ( cn ) MAY ( description $ ipaVaultType $ ipaVaultSalt $ ipaVaultPublicKey $ owner $ member ) X-ORIGIN 'IPA v4.2' )
 objectClasses: (2.16.840.1.113730.3.8.18.1.2 NAME 'ipaVaultContainer' DESC 'IPA vault container' SUP top STRUCTURAL MUST ( cn ) MAY ( description $ owner ) X-ORIGIN 'IPA v4.2' )
diff --git a/install/share/bind.named.conf.template b/install/share/bind.named.conf.template
index 55e8142ebc2..1cdf5d0d6fa 100644
--- a/install/share/bind.named.conf.template
+++ b/install/share/bind.named.conf.template
@@ -55,6 +55,5 @@ dyndb "ipa" "$BIND_LDAP_SO" {
 	base "cn=dns,$SUFFIX";
 	server_id "$FQDN";
 	auth_method "sasl";
-	sasl_mech "GSSAPI";
-	sasl_user "DNS/$FQDN";
+	sasl_mech "EXTERNAL";
 };
diff --git a/install/updates/20-autobind.update b/install/updates/20-autobind.update
index 3a06f84b9a3..f9a3c6d48e5 100644
--- a/install/updates/20-autobind.update
+++ b/install/updates/20-autobind.update
@@ -1,6 +1,14 @@
+# countainer for autobind
+dn: cn=autobind,cn=config
+default: objectClass: nsContainer
+default: objectClass: top
+default: cn: autobind
+
 # map LDAPI autobind uid/gid to user entries (not used by root autobind)
 dn: cn=config
 only: nsslapd-ldapimaptoentries: on
+only: nsslapd-ldapientrysearchbase: cn=autobind,cn=config
+only: nsslapd-ldapiautoauthdnattr: ipaAuthenticateAsDN
 
 # lib389 configures 389-DS for root-autobind. This entry is no longer needed.
 dn: cn=root-autobind,cn=config
diff --git a/install/updates/49-autobind-services.update b/install/updates/49-autobind-services.update
new file mode 100644
index 00000000000..a5d6c491ccb
--- /dev/null
+++ b/install/updates/49-autobind-services.update
@@ -0,0 +1,6 @@
+# create / update LDAPI autobind rules for services
+# also used by ipa-restore to ensure correct mappings
+
+dn: cn=named,cn=autobind,cn=config
+onlyifexist: uidNumber: $NAMED_UID
+onlyifexist: gidNumber: $NAMED_GID
diff --git a/install/updates/Makefile.am b/install/updates/Makefile.am
index 5741805a65a..1f3a9caf1f5 100644
--- a/install/updates/Makefile.am
+++ b/install/updates/Makefile.am
@@ -45,6 +45,7 @@ app_DATA =				\
 	41-caacl.update			\
 	41-lightweight-cas.update	\
 	45-roles.update			\
+	49-autobind-services.update	\
 	50-7_bit_check.update	        \
 	50-dogtag10-migration.update	\
 	50-groupuuid.update		\
diff --git a/ipapython/ipaldap.py b/ipapython/ipaldap.py
index 394cd92e431..d2248f903ea 100644
--- a/ipapython/ipaldap.py
+++ b/ipapython/ipaldap.py
@@ -761,6 +761,8 @@ class LDAPClient:
         'nsslapd-enable-upgrade-hash': True,
         'nsslapd-db-locks': True,
         'nsslapd-logging-hr-timestamps-enabled': True,
+        'nsslapd-ldapientrysearchbase': True,
+        'nsslapd-ldapiautoauthdnattr': True,
     })
 
     time_limit = -1.0   # unlimited
diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
index 3b446ce765c..b75c8f32034 100644
--- a/ipaserver/install/bindinstance.py
+++ b/ipaserver/install/bindinstance.py
@@ -760,8 +760,11 @@ def create_instance(self):
             self.step("setting up records for other masters", self.__add_others)
         # all zones must be created before this step
         self.step("adding NS record to the zones", self.__add_self_ns)
-
+        # The service entry is used for LDAPI autobind. The keytab is no
+        # longer used to authenticate the server. The server still needs
+        # the keytab to handle incoming nsupdate requests with TSIG.
         self.step("setting up kerberos principal", self.__setup_principal)
+        self.step("setting up LDAPI autobind", self.setup_autobind)
         self.step("setting up named.conf", self.setup_named_conf)
         self.step("setting up server configuration",
             self.__setup_server_configuration)
@@ -1028,6 +1031,11 @@ def __setup_principal(self):
                             dns_principal, str(e))
             raise
 
+    def setup_autobind(self):
+        self.add_autobind_entry(
+            constants.NAMED_USER, constants.NAMED_GROUP, self.principal
+        )
+
     def setup_named_conf(self, backup=False):
         """Create, update, or migrate named configuration files
 
diff --git a/ipaserver/install/ipa_restore.py b/ipaserver/install/ipa_restore.py
index 02550e04320..726f9f1ce50 100644
--- a/ipaserver/install/ipa_restore.py
+++ b/ipaserver/install/ipa_restore.py
@@ -40,7 +40,7 @@
 from ipapython.dn import DN
 from ipaserver.install.replication import (wait_for_task, ReplicationManager,
                                            get_cs_replication_manager)
-from ipaserver.install import installutils
+from ipaserver.install import installutils, ldapupdate
 from ipaserver.install import dsinstance, httpinstance, cainstance, krbinstance
 from ipaserver.masters import get_masters
 from ipapython import ipaldap
@@ -467,6 +467,12 @@ def run(self):
                     oddjobd.enable()
                 oddjobd.start()
                 http.remove_httpd_ccaches()
+                # update autobind configuration in case uid/gid have changed
+                ld = ldapupdate.LDAPUpdate(api=api)
+                autobind_update = os.path.join(
+                    paths.UPDATES_DIR, "49-autobind-services.update"
+                )
+                ld.update([autobind_update])
                 # have the daemons pick up their restored configs
                 tasks.systemd_daemon_reload()
                 # Restart IPA a final time.
diff --git a/ipaserver/install/ldapupdate.py b/ipaserver/install/ldapupdate.py
index 15c0ccb5082..c2859ea9bae 100644
--- a/ipaserver/install/ldapupdate.py
+++ b/ipaserver/install/ldapupdate.py
@@ -296,6 +296,9 @@ def __init__(self, dm_password=_sentinel, sub_dict=None,
             SELINUX_USERMAP_DEFAULT=platformconstants.SELINUX_USERMAP_DEFAULT,
             SELINUX_USERMAP_ORDER=platformconstants.SELINUX_USERMAP_ORDER,
             FIPS="#" if tasks.is_fips_enabled() else "",
+            # uid / gid for autobind
+            NAMED_UID=platformconstants.NAMED_USER.uid,
+            NAMED_GID=platformconstants.NAMED_GROUP.gid,
         )
         for k, v in default_sub.items():
             self.sub_dict.setdefault(k, v)
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index 18891d53c7d..46211cba02b 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -1453,6 +1453,13 @@ def upgrade_bind(fstore):
     else:
         bind_started = False
 
+    try:
+        bind.setup_autobind()
+    except ipalib.errors.DuplicateEntry:
+        logger.debug("Autobind entry for named service exists.")
+    else:
+        logger.info("Added autobind entry for named service")
+
     try:
         changed = bind.setup_named_conf(backup=True)
         if changed:
diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py
index 2afb251fc10..ea0953f66c8 100644
--- a/ipaserver/install/service.py
+++ b/ipaserver/install/service.py
@@ -326,6 +326,15 @@ def principal(self):
             kerberos.Principal(
                 (self.service_prefix, self.fqdn), realm=self.realm))
 
+    def get_principal_dn(self, principal=None):
+        if principal is None:
+            principal = self.principal
+        return DN(
+            ('krbprincipalname', principal),
+            self.api.env.container_service,
+            self.suffix
+        )
+
     def _ldap_update(self, filenames, *, basedir=paths.UPDATES_DIR):
         """Apply update ldif files
 
@@ -413,7 +422,7 @@ def move_service(self, principal):
             # This can happen when installing a replica
             return None
         entry.pop('krbpwdpolicyreference', None)  # don't copy virtual attr
-        newdn = DN(('krbprincipalname', principal), ('cn', 'services'), ('cn', 'accounts'), self.suffix)
+        newdn = self.get_principal_dn(principal)
         hostdn = DN(('fqdn', self.fqdn), ('cn', 'computers'), ('cn', 'accounts'), self.suffix)
         api.Backend.ldap2.delete_entry(entry)
         entry.dn = newdn
@@ -431,7 +440,7 @@ def add_simple_service(self, principal):
 
         The principal needs to be fully-formed: service/host@REALM
         """
-        dn = DN(('krbprincipalname', principal), ('cn', 'services'), ('cn', 'accounts'), self.suffix)
+        dn = self.get_principal_dn(principal)
         hostdn = DN(('fqdn', self.fqdn), ('cn', 'computers'), ('cn', 'accounts'), self.suffix)
         entry = api.Backend.ldap2.make_entry(
             dn,
@@ -445,6 +454,23 @@ def add_simple_service(self, principal):
         api.Backend.ldap2.add_entry(entry)
         return dn
 
+    def add_autobind_entry(self, user, group, principal):
+        authdn = self.get_principal_dn(principal)
+        dn = DN(
+            ('cn', self.service_name), ('cn', 'autobind'), ('cn', 'config')
+        )
+        ldap2 = self.api.Backend.ldap2
+        entry = ldap2.make_entry(
+            dn,
+            objectclass=['ipaAutobind'],
+            cn=[self.service_name],
+            uidNumber=[user.uid],
+            gidNumber=[group.gid],
+            ipaAuthenticateAsDN=[authdn]
+        )
+        ldap2.add_entry(entry)
+        return dn
+
     def add_cert_to_service(self):
         """
         Add a certificate to a service
@@ -453,8 +479,7 @@ def add_cert_to_service(self):
         """
         if self.cert is None:
             raise ValueError("{} has no cert".format(self.service_name))
-        dn = DN(('krbprincipalname', self.principal), ('cn', 'services'),
-                ('cn', 'accounts'), self.suffix)
+        dn = self.get_principal_dn()
         entry = api.Backend.ldap2.get_entry(dn)
         entry.setdefault('userCertificate', []).append(self.cert)
         try:
_______________________________________________
FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org
To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/freeipa-devel@lists.fedorahosted.org

Reply via email to