[Freeipa-devel] [PATCH] 0060 Ensure ipa-adtrust-install is run as admin user
Alexander Bokovoy
abokovoy at redhat.com
Wed Jul 18 12:55:34 UTC 2012
On Wed, 18 Jul 2012, Alexander Bokovoy wrote:
>On Tue, 17 Jul 2012, Rob Crittenden wrote:
>>Alexander Bokovoy wrote:
>>>On Fri, 13 Jul 2012, Alexander Bokovoy wrote:
>>>>Hi,
>>>>
>>>>when adding AD trusts support, we need to ensure we have valid kerberos
>>>>ticket of the user from 'admins' group or otherwise appropriate ACIs
>>>>will not be granted.
>>>>
>>>>This patch introduces a check for that. We already check if
>>>>ipa-adtrust-install is run by root so this complements existing checks.
>>>>
>>>>https://fedorahosted.org/freeipa/ticket/2815
>>>After discussing on IRC with Simo and Rob, we came to conclusion that it
>>>is possible to switch to LDAPI and autobind feature of dirsrv for
>>>authentication and remove requirement for Directory Manager credentials
>>>altogether.
>>>
>>>Updated patch makes use of LDAPI + autobind under root privileges to map
>>>automatically to Directory Manager privileges in dirsrv. Additionally it
>>>ensures we have Kerberos credentials to fetch keytab with CIFS service
>>>key.
>>>
>>>Service._ldap_mod() is extended to switch to autobind when self.ldapi is
>>>set to True and we are running as root.
>>>
>>>For those interested in why ACIError is mapped to 'outdated Kerberos
>>>credentials' error message, this is because we'll get ACIError for 'ipa
>>>user-show <uid>' command when authenticated by the Kerberos credentials
>>>for <uid> in a default ccache only when Kerberos credentials are stale --
>>>either belong to a user that was removed or to a previous IPA install
>>>that was wiped before reinstalling. The latter is how I discovered
>>>this case. :)
>>
>>I think that this should raise an exception if one tries to use
>>ldapi, doesn't provide the DM password and is not root. Otherwise
>>it won't authenticate at all.
>This is not exactly true.
>
>$ id
>uid=757000001(abokovoy) gid=757000001(abokovoy) groups=757000001(abokovoy)
>context=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
>
>$ ldapsearch -vvv -H ldapi://%2fvar%2frun%2fslapd-IPA-LOCAL.socket '*' >/dev/null
>ldap_initialize( ldapi://%2Fvar%2Frun%2Fslapd-IPA-LOCAL.socket/??base )
>SASL/EXTERNAL authentication started
>ldap_sasl_interactive_bind_s: Inappropriate authentication (48)
> additional info: SASL EXTERNAL bind requires an SSL connection
>
>$ ldapsearch -vvv -Y GSSAPI -H ldapi://%2fvar%2frun%2fslapd-IPA-LOCAL.socket '*' >/dev/null
>ldap_initialize( ldapi://%2Fvar%2Frun%2Fslapd-IPA-LOCAL.socket/??base )
>SASL/GSSAPI authentication started
>SASL username: abokovoy at IPA.LOCAL
>SASL SSF: 56
>SASL data security layer installed.
>filter: (objectclass=*)
>requesting: *
>
>So GSSAPI auth works with LDAPI access. I can simply enforce -Y GSSAPI
>when non-root and no dm_password regardless of self.ldapi, this would
>extend previously available logic to following:
>
>- ldapi: use -H ldapi://url instead of -h hostname
>- dm_password: add Directory Manager auth
>- root without dm_password: use autobind
>- non-root without dm_password: use GSSAPI
>
>>In reality, I think all this service code always runs as root, so
>>it may be a moot point, but this code is kinda convoluted.
>Yep.
Here is updated patch.
--
/ Alexander Bokovoy
-------------- next part --------------
>From 81b1e0305ac8ad3516bb7bcaeb13999480e0f14f Mon Sep 17 00:00:00 2001
From: Alexander Bokovoy <abokovoy at redhat.com>
Date: Fri, 13 Jul 2012 18:12:48 +0300
Subject: [PATCH 2/5] Ensure ipa-adtrust-install is run with Kerberos ticket
for admin user
When setting up AD trusts support, ipa-adtrust-install utility
needs to be run as:
- root, for performing Samba configuration and using LDAPI/autobind
- kinit-ed IPA admin user, to ensure proper ACIs are granted to
fetch keytab
As result, we can get rid of Directory Manager credentials in ipa-adtrust-install
https://fedorahosted.org/freeipa/ticket/2815
---
install/tools/ipa-adtrust-install | 42 +++++++++++++++++++++++--------
install/tools/man/ipa-adtrust-install.1 | 3 ---
ipaserver/install/adtrustinstance.py | 21 ++++++++--------
ipaserver/install/service.py | 15 +++++++++--
4 files changed, 55 insertions(+), 26 deletions(-)
diff --git a/install/tools/ipa-adtrust-install b/install/tools/ipa-adtrust-install
index 6678018e6346d75d5042894cfb833d38079d3f21..f367d5b2b516bd411bce9275ff299eb3ffdf6bf9 100755
--- a/install/tools/ipa-adtrust-install
+++ b/install/tools/ipa-adtrust-install
@@ -37,8 +37,6 @@ log_file_name = "/var/log/ipaserver-install.log"
def parse_options():
parser = IPAOptionParser(version=version.VERSION)
- parser.add_option("-p", "--ds-password", dest="dm_password",
- sensitive=True, help="directory manager password")
parser.add_option("-d", "--debug", dest="debug", action="store_true",
default=False, help="print debugging information")
parser.add_option("--ip-address", dest="ip_address",
@@ -86,6 +84,30 @@ def read_netbios_name(netbios_default):
return netbios_name
+def ensure_kerberos_admin_rights(api):
+ try:
+ ctx = krbV.default_context()
+ ccache = ctx.default_ccache()
+ principal = ccache.principal()
+ api.Backend.ldap2.connect(ccache.name)
+ user = api.Command.user_show(unicode(principal[0]))['result']
+ group = api.Command.group_show(u'admins')['result']
+ api.Backend.ldap2.disconnect()
+ if not (user['uid'][0] in group['member_user'] and
+ group['cn'][0] in user['memberof_group']):
+ raise errors.RequirementError(name='admins group membership')
+ except Exception, e:
+ error_messages = dict(
+ ACIError = "Outdated Kerberos credentials. Use kdestroy and kinit to update your ticket",
+ Krb5Error = "Must have Kerberos credentials to setup AD trusts on server",
+ RequirementError = "Must have administrative privileges to setup AD trusts on server"
+ )
+ name = type(e).__name__
+ if name in error_messages:
+ sys.exit(error_messages[name])
+ else:
+ sys.exit("Unrecognized error during check of admin rights: %s\n%s" % (name, str(e)))
+
def main():
safe_options, options = parse_options()
@@ -128,6 +150,8 @@ def main():
api.bootstrap(**cfg)
api.finalize()
+ ensure_kerberos_admin_rights(api)
+
if adtrustinstance.ipa_smb_conf_exists():
if not options.unattended:
while True:
@@ -194,9 +218,8 @@ def main():
if not options.unattended and ( not netbios_name or not options.netbios_name):
netbios_name = read_netbios_name(netbios_name)
- dm_password = options.dm_password or read_password("Directory Manager",
- confirm=False, validate=False)
- smb = adtrustinstance.ADTRUSTInstance(fstore, dm_password)
+ smb = adtrustinstance.ADTRUSTInstance(fstore)
+ smb.realm = api.env.realm
# try the connection
try:
@@ -205,12 +228,9 @@ def main():
except ldap.INVALID_CREDENTIALS, e:
sys.exit("Password is not valid!")
- if smb.dm_password:
- api.Backend.ldap2.connect(bind_dn="cn=Directory Manager", bind_pw=smb.dm_password)
- else:
- # See if our LDAP server is up and we can talk to it over GSSAPI
- ccache = krbV.default_context().default_ccache().name
- api.Backend.ldap2.connect(ccache)
+ # See if our LDAP server is up and we can talk to it over GSSAPI
+ ccache = krbV.default_context().default_ccache().name
+ api.Backend.ldap2.connect(ccache)
smb.setup(api.env.host, ip_address, api.env.realm, api.env.domain,
netbios_name, options.rid_base, options.secondary_rid_base,
diff --git a/install/tools/man/ipa-adtrust-install.1 b/install/tools/man/ipa-adtrust-install.1
index b61da19088b40d6a9e53784f9a061913ecda4321..22337c3df8827670657bf405b6c49ba2f8624d6d 100644
--- a/install/tools/man/ipa-adtrust-install.1
+++ b/install/tools/man/ipa-adtrust-install.1
@@ -27,9 +27,6 @@ trust to an Active Directory domain. This requires that the IPA server is
already installed and configured.
.SH "OPTIONS"
.TP
-\fB\-p\fR \fIDM_PASSWORD\fR, \fB\-\-ds\-password\fR=\fIDM_PASSWORD\fR
-The password to be used by the Directory Server for the Directory Manager user
-.TP
\fB\-d\fR, \fB\-\-debug\fR
Enable debug logging when more verbose output is needed
.TP
diff --git a/ipaserver/install/adtrustinstance.py b/ipaserver/install/adtrustinstance.py
index 20feec4df309b5793aa1c29fdf18bc5bfe180943..9dcbec2d61d935f90e74cc65b30a0f1d0c0f9d2a 100644
--- a/ipaserver/install/adtrustinstance.py
+++ b/ipaserver/install/adtrustinstance.py
@@ -96,10 +96,9 @@ class ADTRUSTInstance(service.Service):
OBJC_GROUP = "ipaNTGroupAttrs"
OBJC_DOMAIN = "ipaNTDomainAttrs"
- def __init__(self, fstore=None, dm_password=None):
+ def __init__(self, fstore=None):
self.fqdn = None
self.ip_address = None
- self.realm_name = None
self.domain_name = None
self.netbios_name = None
self.no_msdcs = None
@@ -118,7 +117,7 @@ class ADTRUSTInstance(service.Service):
self.rid_base = None
self.secondary_rid_base = None
- service.Service.__init__(self, "smb", dm_password=dm_password)
+ service.Service.__init__(self, "smb", dm_password=None, ldapi=True)
if fstore:
self.fstore = fstore
@@ -436,6 +435,8 @@ class ADTRUSTInstance(service.Service):
# We do not let the system start IPA components on its own,
# Instead we reply on the IPA init script to start only enabled
# components as found in our LDAP configuration tree
+ # Note that self.dm_password is None for ADTrustInstance because
+ # we ensure to be called as root and using ldapi to use autobind
try:
self.ldap_enable('ADTRUST', self.fqdn, self.dm_password, \
self.suffix)
@@ -449,7 +450,7 @@ class ADTRUSTInstance(service.Service):
root_logger.info("EXTID Service startup entry already exists.")
def __setup_sub_dict(self):
- self.sub_dict = dict(REALM = self.realm_name,
+ self.sub_dict = dict(REALM = self.realm,
SUFFIX = self.suffix,
NETBIOS_NAME = self.netbios_name,
SMB_DN = self.smb_dn,
@@ -460,16 +461,16 @@ class ADTRUSTInstance(service.Service):
rid_base, secondary_rid_base, no_msdcs=False, smbd_user="samba"):
self.fqdn = fqdn
self.ip_address = ip_address
- self.realm_name = realm_name
+ self.realm = realm_name
self.domain_name = domain_name
self.netbios_name = netbios_name
self.rid_base = rid_base
self.secondary_rid_base = secondary_rid_base
self.no_msdcs = no_msdcs
self.smbd_user = smbd_user
- self.suffix = ipautil.realm_to_suffix(self.realm_name)
+ self.suffix = ipautil.realm_to_suffix(self.realm)
self.ldapi_socket = "%%2fvar%%2frun%%2fslapd-%s.socket" % \
- realm_to_serverid(self.realm_name)
+ realm_to_serverid(self.realm)
self.smb_conf = "/etc/samba/smb.conf"
@@ -479,7 +480,7 @@ class ADTRUSTInstance(service.Service):
self.trust_dn = str(DN(api.env.container_trusts, self.suffix))
self.smb_dom_dn = str(DN(('cn', self.domain_name),
api.env.container_cifsdomains, self.suffix))
- self.cifs_principal = "cifs/" + self.fqdn + "@" + self.realm_name
+ self.cifs_principal = "cifs/" + self.fqdn + "@" + self.realm
self.cifs_agent = str(DN(('krbprincipalname', self.cifs_principal.lower()),
api.env.container_service,
self.suffix))
@@ -522,11 +523,11 @@ class ADTRUSTInstance(service.Service):
"range.\nAdd local ID range manually and try " \
"again!")
- entry = ipaldap.Entry(str(DN(('cn', ('%s_id_range' % self.realm_name)),
+ entry = ipaldap.Entry(str(DN(('cn', ('%s_id_range' % self.realm)),
api.env.container_ranges,
self.suffix)))
entry.setValue('objectclass', 'ipaDomainIDRange')
- entry.setValue('cn', ('%s_id_range' % self.realm_name))
+ entry.setValue('cn', ('%s_id_range' % self.realm))
entry.setValue('ipaBaseID', str(base_id))
entry.setValue('ipaIDRangeSize', str(id_range_size))
self.admin_conn.addEntry(entry)
diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py
index 5c2699e3fa4c115c972528d4c2cc6aa170711837..65c8e1b87412fc6aba1187615e39c2ec523e00e5 100644
--- a/ipaserver/install/service.py
+++ b/ipaserver/install/service.py
@@ -107,15 +107,26 @@ class Service(object):
if sub_dict.has_key('RANDOM_PASSWORD'):
nologlist.append(sub_dict['RANDOM_PASSWORD'])
+ args = ["/usr/bin/ldapmodify", "-v", "-f", path]
+
+ # Support autobind when running as root and using ldapi
+ if self.ldapi:
+ if not self.admin_conn:
+ self.ldap_connect()
+ args += ["-H", self.admin_conn._uri]
+ else:
+ args += ["-h", hostname]
+
if self.dm_password:
[pw_fd, pw_name] = tempfile.mkstemp()
os.write(pw_fd, self.dm_password)
os.close(pw_fd)
auth_parms = ["-x", "-D", "cn=Directory Manager", "-y", pw_name]
else:
- auth_parms = ["-Y", "GSSAPI"]
+ auth_params = []
+ if os.getegid() != 0:
+ auth_parms = ["-Y", "GSSAPI"]
- args = ["/usr/bin/ldapmodify", "-h", hostname, "-v", "-f", path]
args += auth_parms
try:
--
1.7.10.4
More information about the Freeipa-devel
mailing list