Refactoring of autobind, object_exists

Required to prevent code duplications

ipaldap.IPAdmin now has method do_bind, which tries several bind methods
ipaldap.IPAClient now has method object_exists(dn)

Reviewed-By: Jan Cholasta <jcholast@redhat.com>
This commit is contained in:
Martin Basti
2014-08-27 15:06:42 +02:00
committed by Martin Kosek
parent dea825fd9c
commit 29ba9d9d26
6 changed files with 50 additions and 50 deletions

View File

@@ -25,7 +25,7 @@ from ipaserver.install import adtrustinstance
from ipaserver.install.installutils import * from ipaserver.install.installutils import *
from ipaserver.install import service from ipaserver.install import service
from ipapython import version from ipapython import version
from ipapython import ipautil, sysrestore from ipapython import ipautil, sysrestore, ipaldap
from ipalib import api, errors, util from ipalib import api, errors, util
from ipapython.config import IPAOptionParser from ipapython.config import IPAOptionParser
import krbV import krbV
@@ -405,7 +405,7 @@ def main():
smb = adtrustinstance.ADTRUSTInstance(fstore) smb = adtrustinstance.ADTRUSTInstance(fstore)
smb.realm = api.env.realm smb.realm = api.env.realm
smb.autobind = service.ENABLED smb.autobind = ipaldap.AUTOBIND_ENABLED
smb.setup(api.env.host, ip_address, api.env.realm, api.env.domain, smb.setup(api.env.host, ip_address, api.env.realm, api.env.domain,
netbios_name, reset_netbios_name, netbios_name, reset_netbios_name,
options.rid_base, options.secondary_rid_base, options.rid_base, options.secondary_rid_base,

View File

@@ -27,6 +27,8 @@ from decimal import Decimal
from copy import deepcopy from copy import deepcopy
import contextlib import contextlib
import collections import collections
import os
import pwd
import ldap import ldap
import ldap.sasl import ldap.sasl
@@ -53,6 +55,10 @@ _debug_log_ldap = False
_missing = object() _missing = object()
# Autobind modes
AUTOBIND_AUTO = 1
AUTOBIND_ENABLED = 2
AUTOBIND_DISABLED = 3
def unicode_from_utf8(val): def unicode_from_utf8(val):
''' '''
@@ -1633,6 +1639,18 @@ class LDAPClient(object):
with self.error_handler(): with self.error_handler():
self.conn.delete_s(dn) self.conn.delete_s(dn)
def entry_exists(self, dn):
"""
Test whether the given object exists in LDAP.
"""
assert isinstance(dn, DN)
try:
self.get_entry(dn, attrs_list=[])
except errors.NotFound:
return False
else:
return True
class IPAdmin(LDAPClient): class IPAdmin(LDAPClient):
@@ -1742,6 +1760,25 @@ class IPAdmin(LDAPClient):
self.__bind_with_wait( self.__bind_with_wait(
self.conn.sasl_interactive_bind_s, timeout, None, auth_tokens) self.conn.sasl_interactive_bind_s, timeout, None, auth_tokens)
def do_bind(self, dm_password="", autobind=AUTOBIND_AUTO, timeout=DEFAULT_TIMEOUT):
if dm_password:
self.do_simple_bind(bindpw=dm_password, timeout=timeout)
return
if autobind != AUTOBIND_DISABLED and os.getegid() == 0 and self.ldapi:
try:
# autobind
pw_name = pwd.getpwuid(os.geteuid()).pw_name
self.do_external_bind(pw_name, timeout=timeout)
return
except errors.NotFound, e:
if autobind == AUTOBIND_ENABLED:
# autobind was required and failed, raise
# exception that it failed
raise
#fall back
self.do_sasl_gssapi_bind(timeout=timeout)
def modify_s(self, *args, **kwargs): def modify_s(self, *args, **kwargs):
# FIXME: for backwards compatibility only # FIXME: for backwards compatibility only
return self.conn.modify_s(*args, **kwargs) return self.conn.modify_s(*args, **kwargs)

View File

@@ -202,23 +202,11 @@ def named_conf_set_directive(name, value, section=NAMED_SECTION_IPA,
with open(NAMED_CONF, 'w') as f: with open(NAMED_CONF, 'w') as f:
f.write("".join(new_lines)) f.write("".join(new_lines))
def dns_container_exists(fqdn, suffix, dm_password=None, ldapi=False, realm=None): def dns_container_exists(fqdn, suffix, dm_password=None, ldapi=False, realm=None,
autobind=ipaldap.AUTOBIND_DISABLED):
""" """
Test whether the dns container exists. Test whether the dns container exists.
""" """
def object_exists(dn): # FIXME, this should be a IPAdmin/ldap2 method so it can be shared
"""
Test whether the given object exists in LDAP.
"""
assert isinstance(dn, DN)
try:
conn.get_entry(dn)
except errors.NotFound:
return False
else:
return True
assert isinstance(suffix, DN) assert isinstance(suffix, DN)
try: try:
# At install time we may need to use LDAPI to avoid chicken/egg # At install time we may need to use LDAPI to avoid chicken/egg
@@ -228,14 +216,11 @@ def dns_container_exists(fqdn, suffix, dm_password=None, ldapi=False, realm=None
else: else:
conn = ipaldap.IPAdmin(host=fqdn, port=636, cacert=CACERT) conn = ipaldap.IPAdmin(host=fqdn, port=636, cacert=CACERT)
if dm_password: conn.do_bind(dm_password, autobind=autobind)
conn.do_simple_bind(bindpw=dm_password)
else:
conn.do_sasl_gssapi_bind()
except ldap.SERVER_DOWN: except ldap.SERVER_DOWN:
raise RuntimeError('LDAP server on %s is not responding. Is IPA installed?' % fqdn) raise RuntimeError('LDAP server on %s is not responding. Is IPA installed?' % fqdn)
ret = object_exists(DN(('cn', 'dns'), suffix)) ret = conn.entry_exists(DN(('cn', 'dns'), suffix))
conn.unbind() conn.unbind()
return ret return ret
@@ -446,7 +431,7 @@ class BindInstance(service.Service):
service_desc="DNS", service_desc="DNS",
dm_password=dm_password, dm_password=dm_password,
ldapi=False, ldapi=False,
autobind=service.DISABLED autobind=ipaldap.AUTOBIND_DISABLED
) )
self.dns_backup = DnsBackup(self) self.dns_backup = DnsBackup(self)
self.named_user = None self.named_user = None

View File

@@ -271,7 +271,7 @@ class CADSInstance(service.Service):
service_desc="directory server for the CA", service_desc="directory server for the CA",
dm_password=dm_password, dm_password=dm_password,
ldapi=False, ldapi=False,
autobind=service.DISABLED) autobind=ipaldap.AUTOBIND_DISABLED)
self.serverid = "PKI-IPA" self.serverid = "PKI-IPA"
self.realm = realm_name self.realm = realm_name

View File

@@ -192,7 +192,7 @@ class DsInstance(service.Service):
service_desc="directory server", service_desc="directory server",
dm_password=dm_password, dm_password=dm_password,
ldapi=False, ldapi=False,
autobind=service.DISABLED autobind=ipaldap.AUTOBIND_DISABLED
) )
self.nickname = 'Server-Cert' self.nickname = 'Server-Cert'
self.dm_password = dm_password self.dm_password = dm_password

View File

@@ -20,7 +20,6 @@
import sys import sys
import os, socket import os, socket
import tempfile import tempfile
import pwd
import time import time
import datetime import datetime
import traceback import traceback
@@ -32,10 +31,6 @@ from ipalib import errors, certstore
from ipaplatform import services from ipaplatform import services
from ipaplatform.paths import paths from ipaplatform.paths import paths
# Autobind modes
AUTO = 1
ENABLED = 2
DISABLED = 3
# The service name as stored in cn=masters,cn=ipa,cn=etc. In the tuple # The service name as stored in cn=masters,cn=ipa,cn=etc. In the tuple
# the first value is the *nix service name, the second the start order. # the first value is the *nix service name, the second the start order.
@@ -74,7 +69,8 @@ def format_seconds(seconds):
class Service(object): class Service(object):
def __init__(self, service_name, service_desc=None, sstore=None, dm_password=None, ldapi=True, autobind=AUTO): def __init__(self, service_name, service_desc=None, sstore=None, dm_password=None, ldapi=True,
autobind=ipaldap.AUTOBIND_AUTO):
self.service_name = service_name self.service_name = service_name
self.service_desc = service_desc self.service_desc = service_desc
self.service = services.service(service_name) self.service = services.service(service_name)
@@ -110,26 +106,8 @@ class Service(object):
conn = ipaldap.IPAdmin(ldapi=self.ldapi, realm=self.realm) conn = ipaldap.IPAdmin(ldapi=self.ldapi, realm=self.realm)
else: else:
conn = ipaldap.IPAdmin(self.fqdn, port=389) conn = ipaldap.IPAdmin(self.fqdn, port=389)
if self.dm_password:
conn.do_simple_bind(bindpw=self.dm_password) conn.do_bind(self.dm_password, autobind=self.autobind)
elif self.autobind in [AUTO, ENABLED]:
if os.getegid() == 0 and self.ldapi:
try:
# autobind
pw_name = pwd.getpwuid(os.geteuid()).pw_name
conn.do_external_bind(pw_name)
except errors.NotFound, e:
if self.autobind == AUTO:
# Fall back
conn.do_sasl_gssapi_bind()
else:
# autobind was required and failed, raise
# exception that it failed
raise e
else:
conn.do_sasl_gssapi_bind()
else:
conn.do_sasl_gssapi_bind()
except Exception, e: except Exception, e:
root_logger.debug("Could not connect to the Directory Server on %s: %s" % (self.fqdn, str(e))) root_logger.debug("Could not connect to the Directory Server on %s: %s" % (self.fqdn, str(e)))
raise raise