Use DN objects instead of strings

* Convert every string specifying a DN into a DN object

* Every place a dn was manipulated in some fashion it was replaced by
  the use of DN operators

* Add new DNParam parameter type for parameters which are DN's

* DN objects are used 100% of the time throughout the entire data
  pipeline whenever something is logically a dn.

* Many classes now enforce DN usage for their attributes which are
  dn's. This is implmented via ipautil.dn_attribute_property(). The
  only permitted types for a class attribute specified to be a DN are
  either None or a DN object.

* Require that every place a dn is used it must be a DN object.
  This translates into lot of::

    assert isinstance(dn, DN)

  sprinkled through out the code. Maintaining these asserts is
  valuable to preserve DN type enforcement. The asserts can be
  disabled in production.

  The goal of 100% DN usage 100% of the time has been realized, these
  asserts are meant to preserve that.

  The asserts also proved valuable in detecting functions which did
  not obey their function signatures, such as the baseldap pre and
  post callbacks.

* Moved ipalib.dn to ipapython.dn because DN class is shared with all
  components, not just the server which uses ipalib.

* All API's now accept DN's natively, no need to convert to str (or
  unicode).

* Removed ipalib.encoder and encode/decode decorators. Type conversion
  is now explicitly performed in each IPASimpleLDAPObject method which
  emulates a ldap.SimpleLDAPObject method.

* Entity & Entry classes now utilize DN's

* Removed __getattr__ in Entity & Entity clases. There were two
  problems with it. It presented synthetic Python object attributes
  based on the current LDAP data it contained. There is no way to
  validate synthetic attributes using code checkers, you can't search
  the code to find LDAP attribute accesses (because synthetic
  attriutes look like Python attributes instead of LDAP data) and
  error handling is circumscribed. Secondly __getattr__ was hiding
  Python internal methods which broke class semantics.

* Replace use of methods inherited from ldap.SimpleLDAPObject via
  IPAdmin class with IPAdmin methods. Directly using inherited methods
  was causing us to bypass IPA logic. Mostly this meant replacing the
  use of search_s() with getEntry() or getList(). Similarly direct
  access of the LDAP data in classes using IPAdmin were replaced with
  calls to getValue() or getValues().

* Objects returned by ldap2.find_entries() are now compatible with
  either the python-ldap access methodology or the Entity/Entry access
  methodology.

* All ldap operations now funnel through the common
  IPASimpleLDAPObject giving us a single location where we interface
  to python-ldap and perform conversions.

* The above 4 modifications means we've greatly reduced the
  proliferation of multiple inconsistent ways to perform LDAP
  operations. We are well on the way to having a single API in IPA for
  doing LDAP (a long range goal).

* All certificate subject bases are now DN's

* DN objects were enhanced thusly:
  - find, rfind, index, rindex, replace and insert methods were added
  - AVA, RDN and DN classes were refactored in immutable and mutable
    variants, the mutable variants are EditableAVA, EditableRDN and
    EditableDN. By default we use the immutable variants preserving
    important semantics. To edit a DN cast it to an EditableDN and
    cast it back to DN when done editing. These issues are fully
    described in other documentation.
  - first_key_match was removed
  - DN equalty comparison permits comparison to a basestring

* Fixed ldapupdate to work with DN's. This work included:
  - Enhance test_updates.py to do more checking after applying
    update. Add test for update_from_dict(). Convert code to use
    unittest classes.
  - Consolidated duplicate code.
  - Moved code which should have been in the class into the class.
  - Fix the handling of the 'deleteentry' update action. It's no longer
    necessary to supply fake attributes to make it work. Detect case
    where subsequent update applies a change to entry previously marked
    for deletetion. General clean-up and simplification of the
    'deleteentry' logic.
  - Rewrote a couple of functions to be clearer and more Pythonic.
  - Added documentation on the data structure being used.
  - Simplfy the use of update_from_dict()

* Removed all usage of get_schema() which was being called prior to
  accessing the .schema attribute of an object. If a class is using
  internal lazy loading as an optimization it's not right to require
  users of the interface to be aware of internal
  optimization's. schema is now a property and when the schema
  property is accessed it calls a private internal method to perform
  the lazy loading.

* Added SchemaCache class to cache the schema's from individual
  servers. This was done because of the observation we talk to
  different LDAP servers, each of which may have it's own
  schema. Previously we globally cached the schema from the first
  server we connected to and returned that schema in all contexts. The
  cache includes controls to invalidate it thus forcing a schema
  refresh.

* Schema caching is now senstive to the run time context. During
  install and upgrade the schema can change leading to errors due to
  out-of-date cached schema. The schema cache is refreshed in these
  contexts.

* We are aware of the LDAP syntax of all LDAP attributes. Every
  attribute returned from an LDAP operation is passed through a
  central table look-up based on it's LDAP syntax. The table key is
  the LDAP syntax it's value is a Python callable that returns a
  Python object matching the LDAP syntax. There are a handful of LDAP
  attributes whose syntax is historically incorrect
  (e.g. DistguishedNames that are defined as DirectoryStrings). The
  table driven conversion mechanism is augmented with a table of
  hard coded exceptions.

  Currently only the following conversions occur via the table:

  - dn's are converted to DN objects

  - binary objects are converted to Python str objects (IPA
    convention).

  - everything else is converted to unicode using UTF-8 decoding (IPA
    convention).

  However, now that the table driven conversion mechanism is in place
  it would be trivial to do things such as converting attributes
  which have LDAP integer syntax into a Python integer, etc.

* Expected values in the unit tests which are a DN no longer need to
  use lambda expressions to promote the returned value to a DN for
  equality comparison. The return value is automatically promoted to
  a DN. The lambda expressions have been removed making the code much
  simpler and easier to read.

* Add class level logging to a number of classes which did not support
  logging, less need for use of root_logger.

* Remove ipaserver/conn.py, it was unused.

* Consolidated duplicate code wherever it was found.

* Fixed many places that used string concatenation to form a new
  string rather than string formatting operators. This is necessary
  because string formatting converts it's arguments to a string prior
  to building the result string. You can't concatenate a string and a
  non-string.

* Simplify logic in rename_managed plugin. Use DN operators to edit
  dn's.

* The live version of ipa-ldap-updater did not generate a log file.
  The offline version did, now both do.

https://fedorahosted.org/freeipa/ticket/1670
https://fedorahosted.org/freeipa/ticket/1671
https://fedorahosted.org/freeipa/ticket/1672
https://fedorahosted.org/freeipa/ticket/1673
https://fedorahosted.org/freeipa/ticket/1674
https://fedorahosted.org/freeipa/ticket/1392
https://fedorahosted.org/freeipa/ticket/2872
This commit is contained in:
John Dennis 2012-05-13 07:36:35 -04:00 committed by Rob Crittenden
parent be9614654e
commit 94d457e83c
123 changed files with 5520 additions and 4179 deletions

14
API.txt
View File

@ -491,7 +491,7 @@ output: Output('value', <type 'unicode'>, None)
command: cosentry_add
args: 1,7,3
arg: Str('cn', attribute=True, cli_name='cn', multivalue=False, primary_key=True, required=True)
option: Str('krbpwdpolicyreference', attribute=True, cli_name='krbpwdpolicyreference', multivalue=False, required=True)
option: DNParam('krbpwdpolicyreference', attribute=True, cli_name='krbpwdpolicyreference', multivalue=False, required=True)
option: Int('cospriority', attribute=True, cli_name='cospriority', minvalue=0, multivalue=False, required=True)
option: Str('setattr*', cli_name='setattr', exclude='webui')
option: Str('addattr*', cli_name='addattr', exclude='webui')
@ -512,7 +512,7 @@ command: cosentry_find
args: 1,9,4
arg: Str('criteria?', noextrawhitespace=False)
option: Str('cn', attribute=True, autofill=False, cli_name='cn', multivalue=False, primary_key=True, query=True, required=False)
option: Str('krbpwdpolicyreference', attribute=True, autofill=False, cli_name='krbpwdpolicyreference', multivalue=False, query=True, required=False)
option: DNParam('krbpwdpolicyreference', attribute=True, autofill=False, cli_name='krbpwdpolicyreference', multivalue=False, query=True, required=False)
option: Int('cospriority', attribute=True, autofill=False, cli_name='cospriority', minvalue=0, multivalue=False, query=True, required=False)
option: Int('timelimit?', autofill=False, minvalue=0)
option: Int('sizelimit?', autofill=False, minvalue=0)
@ -527,7 +527,7 @@ output: Output('truncated', <type 'bool'>, None)
command: cosentry_mod
args: 1,9,3
arg: Str('cn', attribute=True, cli_name='cn', multivalue=False, primary_key=True, query=True, required=True)
option: Str('krbpwdpolicyreference', attribute=True, autofill=False, cli_name='krbpwdpolicyreference', multivalue=False, required=False)
option: DNParam('krbpwdpolicyreference', attribute=True, autofill=False, cli_name='krbpwdpolicyreference', multivalue=False, required=False)
option: Int('cospriority', attribute=True, autofill=False, cli_name='cospriority', minvalue=0, multivalue=False, required=False)
option: Str('setattr*', cli_name='setattr', exclude='webui')
option: Str('addattr*', cli_name='addattr', exclude='webui')
@ -1931,9 +1931,9 @@ command: migrate_ds
args: 2,16,4
arg: Str('ldapuri', cli_name='ldap_uri')
arg: Password('bindpw', cli_name='password', confirm=False)
option: Str('binddn?', autofill=True, cli_name='bind_dn', default=u'cn=directory manager')
option: Str('usercontainer', autofill=True, cli_name='user_container', default=u'ou=people')
option: Str('groupcontainer', autofill=True, cli_name='group_container', default=u'ou=groups')
option: DNParam('binddn?', autofill=True, cli_name='bind_dn', default=ipapython.dn.DN('cn=directory manager'))
option: DNParam('usercontainer', autofill=True, cli_name='user_container', default=ipapython.dn.DN('ou=people'))
option: DNParam('groupcontainer', autofill=True, cli_name='group_container', default=ipapython.dn.DN('ou=groups'))
option: Str('userobjectclass+', autofill=True, cli_name='user_objectclass', csv=True, default=(u'person',))
option: Str('groupobjectclass+', autofill=True, cli_name='group_objectclass', csv=True, default=(u'groupOfUniqueNames', u'groupOfNames'))
option: Str('userignoreobjectclass*', autofill=True, cli_name='user_ignore_objectclass', csv=True, default=())
@ -1943,7 +1943,7 @@ option: Str('groupignoreattribute*', autofill=True, cli_name='group_ignore_attri
option: Flag('groupoverwritegid', autofill=True, cli_name='group_overwrite_gid', default=False)
option: StrEnum('schema?', autofill=True, cli_name='schema', default=u'RFC2307bis', values=(u'RFC2307bis', u'RFC2307'))
option: Flag('continue?', autofill=True, default=False)
option: Str('basedn?', cli_name='base_dn')
option: DNParam('basedn?', cli_name='base_dn')
option: Flag('compat?', autofill=True, cli_name='with_compat', default=False)
option: Str('exclude_groups*', autofill=True, cli_name='exclude_groups', csv=True, default=())
option: Str('exclude_users*', autofill=True, cli_name='exclude_users', csv=True, default=())

View File

@ -31,6 +31,7 @@ from optparse import OptionParser
import ipachangeconf
import ldap
from ldap import LDAPError
from ipapython.dn import DN
class ipaserver:
@ -90,7 +91,8 @@ class ipaserver:
#search and return known realms
root_logger.debug("Search for (objectClass=krbRealmContainer) in "+self.basedn+"(sub)")
lret = lh.search_s("cn=kerberos,"+self.basedn, ldap.SCOPE_SUBTREE, "(objectClass=krbRealmContainer)")
lret = lh.search_s(str(DN(('cn', 'kerberos'), self.basedn)),
ldap.SCOPE_SUBTREE, "(objectClass=krbRealmContainer)")
if not lret:
#something very wrong
return False
@ -272,8 +274,8 @@ def main():
{'name':'ldap_version', 'type':'option', 'value':'3'},
{'name':'base', 'type':'option', 'value':ipasrv.getBaseDN()},
{'name':'empty', 'type':'empty'},
{'name':'nss_base_passwd', 'type':'option', 'value':'cn=users,cn=accounts,'+ipasrv.getBaseDN()+'?sub'},
{'name':'nss_base_group', 'type':'option', 'value':'cn=users,cn=accounts,'+ipasrv.getBaseDN()+'?sub'},
{'name':'nss_base_passwd', 'type':'option', 'value':str(DN(('cn', 'users'), ('cn', 'accounts'), ipasrv.getBaseDN()))+'?sub'},
{'name':'nss_base_group', 'type':'option', 'value':str(DN(('cn', 'users'), ('cn', 'accounts'), ipasrv.getBaseDN()))+'?sub'},
{'name':'nss_schema', 'type':'option', 'value':'rfc2307bis'},
{'name':'nss_map_attribute', 'type':'option', 'value':'uniqueMember member'},
{'name':'nss_initgroups_ignoreusers', 'type':'option', 'value':'root,dirsrv'},

View File

@ -29,7 +29,7 @@ import tempfile
import krbV
import syslog
from ipalib import api
from ipalib.dn import DN
from ipapython.dn import DN
from ipalib import errors
from ipalib import x509
from ipapython import services as ipaservices
@ -52,7 +52,7 @@ api.finalize()
# Update or add it
tmpdir = tempfile.mkdtemp(prefix = "tmp-")
try:
dn = str(DN(('cn',nickname),('cn=ca_renewal,cn=ipa,cn=etc'),(api.env.basedn)))
dn = DN(('cn', nickname), ('cn', 'ca_renewal'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
principal = str('host/%s@%s' % (api.env.host, api.env.realm))
ccache = ipautil.kinit_hostprincipal('/etc/krb5.keytab', tmpdir, principal)
conn = ldap2(shared_instance=False, ldap_uri=api.env.ldap_uri)

View File

@ -27,6 +27,7 @@ import ldap
import wsgiref
from ipapython.ipa_log_manager import *
from ipapython.ipautil import get_ipa_basedn
from ipapython.dn import DN
BASE_DN = ''
LDAP_URI = 'ldaps://localhost:636'
@ -80,10 +81,10 @@ def bind(username, password):
if not base_dn:
root_logger.error('migration unable to get base dn')
raise IOError(errno.EIO, 'Cannot get Base DN')
bind_dn = 'uid=%s,cn=users,cn=accounts,%s' % (username, base_dn)
bind_dn = DN(('uid', username), ('cn', 'users'), ('cn', 'accounts'), base_dn)
try:
conn = ldap.initialize(LDAP_URI)
conn.simple_bind_s(bind_dn, password)
conn.simple_bind_s(str(bind_dn), password)
except (ldap.INVALID_CREDENTIALS, ldap.UNWILLING_TO_PERFORM,
ldap.NO_SUCH_OBJECT), e:
root_logger.error('migration invalid credentials for %s: %s' % (bind_dn, convert_exception(e)))

View File

@ -26,7 +26,7 @@ import tempfile
import krbV
import syslog
from ipalib import api
from ipalib.dn import DN
from ipapython.dn import DN
from ipalib import errors
from ipapython import services as ipaservices
from ipapython import ipautil
@ -50,7 +50,7 @@ if not cert:
# Update or add it
tmpdir = tempfile.mkdtemp(prefix = "tmp-")
try:
dn = str(DN(('cn',nickname),('cn=ca_renewal,cn=ipa,cn=etc'),(api.env.basedn)))
dn = DN(('cn',nickname), ('cn', 'ca_renewal'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
principal = str('host/%s@%s' % (api.env.host, api.env.realm))
ccache = ipautil.kinit_hostprincipal('/etc/krb5.keytab', tmpdir, principal)
conn = ldap2(shared_instance=False, ldap_uri=api.env.ldap_uri)

View File

@ -29,7 +29,7 @@ from ipapython import ipautil
from ipaserver.install import certs
from ipaserver.install.cainstance import DEFAULT_DSPORT
from ipalib import api
from ipalib.dn import DN
from ipapython.dn import DN
from ipalib import x509
from ipalib import errors
from ipaserver.plugins.ldap2 import ldap2
@ -45,7 +45,7 @@ subject = x509.get_subject(cert, datatype=x509.DER)
issuer = x509.get_issuer(cert, datatype=x509.DER)
# Load it into dogtag
dn = str(DN(('uid','ipara'),('ou','People'),('o','ipaca')))
dn = DN(('uid','ipara'),('ou','People'),('o','ipaca'))
try:
dm_password = get_pin('internaldb')
@ -55,7 +55,7 @@ except IOError, e:
try:
conn = ldap2(shared_instance=False, ldap_uri='ldap://localhost:%d' % DEFAULT_DSPORT)
conn.connect(bind_dn='cn=directory manager', bind_pw=dm_password)
conn.connect(bind_dn=DN(('cn', 'directory manager')), bind_pw=dm_password)
(entry_dn, entry_attrs) = conn.get_entry(dn, ['usercertificate'], normalize=False)
entry_attrs['usercertificate'].append(cert)
entry_attrs['description'] = '2;%d;%s;%s' % (serial_number, issuer, subject)
@ -68,7 +68,7 @@ except Exception, e:
# Store it in the IPA LDAP server
tmpdir = tempfile.mkdtemp(prefix = "tmp-")
try:
dn = str(DN(('cn','ipaCert'),('cn=ca_renewal,cn=ipa,cn=etc'),(api.env.basedn)))
dn = DN(('cn','ipaCert'), ('cn', 'ca_renewal'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
principal = str('host/%s@%s' % (api.env.host, api.env.realm))
ccache = ipautil.kinit_hostprincipal('/etc/krb5.keytab', tmpdir, principal)
conn = ldap2(shared_instance=False, ldap_uri=api.env.ldap_uri)

View File

@ -32,6 +32,7 @@ from ipapython.config import IPAOptionParser
import krbV
import ldap
from ipapython.ipa_log_manager import *
from ipapython.dn import DN
log_file_name = "/var/log/ipaserver-install.log"

View File

@ -28,6 +28,7 @@ try:
from ipaserver.plugins.ldap2 import ldap2
from ipalib import api, errors
from ipapython.ipa_log_manager import *
from ipapython.dn import DN
except ImportError:
print >> sys.stderr, """\
There was a problem importing one of the required Python modules. The
@ -37,8 +38,8 @@ error was:
""" % sys.exc_value
sys.exit(1)
compat_dn = "cn=Schema Compatibility,cn=plugins,cn=config"
nis_config_dn = "cn=NIS Server,cn=plugins,cn=config"
compat_dn = DN(('cn', 'Schema Compatibility'), ('cn', 'plugins'), ('cn', 'config'))
nis_config_dn = DN(('cn', 'NIS Server'), ('cn', 'plugins'), ('cn', 'config'))
def parse_options():
usage = "%prog [options] <enable|disable>\n"
@ -107,7 +108,7 @@ def main():
try:
conn = ldap2(shared_instance=False, base_dn='')
conn.connect(
bind_dn='cn=directory manager', bind_pw=dirman_password
bind_dn=DN(('cn', 'directory manager')), bind_pw=dirman_password
)
except errors.ExecutionError, lde:
sys.exit("An error occurred while connecting to the server.\n%s\n" % str(lde))

View File

@ -36,6 +36,7 @@ try:
from ipaserver.plugins.ldap2 import ldap2
from ipalib import api, errors, backend
from ipaserver.install import installutils
from ipapython.dn import DN
except ImportError, e:
# If python-rhsm isn't installed exit gracefully and quietly.
if e.args[0] == 'No module named rhsm.certificate':
@ -116,7 +117,7 @@ def check_compliance(tmpdir, debug=False):
# Get the hosts first
try:
(entries, truncated) = conn.find_entries('(krblastpwdchange=*)', ['dn'],
'%s,%s' % (api.env.container_host, api.env.basedn),
DN(api.env.container_host, api.env.basedn),
conn.SCOPE_ONELEVEL,
size_limit = -1)
except errors.NotFound:
@ -136,7 +137,7 @@ def check_compliance(tmpdir, debug=False):
try:
(entries, truncated) = conn.find_entries('(objectclass=ipaentitlement)',
['dn', 'userCertificate'],
'%s,%s' % (api.env.container_entitlements, api.env.basedn),
DN(api.env.container_entitlements, api.env.basedn),
conn.SCOPE_ONELEVEL,
size_limit = -1)

View File

@ -30,7 +30,7 @@ from ipaserver.install import replication, installutils
from ipaserver import ipaldap
from ipapython import version
from ipalib import api, errors, util
from ipalib.dn import DN
from ipapython.dn import DN
CACERT = "/etc/ipa/ca.crt"
PORT = 7389
@ -63,7 +63,7 @@ class CSReplicationManager(replication.ReplicationManager):
def __init__(self, realm, hostname, dirman_passwd, port=PORT, starttls=True):
super(CSReplicationManager, self).__init__(realm, hostname, dirman_passwd, port, starttls)
self.suffix = 'o=ipaca'
self.suffix = DN(('o', 'ipaca'))
self.hostnames = [] # set before calling or agreement_dn() will fail
def agreement_dn(self, hostname, master=None):
@ -89,14 +89,14 @@ class CSReplicationManager(replication.ReplicationManager):
else:
name = "clone"
cn="%sAgreement1-%s-%s" % (name, hostname, instance_name)
dn = str(DN("cn=%s, %s" % (cn, self.replica_dn())))
dn = DN(('cn', cn), self.replica_dn())
return (cn, dn)
for host in self.hostnames:
for master in ["master", "clone"]:
try:
cn="%sAgreement1-%s-%s" % (master, host, instance_name)
dn = "cn=%s, %s" % (cn, self.replica_dn())
dn = DN(('cn', cn), self.replica_dn())
self.conn.getEntry(dn, ldap.SCOPE_BASE)
return (cn, dn)
except errors.NotFound:
@ -106,12 +106,10 @@ class CSReplicationManager(replication.ReplicationManager):
raise errors.NotFound(reason='No agreement found for %s' % hostname)
def delete_referral(self, hostname):
esc1_suffix = self.suffix.replace('=', '\\3D').replace(',', '\\2C')
esc2_suffix = self.suffix.replace('=', '%3D').replace(',', '%2C')
dn = 'cn=%s,cn=mapping tree,cn=config' % esc1_suffix
dn = DN(('cn', self.suffix), ('cn', 'mapping tree'), ('cn', 'config'))
# TODO: should we detect proto/port somehow ?
mod = [(ldap.MOD_DELETE, 'nsslapd-referral',
'ldap://%s/%s' % (ipautil.format_netloc(hostname, PORT), esc2_suffix))]
'ldap://%s/%s' % (ipautil.format_netloc(hostname, PORT), self.suffix))]
try:
self.conn.modify_s(dn, mod)
@ -165,16 +163,16 @@ def list_replicas(realm, host, replica, dirman_passwd, verbose):
conn = ipaldap.IPAdmin(host, 636, cacert=CACERT)
conn.do_simple_bind(bindpw=dirman_passwd)
dn = str(DN('cn=masters,cn=ipa,cn=etc,%s' % ipautil.realm_to_suffix(realm)))
entries = conn.search_s(dn, ldap.SCOPE_ONELEVEL)
dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), ipautil.realm_to_suffix(realm))
entries = conn.getList(dn, ldap.SCOPE_ONELEVEL)
for ent in entries:
try:
cadn = DN(('cn', 'CA'), DN(ent.dn))
entry = conn.getEntry(str(cadn), ldap.SCOPE_BASE)
peers[ent.cn] = ['master', '']
entry = conn.getEntry(cadn, ldap.SCOPE_BASE)
peers[ent.getValue('cn')] = ['master', '']
except errors.NotFound:
peers[ent.cn] = ['CA not configured', '']
peers[ent.getValue('cn')] = ['CA not configured', '']
except Exception, e:
sys.exit("Failed to get data from '%s': %s" % (host, convert_error(e)))
@ -190,13 +188,13 @@ def list_replicas(realm, host, replica, dirman_passwd, verbose):
entries = repl.find_replication_agreements()
for entry in entries:
print '%s' % entry.nsds5replicahost
print '%s' % entry.getValue('nsds5replicahost')
if verbose:
print " last init status: %s" % entry.nsds5replicalastinitstatus
print " last init ended: %s" % str(ipautil.parse_generalized_time(entry.nsds5replicalastinitend))
print " last update status: %s" % entry.nsds5replicalastupdatestatus
print " last update ended: %s" % str(ipautil.parse_generalized_time(entry.nsds5replicalastupdateend))
print " last init status: %s" % entry.getValue('nsds5replicalastinitstatus')
print " last init ended: %s" % str(ipautil.parse_generalized_time(entry.getValue('nsds5replicalastinitend')))
print " last update status: %s" % entry.getValue('nsds5replicalastupdatestatus')
print " last update ended: %s" % str(ipautil.parse_generalized_time(entry.getValue('nsds5replicalastupdateend')))
def del_link(realm, replica1, replica2, dirman_passwd, force=False):
@ -316,7 +314,8 @@ def add_link(realm, replica1, replica2, dirman_passwd, options):
conn = ipaldap.IPAdmin(replica2, 636, cacert=CACERT)
conn.do_simple_bind(bindpw=dirman_passwd)
dn = str(DN('cn=CA,cn=%s,cn=masters,cn=ipa,cn=etc,%s' % (replica2, ipautil.realm_to_suffix(realm))))
dn = DN(('cn', 'CA'), ('cn', replica2), ('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'),
ipautil.realm_to_suffix(realm))
conn.search_s(dn, ldap.SCOPE_ONELEVEL)
conn.unbind_s()
except ldap.NO_SUCH_OBJECT:
@ -341,7 +340,7 @@ def add_link(realm, replica1, replica2, dirman_passwd, options):
except Exception, e:
sys.exit("Failed to get data from '%s': %s" % (replica1, convert_error(e)))
repl1.setup_replication(replica2, PORT, 0, "cn=Directory Manager", dirman_passwd, True, True)
repl1.setup_replication(replica2, PORT, 0, DN(('cn', 'Directory Manager')), dirman_passwd, True, True)
print "Connected '%s' to '%s'" % (replica1, replica2)
def re_initialize(realm, options):
@ -355,7 +354,7 @@ def re_initialize(realm, options):
thishost = installutils.get_fqdn()
filter = "(&(nsDS5ReplicaHost=%s)(|(objectclass=nsDSWindowsReplicationAgreement)(objectclass=nsds5ReplicationAgreement)))" % thishost
entry = repl.conn.search_s("cn=config", ldap.SCOPE_SUBTREE, filter)
entry = repl.conn.search_s(DN(('cn', 'config')), ldap.SCOPE_SUBTREE, filter)
if len(entry) == 0:
root_logger.error("Unable to find %s -> %s replication agreement" % (options.fromhost, thishost))
sys.exit(1)

View File

@ -202,7 +202,7 @@ def main():
root_logger.debug("will use dns_forwarders: %s\n", str(dns_forwarders))
if bind.dm_password:
api.Backend.ldap2.connect(bind_dn="cn=Directory Manager", bind_pw=bind.dm_password)
api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')), bind_pw=bind.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

View File

@ -28,8 +28,8 @@ try:
from ipaserver import ipaldap
from ipaserver.plugins.ldap2 import ldap2
from ipalib import api, errors
from ipalib.dn import *
from ipapython.ipa_log_manager import *
from ipapython.dn import DN
except ImportError:
print >> sys.stderr, """\
@ -92,9 +92,8 @@ def main():
('cn', 'Definitions'),
('cn', 'Managed Entries'),
('cn', 'etc'),
DN(api.env.basedn)
api.env.basedn
)
managed_entry_definitions_dn = str(managed_entry_definitions_dn)
conn = None
try:
@ -125,13 +124,13 @@ def main():
# List available Managed Entry Plugins
managed_entries = None
try:
entries = conn.search_s(
entries = conn.getList(
managed_entry_definitions_dn, ldap.SCOPE_SUBTREE, filter
)
except Exception, e:
root_logger.debug("Search for managed entries failed: %s" % str(e))
sys.exit("Unable to find managed entries at %s" % managed_entry_definitions_dn)
managed_entries = [entry.cn for entry in entries]
managed_entries = [entry.getValue('cn') for entry in entries]
if managed_entries:
print "Available Managed Entry Definitions:"
for managed_entry in managed_entries:
@ -142,22 +141,18 @@ def main():
if not options.managed_entry:
sys.exit("\nYou must specify a managed entry definition")
else:
rdn = DN(
('cn', options.managed_entry),
DN(managed_entry_definitions_dn)
)
def_dn = str(rdn)
def_dn = DN(('cn', options.managed_entry), managed_entry_definitions_dn)
disabled = True
try:
entries = conn.search_s(def_dn,
entry = conn.getEntry(def_dn,
ldap.SCOPE_BASE,
filter,
['originfilter'],
)
disable_attr = '(objectclass=disable)'
try:
org_filter = entries[0].originfilter
org_filter = entry.getValue('originfilter')
disabled = re.search(r'%s' % disable_attr, org_filter)
except KeyError:
sys.exit("%s is not a valid Managed Entry" % def_dn)

View File

@ -30,6 +30,7 @@ try:
from ipaserver.plugins.ldap2 import ldap2
from ipalib import api, errors
from ipapython.ipa_log_manager import *
from ipapython.dn import DN
except ImportError:
print >> sys.stderr, """\
There was a problem importing one of the required Python modules. The
@ -39,8 +40,8 @@ error was:
""" % sys.exc_value
sys.exit(1)
nis_config_dn = "cn=NIS Server,cn=plugins,cn=config"
compat_dn = "cn=Schema Compatibility,cn=plugins,cn=config"
nis_config_dn = DN(('cn', 'NIS Server'), ('cn', 'plugins'), ('cn', 'config'))
compat_dn = DN(('cn', 'Schema Compatibility'), ('cn', 'plugins'), ('cn', 'config'))
def parse_options():
usage = "%prog [options] <enable|disable>\n"
@ -120,7 +121,7 @@ def main():
try:
conn = ldap2(shared_instance=False, base_dn='')
conn.connect(
bind_dn='cn=directory manager', bind_pw=dirman_password
bind_dn=DN(('cn', 'directory manager')), bind_pw=dirman_password
)
except errors.ExecutionError, lde:
sys.exit("An error occurred while connecting to the server: %s" % str(lde))

View File

@ -36,12 +36,13 @@ from ipaserver.install.installutils import ReplicaConfig, expand_replica_info, r
from ipaserver.install.installutils import get_host_name, BadHostError
from ipaserver.plugins.ldap2 import ldap2
from ipaserver.install import cainstance
from ipapython import version
from ipalib import api, errors, util
from ipapython import version
from ipapython.config import IPAOptionParser
from ipapython import sysrestore
from ipapython import services as ipaservices
from ipapython.ipa_log_manager import *
from ipapython.dn import DN
log_file_name = "/var/log/ipareplica-install.log"
CACERT = "/etc/ipa/ca.crt"
@ -204,7 +205,7 @@ def install_http(config, auto_redirect):
return http
def install_bind(config, options):
api.Backend.ldap2.connect(bind_dn="cn=Directory Manager",
api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')),
bind_pw=config.dirman_password)
if options.forwarders:
forwarders = options.forwarders
@ -246,7 +247,7 @@ def install_dns_records(config, options):
cur_uri = api.Backend.ldap2.ldap_uri
object.__setattr__(api.Backend.ldap2, 'ldap_uri',
'ldaps://%s' % ipautil.format_netloc(config.master_host_name))
api.Backend.ldap2.connect(bind_dn="cn=Directory Manager",
api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')),
bind_pw=config.dirman_password,
tls_cacertfile=CACERT)
bind = bindinstance.BindInstance(dm_password=config.dirman_password)
@ -360,10 +361,10 @@ def main():
try:
fd = open("/etc/ipa/default.conf", "w")
fd.write("[global]\n")
fd.write("host=" + config.host_name + "\n")
fd.write("basedn=" + ipautil.realm_to_suffix(config.realm_name) + "\n")
fd.write("realm=" + config.realm_name + "\n")
fd.write("domain=" + config.domain_name + "\n")
fd.write("host=%s\n" % config.host_name)
fd.write("basedn=%s\n" % str(ipautil.realm_to_suffix(config.realm_name)))
fd.write("realm=%s\n" % config.realm_name)
fd.write("domain=%s\n" % config.domain_name)
fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % ipautil.format_netloc(config.host_name))
fd.write("ldap_uri=ldapi://%%2fvar%%2frun%%2fslapd-%s.socket\n" % dsinstance.realm_to_serverid(config.realm_name))
if ipautil.file_exists(config.dir + "/cacert.p12"):
@ -404,14 +405,14 @@ def main():
ldapuri = 'ldaps://%s' % ipautil.format_netloc(config.master_host_name)
try:
conn = ldap2(shared_instance=False, ldap_uri=ldapuri, base_dn='')
conn.connect(bind_dn='cn=directory manager',
conn.connect(bind_dn=DN(('cn', 'directory manager')),
bind_pw=config.dirman_password,
tls_cacertfile=CACERT)
replman = ReplicationManager(config.realm_name, config.master_host_name,
config.dirman_password)
found = False
try:
entry = conn.find_entries(u'fqdn=%s' % host, ['dn', 'fqdn'], u'%s,%s' % (api.env.container_host, api.env.basedn))
entry = conn.find_entries(u'fqdn=%s' % host, ['dn', 'fqdn'], DN(api.env.container_host, api.env.basedn))
print "The host %s already exists on the master server.\nYou should remove it before proceeding:" % host
print " %% ipa host-del %s" % host
found = True

View File

@ -29,8 +29,8 @@ from ipaserver.install import bindinstance
from ipaserver import ipaldap
from ipapython import version
from ipalib import api, errors, util
from ipalib.dn import DN
from ipapython.ipa_log_manager import *
from ipapython.dn import DN
CACERT = "/etc/ipa/ca.crt"
@ -125,23 +125,28 @@ def list_replicas(realm, host, replica, dirman_passwd, verbose):
conn.do_simple_bind(bindpw=dirman_passwd)
else:
conn.do_sasl_gssapi_bind()
dn = 'cn=masters,cn=ipa,cn=etc,%s' % ipautil.realm_to_suffix(realm)
entries = conn.search_s(dn, ldap.SCOPE_ONELEVEL)
for ent in entries:
peers[ent.cn] = ['master', '']
dn = 'cn=replicas,cn=ipa,cn=etc,%s' % ipautil.realm_to_suffix(realm)
entries = conn.search_s(dn, ldap.SCOPE_ONELEVEL)
for ent in entries:
peers[ent.cn] = ent.ipaconfigstring.split(':')
except Exception, e:
print "Failed to get data from '%s': %s" % (host, str(e))
print "Failed to connect to host '%s': %s" % (host, str(e))
return
dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), ipautil.realm_to_suffix(realm))
try:
entries = conn.getList(dn, ldap.SCOPE_ONELEVEL)
except:
print "Failed read master data from '%s': %s" % (host, str(e))
return
else:
for ent in entries:
peers[ent.getValue('cn')] = ['master', '']
dn = DN(('cn', 'replicas'), ('cn', 'ipa'), ('cn', 'etc'), ipautil.realm_to_suffix(realm))
try:
entries = conn.getList(dn, ldap.SCOPE_ONELEVEL)
except:
pass
else:
for ent in entries:
peers[ent.getValue('cn')] = ent.getValue('ipaConfigString').split(':')
if not replica:
for k, p in peers.iteritems():
@ -164,8 +169,8 @@ def list_replicas(realm, host, replica, dirman_passwd, verbose):
repl = replication.ReplicationManager(realm, winsync_peer,
dirman_passwd)
cn, dn = repl.agreement_dn(replica)
entries = repl.conn.search_s(dn, ldap.SCOPE_BASE,
"(objectclass=nsDSWindowsReplicationAgreement)")
entries = repl.conn.getList(dn, ldap.SCOPE_BASE,
"(objectclass=nsDSWindowsReplicationAgreement)")
ent_type = 'winsync'
else:
repl = replication.ReplicationManager(realm, replica,
@ -177,13 +182,13 @@ def list_replicas(realm, host, replica, dirman_passwd, verbose):
return
for entry in entries:
print '%s: %s' % (entry.nsds5replicahost, ent_type)
print '%s: %s' % (entry.getValue('nsds5replicahost'), ent_type)
if verbose:
print " last init status: %s" % entry.nsds5replicalastinitstatus
print " last init ended: %s" % str(ipautil.parse_generalized_time(entry.nsds5replicalastinitend))
print " last update status: %s" % entry.nsds5replicalastupdatestatus
print " last update ended: %s" % str(ipautil.parse_generalized_time(entry.nsds5replicalastupdateend))
print " last init status: %s" % entry.getValue('nsds5replicalastinitstatus')
print " last init ended: %s" % str(ipautil.parse_generalized_time(entry.getValue('nsds5replicalastinitend')))
print " last update status: %s" % entry.getValue('nsds5replicalastupdatestatus')
print " last update ended: %s" % str(ipautil.parse_generalized_time(entry.getValue('nsds5replicalastupdateend')))
def del_link(realm, replica1, replica2, dirman_passwd, force=False):
@ -254,9 +259,9 @@ def del_link(realm, replica1, replica2, dirman_passwd, force=False):
if type1 == replication.WINSYNC:
try:
dn = 'cn=%s,cn=replicas,cn=ipa,cn=etc,%s' % (replica2,
ipautil.realm_to_suffix(realm))
entries = repl1.conn.search_s(dn, ldap.SCOPE_SUBTREE)
dn = DN(('cn', replica2), ('cn', 'replicas'), ('cn', 'ipa'), ('cn', 'etc'),
ipautil.realm_to_suffix(realm))
entries = repl1.conn.getList(dn, ldap.SCOPE_SUBTREE)
if len(entries) != 0:
dnset = repl1.conn.get_dns_sorted_by_length(entries,
reverse=True)
@ -300,11 +305,11 @@ def del_master(realm, hostname, options):
force_del = True
if force_del:
dn = 'cn=masters,cn=ipa,cn=etc,%s' % thisrepl.suffix
res = thisrepl.conn.search_s(dn, ldap.SCOPE_ONELEVEL)
dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), thisrepl.suffix)
entries = thisrepl.conn.getList(dn, ldap.SCOPE_ONELEVEL)
replica_names = []
for entry in res:
replica_names.append(entry.cn)
for entry in entries:
replica_names.append(entry.getValue('cn'))
else:
# Get list of agreements.
replica_names = delrepl.find_ipa_replication_agreements()
@ -340,7 +345,7 @@ def del_master(realm, hostname, options):
if bindinstance.dns_container_exists(options.host, thisrepl.suffix,
dm_password=options.dirman_passwd):
if options.dirman_passwd:
api.Backend.ldap2.connect(bind_dn='cn=Directory Manager',
api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')),
bind_pw=options.dirman_passwd)
else:
ccache = krbV.default_context().default_ccache().name
@ -366,7 +371,7 @@ def add_link(realm, replica1, replica2, dirman_passwd, options):
repl = replication.ReplicationManager(realm, replica1, dirman_passwd)
if repl.get_agreement_type(replica2) == replication.WINSYNC:
agreement = repl.get_replication_agreement(replica2)
sys.exit("winsync agreement already exists on subtree %s" %
sys.exit("winsync agreement already exists on subtree %s" %
agreement.getValue('nsds7WindowsReplicaSubtree'))
else:
sys.exit("A replication agreement to %s already exists" % replica2)
@ -407,8 +412,8 @@ def add_link(realm, replica1, replica2, dirman_passwd, options):
# from scratch
try:
masters_dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), (api.env.basedn))
master1_dn = str(DN(('cn', replica1), masters_dn))
master2_dn = str(DN(('cn', replica2), masters_dn))
master1_dn = DN(('cn', replica1), masters_dn)
master2_dn = DN(('cn', replica2), masters_dn)
repl1.conn.getEntry(master1_dn, ldap.SCOPE_BASE)
repl1.conn.getEntry(master2_dn, ldap.SCOPE_BASE)

View File

@ -35,6 +35,7 @@ from ipaserver.plugins.ldap2 import ldap2
from ipapython import version
from ipapython.config import IPAOptionParser
from ipalib import api, errors, util
from ipapython.dn import DN
def parse_options():
usage = "%prog [options] FQDN (e.g. replica.example.com)"
@ -99,13 +100,16 @@ def parse_options():
def get_subject_base(host_name, dm_password, suffix):
try:
conn = ldap2(shared_instance=False, base_dn=suffix)
conn.connect(bind_dn='cn=directory manager', bind_pw=dm_password)
conn.connect(bind_dn=DN(('cn', 'directory manager')), bind_pw=dm_password)
except errors.ExecutionError, e:
root_logger.critical("Could not connect to the Directory Server on %s" % host_name)
raise e
(dn, entry_attrs) = conn.get_ipa_config()
conn.disconnect()
return entry_attrs.get('ipacertificatesubjectbase', [None])[0]
subject_base = entry_attrs.get('ipacertificatesubjectbase', [None])[0]
if subject_base is not None:
subject_base = DN(subject_base)
return subject_base
def check_ipa_configuration(realm_name):
config_dir = dsinstance.config_dirname(dsinstance.realm_to_serverid(realm_name))
@ -200,7 +204,7 @@ def save_config(dir, realm_name, host_name,
config.set("realm", "master_host_name", host_name)
config.set("realm", "domain_name", domain_name)
config.set("realm", "destination_host", dest_host)
config.set("realm", "subject_base", subject_base)
config.set("realm", "subject_base", str(subject_base))
fd = open(dir + "/realm_info", "w")
config.write(fd)
@ -260,7 +264,7 @@ def main():
# Try out the password
try:
conn = ldap2(shared_instance=False)
conn.connect(bind_dn='cn=directory manager', bind_pw=dirman_password)
conn.connect(bind_dn=DN(('cn', 'directory manager')), bind_pw=dirman_password)
conn.disconnect()
except errors.ACIError:
sys.exit("\nThe password provided is incorrect for LDAP server %s" % api.env.host)
@ -431,7 +435,7 @@ def main():
if options.ip_address:
print "Adding DNS records for %s" % replica_fqdn
api.Backend.ldap2.connect(bind_dn="cn=Directory Manager", bind_pw=dirman_password)
api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')), bind_pw=dirman_password)
domain = replica_fqdn.split(".")
name = domain.pop(0)

View File

@ -32,6 +32,7 @@ from ipapython.ipautil import user_input
from ipaserver.install import certs, dsinstance, httpinstance, installutils
from ipalib import api
from ipapython.ipa_log_manager import *
from ipapython.dn import DN
from ipaserver.plugins.ldap2 import ldap2
def get_realm_name():
@ -66,9 +67,9 @@ def parse_options():
def set_ds_cert_name(cert_name, dm_password):
conn = ldap2(shared_instance=False, base_dn='')
conn.connect(bind_dn='cn=directory manager', bind_pw=dm_password)
conn.connect(bind_dn=DN(('cn', 'directory manager')), bind_pw=dm_password)
mod = {'nssslpersonalityssl': cert_name}
conn.update_entry('cn=RSA,cn=encryption,cn=config', mod)
conn.update_entry(DN(('cn', 'RSA'), ('cn', 'encryption'), ('cn', 'config')), mod)
conn.disconnect()
def choose_server_cert(server_certs):

View File

@ -60,11 +60,11 @@ from ipapython.ipautil import *
from ipapython import ipautil
from ipalib import api, errors, util
from ipapython.config import IPAOptionParser
from ipalib.dn import DN
from ipalib.x509 import load_certificate_from_file, load_certificate_chain_from_file
from ipalib.util import validate_domain_name
from ipapython import services as ipaservices
from ipapython.ipa_log_manager import *
from ipapython.dn import DN
pw_name = None
uninstalling = False
@ -530,13 +530,13 @@ def set_subject_in_config(realm_name, dm_password, suffix, subject_base):
)
try:
conn = ldap2(shared_instance=False, ldap_uri=ldapuri, base_dn=suffix)
conn.connect(bind_dn='cn=directory manager', bind_pw=dm_password)
conn.connect(bind_dn=DN(('cn', 'directory manager')), bind_pw=dm_password)
except errors.ExecutionError, e:
root_logger.critical("Could not connect to the Directory Server on %s" % realm_name)
raise e
(dn, entry_attrs) = conn.get_ipa_config()
if 'ipacertificatesubjectbase' not in entry_attrs:
mod = {'ipacertificatesubjectbase': subject_base}
mod = {'ipacertificatesubjectbase': str(subject_base)}
conn.update_entry(dn, mod)
conn.disconnect()
@ -770,7 +770,7 @@ def main():
realm_name = options.realm_name.upper()
if not options.subject:
options.subject = "O=%s" % realm_name
options.subject = DN(('O', realm_name))
if not options.dm_password:
dm_password = read_dm_password()
@ -840,10 +840,10 @@ def main():
target_fname = '/etc/ipa/default.conf'
fd = open(target_fname, "w")
fd.write("[global]\n")
fd.write("host=" + host_name + "\n")
fd.write("basedn=" + ipautil.realm_to_suffix(realm_name) + "\n")
fd.write("realm=" + realm_name + "\n")
fd.write("domain=" + domain_name + "\n")
fd.write("host=%s\n" % host_name)
fd.write("basedn=%s\n" % ipautil.realm_to_suffix(realm_name))
fd.write("realm=%s\n" % realm_name)
fd.write("domain=%s\n" % domain_name)
fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % format_netloc(host_name))
fd.write("ldap_uri=ldapi://%%2fvar%%2frun%%2fslapd-%s.socket\n" % dsinstance.realm_to_serverid(realm_name))
fd.write("enable_ra=True\n")
@ -1046,7 +1046,7 @@ def main():
persistent_search=options.persistent_search,
serial_autoincrement=options.serial_autoincrement)
if options.setup_dns:
api.Backend.ldap2.connect(bind_dn="cn=Directory Manager", bind_pw=dm_password)
api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')), bind_pw=dm_password)
bind.create_instance()
print ""

View File

@ -253,7 +253,7 @@ def update_dbmodules(realm, filename="/etc/krb5.conf"):
newfile.append('#%s' % line)
prefix = ''
continue
newfile.append('%s%s' % (prefix, line))
# Append updated dbmodules information

View File

@ -26,10 +26,10 @@ try:
from ipaserver.install.dsinstance import config_dirname, realm_to_serverid
from ipaserver.install.installutils import is_ipa_configured, ScriptError
from ipapython.ipautil import wait_for_open_ports, wait_for_open_socket
from ipalib import api, errors
from ipapython import sysrestore
from ipapython import config
from ipalib import api, errors
from ipalib.dn import DN
from ipapython.dn import DN
import ldap
import ldap.sasl
import ldapurl
@ -107,8 +107,7 @@ def emit_err(err):
sys.stderr.write(err + '\n')
def get_config(dirsrv):
base = "cn=%s,cn=masters,cn=ipa,cn=etc,%s" % (api.env.host,
api.env.basedn)
base = DN(('cn', api.env.host), ('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
srcfilter = '(ipaConfigString=enabledService)'
attrs = ['cn', 'ipaConfigString']
if not dirsrv.is_running():
@ -127,7 +126,7 @@ def get_config(dirsrv):
wait_for_open_ports(host, [int(port)], timeout=api.env.startup_timeout)
con = ldap.initialize(api.env.ldap_uri)
con.sasl_interactive_bind_s('', SASL_EXTERNAL)
res = con.search_st(base,
res = con.search_st(str(base),
ldap.SCOPE_SUBTREE,
filterstr=srcfilter,
attrlist=attrs,
@ -138,12 +137,10 @@ def get_config(dirsrv):
"Directory Server is stopped", 3)
except ldap.NO_SUCH_OBJECT:
masters_list = []
dn = str(DN('cn=masters,cn=ipa,cn=etc,%s' % api.env.basedn))
dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
attrs = ['cn']
try:
entries = con.search_s(dn,
ldap.SCOPE_ONELEVEL,
attrlist=attrs,)
entries = con.search_s(str(dn), ldap.SCOPE_ONELEVEL, attrlist=attrs)
except Exception, e:
masters_list.append("No master found because of error: %s" % str(e))
else:

View File

@ -31,12 +31,12 @@ import SSSDConfig
from optparse import OptionParser
from ipalib import api, errors
from ipalib.dn import DN
from ipapython import sysrestore
from ipapython import ipautil
from ipaclient import ipadiscovery
from ipaclient import ipachangeconf
from ipapython.ipa_log_manager import *
from ipapython.dn import DN
from ipapython import services as ipaservices
AUTOFS_CONF = '/etc/sysconfig/autofs'

View File

@ -41,6 +41,7 @@ try:
from ipapython import certmonger
from ipapython.config import IPAOptionParser
from ipalib import api, errors
from ipapython.dn import DN
import SSSDConfig
from ConfigParser import RawConfigParser
from optparse import SUPPRESS_HELP, OptionGroup
@ -510,8 +511,8 @@ def configure_ldap_conf(fstore, cli_basedn, cli_realm, cli_domain, cli_server, d
{'name':'ldap_version', 'type':'option', 'value':'3'},
{'name':'base', 'type':'option', 'value':cli_basedn},
{'name':'empty', 'type':'empty'},
{'name':'nss_base_passwd', 'type':'option', 'value':'cn=users,cn=accounts,'+cli_basedn+'?sub'},
{'name':'nss_base_group', 'type':'option', 'value':'cn=groups,cn=accounts,'+cli_basedn+'?sub'},
{'name':'nss_base_passwd', 'type':'option', 'value':str(DN(('cn', 'users'), ('cn', 'accounts'), cli_basedn))+'?sub'},
{'name':'nss_base_group', 'type':'option', 'value':str(DN(('cn', 'groups'), ('cn', 'accounts'), cli_basedn))+'?sub'},
{'name':'nss_schema', 'type':'option', 'value':'rfc2307bis'},
{'name':'nss_map_attribute', 'type':'option', 'value':'uniqueMember member'},
{'name':'nss_initgroups_ignoreusers', 'type':'option', 'value':'root,dirsrv'},
@ -555,8 +556,8 @@ def configure_nslcd_conf(fstore, cli_basedn, cli_realm, cli_domain, cli_server,
{'name':'ldap_version', 'type':'option', 'value':'3'},
{'name':'base', 'type':'option', 'value':cli_basedn},
{'name':'empty', 'type':'empty'},
{'name':'base passwd', 'type':'option', 'value':'cn=users,cn=accounts,'+cli_basedn},
{'name':'base group', 'type':'option', 'value':'cn=groups,cn=accounts,'+cli_basedn},
{'name':'base passwd', 'type':'option', 'value':str(DN(('cn', 'users'), ('cn', 'accounts'), cli_basedn))},
{'name':'base group', 'type':'option', 'value':str(DN(('cn', 'groups'), ('cn', 'accounts'), cli_basedn))},
{'name':'map group', 'type':'option', 'value':'uniqueMember member'},
{'name':'timelimit', 'type':'option', 'value':'15'},
{'name':'empty', 'type':'empty'}]
@ -743,9 +744,9 @@ def configure_certmonger(fstore, subject_base, cli_realm, hostname, options):
# Request our host cert
if started:
client_nss_nickname = client_nss_nickname_format % hostname
subject = 'CN=%s,%s' % (hostname, subject_base)
subject = DN(('CN', hostname), subject_base)
try:
run(["ipa-getcert", "request", "-d", "/etc/pki/nssdb", "-n", client_nss_nickname, "-N", subject, "-K", principal])
run(["ipa-getcert", "request", "-d", "/etc/pki/nssdb", "-n", client_nss_nickname, "-N", str(subject), "-K", principal])
except:
root_logger.error(
"%s request for host certificate failed", cmonger.service_name)
@ -1337,7 +1338,7 @@ def install(options, env, fstore, statestore):
cli_basedn = ds.basedn
cli_basedn_source = ds.basedn_source
root_logger.debug("will use discovered basedn: %s", cli_basedn)
subject_base = "O=%s" % cli_realm
subject_base = DN(('O', cli_realm))
# Now do a sanity check on the other servers
if options.server and len(options.server) > 1:
@ -1431,7 +1432,7 @@ def install(options, env, fstore, statestore):
root_logger.error("Test kerberos configuration failed")
return CLIENT_INSTALL_ERROR
env['KRB5_CONFIG'] = krb_name
join_args = ["/usr/sbin/ipa-join", "-s", cli_server[0], "-b", realm_to_suffix(cli_realm)]
join_args = ["/usr/sbin/ipa-join", "-s", cli_server[0], "-b", str(realm_to_suffix(cli_realm))]
if options.debug:
join_args.append("-d")
env['XMLRPC_TRACE_CURL'] = 'yes'
@ -1508,6 +1509,7 @@ def install(options, env, fstore, statestore):
start = start + 29
subject_base = stderr[start:]
subject_base = subject_base.strip()
subject_base = DN(subject_base)
finally:
if options.principal is not None:

View File

@ -28,7 +28,7 @@ from dns.exception import DNSException
from ipapython.ipautil import run, CalledProcessError, valid_ip, get_ipa_basedn, \
realm_to_suffix, format_netloc
from ipapython.dn import DN
NOT_FQDN = -1
NO_LDAP_SERVER = -2
@ -320,7 +320,7 @@ class IPADiscovery(object):
root_logger.debug(
"Search for (objectClass=krbRealmContainer) in %s (sub)",
self.basedn)
lret = lh.search_s("cn=kerberos,"+self.basedn, ldap.SCOPE_SUBTREE, "(objectClass=krbRealmContainer)")
lret = lh.search_s(str(DN(('cn', 'kerberos'), self.basedn)), ldap.SCOPE_SUBTREE, "(objectClass=krbRealmContainer)")
if not lret:
#something very wrong
return [REALM_NOT_FOUND]

View File

@ -878,7 +878,7 @@ from backend import Backend
from frontend import Command, LocalOrRemote, Updater
from frontend import Object, Method, Property
from crud import Create, Retrieve, Update, Delete, Search
from parameters import DefaultFrom, Bool, Flag, Int, Decimal, Bytes, Str, IA5Str, Password
from parameters import DefaultFrom, Bool, Flag, Int, Decimal, Bytes, Str, IA5Str, Password, DNParam
from parameters import BytesEnum, StrEnum, AccessTime, File
from errors import SkipPluginModule
from text import _, ngettext, GettextFactory, NGettextFactory

View File

@ -254,32 +254,6 @@ class ACI:
# We got this far so lets declare them the same
return True
def extract_group_cns(aci_list, client):
"""
Extracts all the cn's from a list of aci's and returns them as a hash
from group_dn to group_cn.
It first tries to cheat by looking at the first rdn for the
group dn. If that's not cn for some reason, it looks up the group.
"""
group_dn_to_cn = {}
for aci in aci_list:
for dn in (aci.source_group, aci.dest_group):
if not group_dn_to_cn.has_key(dn):
rdn_list = ldap.explode_dn(dn, 0)
first_rdn = rdn_list[0]
(type,value) = first_rdn.split('=')
if type == "cn":
group_dn_to_cn[dn] = value
else:
try:
group = client.get_entry_by_dn(dn, ['cn'])
group_dn_to_cn[dn] = group.getValue('cn')
except Exception:
group_dn_to_cn[dn] = 'unknown'
return group_dn_to_cn
if __name__ == '__main__':
# a = ACI('(targetattr="title")(targetfilter="(memberOf=cn=bar,cn=groups,cn=accounts ,dc=example,dc=com)")(version 3.0;acl "foobar";allow (write) groupdn="ldap:///cn=foo,cn=groups,cn=accounts,dc=example,dc=com";)')
# print a

View File

@ -35,6 +35,7 @@ import os
from os import path
import sys
from socket import getfqdn
from ipapython.dn import DN
from base import check_name
from constants import CONFIG_SECTION
@ -256,12 +257,14 @@ class Env(object):
value = m[value]
elif value.isdigit():
value = int(value)
elif key in ('basedn'):
value = DN(value)
else:
try:
value = float(value)
except (TypeError, ValueError):
pass
assert type(value) in (unicode, int, float, bool, NoneType)
assert type(value) in (unicode, int, float, bool, NoneType, DN)
object.__setattr__(self, key, value)
self.__d[key] = value

View File

@ -22,6 +22,7 @@
All constants centralised in one file.
"""
import socket
from ipapython.dn import DN
from ipapython.version import VERSION
try:
FQDN = socket.getfqdn()
@ -69,44 +70,44 @@ DEFAULT_CONFIG = (
# Domain, realm, basedn:
('domain', 'example.com'),
('realm', 'EXAMPLE.COM'),
('basedn', 'dc=example,dc=com'),
('basedn', DN(('dc', 'example'), ('dc', 'com'))),
# LDAP containers:
('container_accounts', 'cn=accounts'),
('container_user', 'cn=users,cn=accounts'),
('container_group', 'cn=groups,cn=accounts'),
('container_service', 'cn=services,cn=accounts'),
('container_host', 'cn=computers,cn=accounts'),
('container_hostgroup', 'cn=hostgroups,cn=accounts'),
('container_rolegroup', 'cn=roles,cn=accounts'),
('container_permission', 'cn=permissions,cn=pbac'),
('container_privilege', 'cn=privileges,cn=pbac'),
('container_automount', 'cn=automount'),
('container_policies', 'cn=policies'),
('container_configs', 'cn=configs,cn=policies'),
('container_roles', 'cn=roles,cn=policies'),
('container_applications', 'cn=applications,cn=configs,cn=policies'),
('container_policygroups', 'cn=policygroups,cn=configs,cn=policies'),
('container_policylinks', 'cn=policylinks,cn=configs,cn=policies'),
('container_netgroup', 'cn=ng,cn=alt'),
('container_hbac', 'cn=hbac'),
('container_hbacservice', 'cn=hbacservices,cn=hbac'),
('container_hbacservicegroup', 'cn=hbacservicegroups,cn=hbac'),
('container_dns', 'cn=dns'),
('container_virtual', 'cn=virtual operations,cn=etc'),
('container_sudorule', 'cn=sudorules,cn=sudo'),
('container_sudocmd', 'cn=sudocmds,cn=sudo'),
('container_sudocmdgroup', 'cn=sudocmdgroups,cn=sudo'),
('container_entitlements', 'cn=entitlements,cn=etc'),
('container_automember', 'cn=automember,cn=etc'),
('container_selinux', 'cn=usermap,cn=selinux'),
('container_s4u2proxy', 'cn=s4u2proxy,cn=etc'),
('container_cifsdomains', 'cn=ad,cn=etc'),
('container_trusts', 'cn=trusts'),
('container_adtrusts', 'cn=ad,cn=trusts'),
('container_ranges', 'cn=ranges,cn=etc'),
('container_dna', 'cn=dna,cn=ipa,cn=etc'),
('container_dna_posix_ids', 'cn=posix-ids,cn=dna,cn=ipa,cn=etc'),
('container_accounts', DN(('cn', 'accounts'))),
('container_user', DN(('cn', 'users'), ('cn', 'accounts'))),
('container_group', DN(('cn', 'groups'), ('cn', 'accounts'))),
('container_service', DN(('cn', 'services'), ('cn', 'accounts'))),
('container_host', DN(('cn', 'computers'), ('cn', 'accounts'))),
('container_hostgroup', DN(('cn', 'hostgroups'), ('cn', 'accounts'))),
('container_rolegroup', DN(('cn', 'roles'), ('cn', 'accounts'))),
('container_permission', DN(('cn', 'permissions'), ('cn', 'pbac'))),
('container_privilege', DN(('cn', 'privileges'), ('cn', 'pbac'))),
('container_automount', DN(('cn', 'automount'))),
('container_policies', DN(('cn', 'policies'))),
('container_configs', DN(('cn', 'configs'), ('cn', 'policies'))),
('container_roles', DN(('cn', 'roles'), ('cn', 'policies'))),
('container_applications', DN(('cn', 'applications'), ('cn', 'configs'), ('cn', 'policies'))),
('container_policygroups', DN(('cn', 'policygroups'), ('cn', 'configs'), ('cn', 'policies'))),
('container_policylinks', DN(('cn', 'policylinks'), ('cn', 'configs'), ('cn', 'policies'))),
('container_netgroup', DN(('cn', 'ng'), ('cn', 'alt'))),
('container_hbac', DN(('cn', 'hbac'))),
('container_hbacservice', DN(('cn', 'hbacservices'), ('cn', 'hbac'))),
('container_hbacservicegroup', DN(('cn', 'hbacservicegroups'), ('cn', 'hbac'))),
('container_dns', DN(('cn', 'dns'))),
('container_virtual', DN(('cn', 'virtual operations'), ('cn', 'etc'))),
('container_sudorule', DN(('cn', 'sudorules'), ('cn', 'sudo'))),
('container_sudocmd', DN(('cn', 'sudocmds'), ('cn', 'sudo'))),
('container_sudocmdgroup', DN(('cn', 'sudocmdgroups'), ('cn', 'sudo'))),
('container_entitlements', DN(('cn', 'entitlements'), ('cn', 'etc'))),
('container_automember', DN(('cn', 'automember'), ('cn', 'etc'))),
('container_selinux', DN(('cn', 'usermap'), ('cn', 'selinux'))),
('container_s4u2proxy', DN(('cn', 's4u2proxy'), ('cn', 'etc'))),
('container_cifsdomains', DN(('cn', 'ad'), ('cn', 'etc'))),
('container_trusts', DN(('cn', 'trusts'))),
('container_adtrusts', DN(('cn', 'ad'), ('cn', 'trusts'))),
('container_ranges', DN(('cn', 'ranges'), ('cn', 'etc'))),
('container_dna', DN(('cn', 'dna'), ('cn', 'ipa'), ('cn', 'etc'))),
('container_dna_posix_ids', DN(('cn', 'posix-ids'), ('cn', 'dna'), ('cn', 'ipa'), ('cn', 'etc'))),
# Ports, hosts, and URIs:
# FIXME: let's renamed xmlrpc_uri to rpc_xml_uri

View File

@ -1,213 +0,0 @@
# Authors:
# Pavel Zuna <pzuna@redhat.com>
#
# Copyright (C) 2009 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Encoding capabilities.
"""
from decimal import Decimal
class EncoderSettings(object):
"""
Container for encoder settings.
"""
encode_to = 'utf-8'
encode_none = False
encode_dict_keys = False
encode_dict_keys_postprocess = True
encode_dict_vals = True
encode_dict_vals_postprocess = True
encode_postprocessor = staticmethod(lambda x: x)
decode_from = 'utf-8'
decode_none = False
decode_dict_keys = False
decode_dict_keys_postprocess = True
decode_dict_vals = True
decode_dict_vals_postprocess = True
decode_dict_vals_table = dict()
decode_dict_vals_table_keygen = staticmethod(lambda x, y: x)
decode_postprocessor = staticmethod(lambda x: x)
class Encoder(object):
"""
Base class implementing encoding of python scalar types to strings
and vise-versa.
"""
encoder_settings = EncoderSettings()
def __init__(self):
# each instance should have its own settings
self.encoder_settings = EncoderSettings()
def _decode_dict_val(self, key, val):
f = self.encoder_settings.decode_dict_vals_table.get(
self.encoder_settings.decode_dict_vals_table_keygen(key, val)
)
if f:
return val
return self.decode(val)
def encode(self, var):
"""
Encode any python built-in python type variable into `self.encode_to`.
Compound types have their individual members encoded.
Returns an encoded copy of 'var'.
"""
if isinstance(var, str):
return var
elif isinstance(var, unicode):
return self.encoder_settings.encode_postprocessor(
var.encode(self.encoder_settings.encode_to)
)
elif isinstance(var, bool):
if var:
var = 'TRUE'
else:
var = 'FALSE'
return self.encoder_settings.encode_postprocessor(
var.encode(self.encoder_settings.encode_to)
)
elif isinstance(var, (float, Decimal, int, long)):
return self.encoder_settings.encode_postprocessor(
str(var).encode(self.encoder_settings.encode_to)
)
elif isinstance(var, list):
return [self.encode(m) for m in var]
elif isinstance(var, tuple):
return tuple(self.encode(m) for m in var)
elif isinstance(var, dict):
if self.encoder_settings.encode_dict_keys:
dct = dict()
if not self.encoder_settings.encode_dict_keys_postprocess:
tmp = self.encoder_settings.encode_postprocessor
self.encoder_settings.encode_postprocessor = lambda x: x
for (k, v) in var.iteritems():
dct[self.encode(k)] = v
if not self.encoder_settings.encode_dict_keys_postprocess:
self.encoder_settings.encode_postprocessor = tmp
else:
dct = dict(var)
if self.encoder_settings.encode_dict_vals:
if not self.encoder_settings.encode_dict_vals_postprocess:
tmp = self.encoder_settings.encode_postprocessor
self.encoder_settings.encode_postprocessor = lambda x: x
for (k, v) in dct.iteritems():
dct[k] = self.encode(v)
if not self.encoder_settings.encode_dict_vals_postprocess:
self.encoder_settings.encode_postprocessor = tmp
return dct
elif var is None:
if self.encoder_settings.encode_none:
return self.encoder_settings.encode_postprocessor(
str(var).encode(self.encoder_settings.encode_to)
)
return None
raise TypeError('python built-in type expected, got \'%s\'', type(var))
def decode(self, var):
"""
Decode strings in `self.decode_from` into python strings.
Compound types have their individual members decoded.
Dictionaries can have their values decoded into other types
by looking up keys in `self.decode_dict_vals_table`.
Returns a decoded copy of 'var'.
"""
if isinstance(var, unicode):
return var
elif isinstance(var, str):
return self.encoder_settings.decode_postprocessor(
var.decode(self.encoder_settings.decode_from)
)
elif isinstance(var, (bool, float, Decimal, int, long)):
return var
elif isinstance(var, list):
return [self.decode(m) for m in var]
elif isinstance(var, tuple):
return tuple(self.decode(m) for m in var)
elif isinstance(var, dict):
if self.encoder_settings.decode_dict_keys:
dct = dict()
if not self.encoder_settings.decode_dict_keys_postprocess:
tmp = self.encoder_settings.decode_postprocessor
self.encoder_settings.decode_postprocessor = lambda x: x
for (k, v) in var.iteritems():
dct[self.decode(k)] = v
if not self.encoder_settings.decode_dict_keys_postprocess:
self.encoder_settings.decode_postprocessor = tmp
else:
dct = dict(var)
if self.encoder_settings.decode_dict_vals:
if not self.encoder_settings.decode_dict_vals_postprocess:
tmp = self.encoder_settings.decode_postprocessor
self.encoder_settings.decode_postprocessor = lambda x: x
for (k, v) in dct.iteritems():
dct[k] = self._decode_dict_val(k, v)
if not self.encoder_settings.decode_dict_vals_postprocess:
self.encoder_settings.decode_postprocessor = tmp
return dct
elif var is None:
if self.encoder_settings.decode_none:
return self.encoder_settings.decode_postprocessor(
str(var).decode(self.encoder_settings.decode_from)
)
return None
raise TypeError('python built-in type expected, got \'%s\'', type(var))
## ENCODER METHOD DECORATORS
def encode_args(*outer_args):
def decorate(f):
def new_f(*args, **kwargs):
assert isinstance(args[0], Encoder), \
'first argument not Encoder instance'
new_args = list(args)
for a in outer_args:
if isinstance(a, int):
if a < len(args):
new_args[a] = args[0].encode(args[a])
elif isinstance(a, basestring):
if a in kwargs:
kwargs[a] = args[0].encode(kwargs[a])
else:
raise TypeError(
'encode_args takes a list of ints and basestrings'
)
return f(*new_args, **kwargs)
new_f.func_name = f.func_name
return new_f
return decorate
def decode_retval():
def decorate(f):
def new_f(*args, **kwargs):
assert isinstance(args[0], Encoder), \
'first argument not Encoder instance'
return args[0].decode(f(*args, **kwargs))
new_f.func_name = f.func_name
return new_f
return decorate

View File

@ -112,7 +112,7 @@ from errors import ConversionError, RequirementError, ValidationError
from errors import PasswordMismatch
from constants import NULLS, TYPE_ERROR, CALLABLE_ERROR
from text import Gettext, FixMe
from ipapython.dn import DN
class DefaultFrom(ReadOnly):
"""
@ -1845,6 +1845,23 @@ class AccessTime(Str):
return None
class DNParam(Param):
type = DN
def _convert_scalar(self, value, index=None):
"""
Convert a single scalar value.
"""
if type(value) is self.type:
return value
try:
dn = DN(value)
except Exception, e:
raise ConversionError(name=self.get_param_name(), index=index,
error=ugettext(e))
return dn
def create_param(spec):
"""
Create an `Str` instance from the shorthand ``spec``.

View File

@ -123,24 +123,22 @@ from ipalib import api, crud, errors
from ipalib import Object, Command
from ipalib import Flag, Int, Str, StrEnum
from ipalib.aci import ACI
from ipalib.dn import DN
from ipalib import output
from ipalib import _, ngettext
from ipalib.plugins.baseldap import gen_pkey_only_option
if api.env.in_server and api.env.context in ['lite', 'server']:
from ldap import explode_dn
from ipapython.ipa_log_manager import *
from ipapython.dn import DN
ACI_NAME_PREFIX_SEP = ":"
_type_map = {
'user': 'ldap:///uid=*,%s,%s' % (api.env.container_user, api.env.basedn),
'group': 'ldap:///cn=*,%s,%s' % (api.env.container_group, api.env.basedn),
'host': 'ldap:///fqdn=*,%s,%s' % (api.env.container_host, api.env.basedn),
'hostgroup': 'ldap:///cn=*,%s,%s' % (api.env.container_hostgroup, api.env.basedn),
'service': 'ldap:///krbprincipalname=*,%s,%s' % (api.env.container_service, api.env.basedn),
'netgroup': 'ldap:///ipauniqueid=*,%s,%s' % (api.env.container_netgroup, api.env.basedn),
'dnsrecord': 'ldap:///idnsname=*,%s,%s' % (api.env.container_dns, api.env.basedn),
'user': 'ldap:///' + str(DN(('uid', '*'), api.env.container_user, api.env.basedn)),
'group': 'ldap:///' + str(DN(('cn', '*'), api.env.container_group, api.env.basedn)),
'host': 'ldap:///' + str(DN(('fqdn', '*'), api.env.container_host, api.env.basedn)),
'hostgroup': 'ldap:///' + str(DN(('cn', '*'), api.env.container_hostgroup, api.env.basedn)),
'service': 'ldap:///' + str(DN(('krbprincipalname', '*'), api.env.container_service, api.env.basedn)),
'netgroup': 'ldap:///' + str(DN(('ipauniqueid', '*'), api.env.container_netgroup, api.env.basedn)),
'dnsrecord': 'ldap:///' + str(DN(('idnsname', '*'), api.env.container_dns, api.env.basedn)),
}
_valid_permissions_values = [
@ -247,7 +245,7 @@ def _make_aci(ldap, current, aciname, kw):
if 'test' in kw and not kw.get('test'):
raise e
else:
entry_attrs = {'dn': 'cn=%s,%s' % (kw['permission'], api.env.container_permission)}
entry_attrs = {'dn': DN(('cn', kw['permission']), api.env.container_permission)}
elif group:
# Not so friendly with groups. This will raise
try:
@ -343,10 +341,9 @@ def _aci_to_kw(ldap, a, test=False, pkey_only=False):
else:
# See if the target is a group. If so we set the
# targetgroup attr, otherwise we consider it a subtree
if api.env.container_group in target:
targetdn = unicode(target.replace('ldap:///',''))
target = DN(targetdn)
kw['targetgroup'] = target['cn']
targetdn = DN(target.replace('ldap:///',''))
if targetdn.endswith(DN(api.env.container_group, api.env.basedn)):
kw['targetgroup'] = targetdn[0]['cn']
else:
kw['subtree'] = unicode(target)
@ -357,15 +354,16 @@ def _aci_to_kw(ldap, a, test=False, pkey_only=False):
elif groupdn == 'anyone':
pass
else:
if groupdn.startswith('cn='):
dn = ''
groupdn = DN(groupdn)
if len(groupdn) and groupdn[0].attr == 'cn':
dn = DN()
entry_attrs = {}
try:
(dn, entry_attrs) = ldap.get_entry(groupdn, ['cn'])
except errors.NotFound, e:
# FIXME, use real name here
if test:
dn = 'cn=%s,%s' % ('test', api.env.container_permission)
dn = DN(('cn', 'test'), api.env.container_permission)
entry_attrs = {'cn': [u'test']}
if api.env.container_permission in dn:
kw['permission'] = entry_attrs['cn'][0]
@ -801,11 +799,11 @@ class aci_find(crud.Search):
if kw.get('group'):
for a in acis:
groupdn = a.bindrule['expression']
groupdn = groupdn.replace('ldap:///','')
cn = None
if groupdn.startswith('cn='):
cn = explode_dn(groupdn)[0]
cn = cn.replace('cn=','')
groupdn = DN(groupdn.replace('ldap:///',''))
try:
cn = groupdn[0]['cn'].value
except (IndexError, KeyError):
cn = None
if cn is None or cn != kw['group']:
try:
results.remove(a)
@ -818,9 +816,11 @@ class aci_find(crud.Search):
if 'target' in a.target:
target = a.target['target']['expression']
if api.env.container_group in target:
targetdn = unicode(target.replace('ldap:///',''))
cn = explode_dn(targetdn)[0]
cn = cn.replace('cn=','')
targetdn = DN(target.replace('ldap:///',''))
try:
cn = targetdn[0]['cn']
except (IndexError, KeyError):
cn = None
if cn == kw['targetgroup']:
found = True
if not found:

View File

@ -22,8 +22,8 @@ from ipalib import Str, StrEnum
from ipalib.plugins.baseldap import *
from ipalib import _, ngettext
from ipalib.request import context
from ipalib.dn import *
import ldap as _ldap
from ipapython.dn import DN
__doc__ = _("""
Auto Membership Rule.
@ -200,19 +200,16 @@ class automember(LDAPObject):
parent_dn = self.container_dn
grouptype = options['type']
try:
ndn = DN(('cn', keys[-1]), ('cn', grouptype), DN(parent_dn))
ndn = DN(('cn', keys[-1]), ('cn', grouptype), parent_dn)
except IndexError:
ndn = DN(('cn', grouptype), DN(parent_dn))
parent_dn = str(ndn)
return parent_dn
ndn = DN(('cn', grouptype), parent_dn)
return ndn
def check_attr(self, attr):
"""
Verify that the user supplied key is a valid attribute in the schema
"""
ldap = self.api.Backend.ldap2
if not ldap.schema:
ldap.get_schema()
obj = ldap.schema.get_obj(_ldap.schema.AttributeType, attr)
if obj is not None:
return obj
@ -238,6 +235,7 @@ class automember_add(LDAPCreate):
msg_summary = _('Added automember rule "%(value)s"')
def pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
entry_attrs['cn'] = keys[-1]
if not automember_container_exists(self.api.Backend.ldap2):
@ -284,6 +282,7 @@ class automember_add_condition(LDAPUpdate):
)
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
# Check to see if the automember rule exists
try:
(tdn, test_attrs) = ldap.get_entry(dn, [])
@ -370,6 +369,7 @@ class automember_remove_condition(LDAPUpdate):
)
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
# Check to see if the automember rule exists
try:
(tdn, test_attrs) = ldap.get_entry(dn, [])
@ -479,10 +479,10 @@ class automember_find(LDAPSearch):
)
def pre_callback(self, ldap, filters, attrs_list, base_dn, scope, *args, **options):
assert isinstance(base_dn, DN)
scope = ldap.SCOPE_SUBTREE
ndn = DN(('cn', options['type']), DN(base_dn))
base_dn = str(ndn)
return (filters, base_dn, scope)
ndn = DN(('cn', options['type']), base_dn)
return (filters, ndn, scope)
api.register(automember_find)
@ -520,7 +520,6 @@ class automember_default_group_set(LDAPUpdate):
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
dn = DN(('cn', options['type']), api.env.container_automember)
dn = str(dn)
entry_attrs['automemberdefaultgroup'] = self.obj.dn_exists(options['type'], options['automemberdefaultgroup'])
return dn
@ -542,7 +541,6 @@ class automember_default_group_remove(LDAPUpdate):
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
dn = DN(('cn', options['type']), api.env.container_automember)
dn = str(dn)
attr = 'automemberdefaultgroup'
(dn, entry_attrs_) = ldap.get_entry(
@ -556,6 +554,7 @@ class automember_default_group_remove(LDAPUpdate):
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
if 'automemberdefaultgroup' not in entry_attrs:
entry_attrs['automemberdefaultgroup'] = unicode(_('No default (fallback) group set'))
return dn
@ -576,10 +575,10 @@ class automember_default_group_show(LDAPRetrieve):
def pre_callback(self, ldap, dn, attrs_list, *keys, **options):
dn = DN(('cn', options['type']), api.env.container_automember)
dn = str(dn)
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
if 'automemberdefaultgroup' not in entry_attrs:
entry_attrs['automemberdefaultgroup'] = unicode(_('No default (fallback) group set'))
return dn

View File

@ -227,6 +227,7 @@ class automountlocation_add(LDAPCreate):
msg_summary = _('Added automount location "%(value)s"')
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
# create auto.master for the new location
self.api.Command['automountmap_add'](keys[-1], u'auto.master')
@ -595,6 +596,7 @@ class automountmap_del(LDAPDelete):
msg_summary = _('Deleted automount map "%(value)s"')
def post_callback(self, ldap, dn, *keys, **options):
assert isinstance(dn, DN)
# delete optional parental connection (direct maps may not have this)
try:
(dn_, entry_attrs) = ldap.find_entry_by_attr(
@ -718,7 +720,7 @@ class automountkey(LDAPObject):
(kwargs['automountkey'], kwargs['automountinformation'])
else:
sfilter = '(automountkey=%s)' % kwargs['automountkey']
basedn = 'automountmapname=%s,cn=%s,%s' % (parent_keys[1], parent_keys[0], self.container_dn)
basedn = DN(('automountmapname', parent_keys[1]), ('cn', parent_keys[0]), self.container_dn)
attrs_list = ['*']
(entries, truncated) = ldap.find_entries(sfilter, attrs_list,
basedn, _ldap.SCOPE_ONELEVEL)
@ -790,6 +792,7 @@ class automountkey_add(LDAPCreate):
internal_options = ['description', 'add_operation']
def pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
options.pop('add_operation', None)
options.pop('description', None)
self.obj.check_key_uniqueness(keys[-2], keys[-1], **options)
@ -926,6 +929,7 @@ class automountkey_mod(LDAPUpdate):
yield key
def pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
if 'newautomountkey' in options:
entry_attrs['automountkey'] = options['newautomountkey']
if 'newautomountinformation' in options:

View File

@ -34,7 +34,7 @@ from ipalib.cli import to_cli, from_cli
from ipalib import output
from ipalib.text import _
from ipalib.util import json_serialize, validate_hostname
from ipalib.dn import *
from ipapython.dn import DN, RDN
global_output_params = (
Flag('has_password',
@ -200,6 +200,7 @@ def validate_attribute(ugettext, name, attr):
raise errors.ValidationError(name=name, error='Invalid format. Should be name=value')
def get_effective_rights(ldap, dn, attrs=None):
assert isinstance(dn, DN)
if attrs is None:
attrs = ['*', 'nsaccountlock', 'cospriority']
rights = ldap.get_effective_rights(dn, attrs)
@ -332,6 +333,7 @@ def add_external_pre_callback(membertype, ldap, dn, keys, options):
membertype is the type of member
"""
assert isinstance(dn, DN)
# validate hostname with allowed underscore characters, non-fqdn
# hostnames are allowed
def validate_host(hostname):
@ -361,12 +363,14 @@ def add_external_post_callback(memberattr, membertype, externalattr, ldap, compl
membertype is the type of member: user,
externalattr is one of externaluser,
"""
assert isinstance(dn, DN)
completed_external = 0
normalize = options.get('external_callback_normalize', True)
# Sift through the failures. We assume that these are all
# entries that aren't stored in IPA, aka external entries.
if memberattr in failed and membertype in failed[memberattr]:
(dn, entry_attrs_) = ldap.get_entry(dn, [externalattr])
assert isinstance(dn, DN)
members = entry_attrs.get(memberattr, [])
external_entries = entry_attrs_.get(externalattr, [])
lc_external_entries = set(e.lower() for e in external_entries)
@ -374,6 +378,7 @@ def add_external_post_callback(memberattr, membertype, externalattr, ldap, compl
for entry in failed[memberattr][membertype]:
membername = entry[0].lower()
member_dn = api.Object[membertype].get_dn(membername)
assert isinstance(member_dn, DN)
if (membername not in lc_external_entries and
member_dn not in members):
# Not an IPA entry, assume external
@ -406,6 +411,7 @@ def add_external_post_callback(memberattr, membertype, externalattr, ldap, compl
return (completed + completed_external, dn)
def remove_external_post_callback(memberattr, membertype, externalattr, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
# Run through the failures and gracefully remove any member defined
# as an external member.
if memberattr in failed and membertype in failed[memberattr]:
@ -440,7 +446,7 @@ def host_is_master(ldap, fqdn):
Raises an exception if a master, otherwise returns nothing.
"""
master_dn = str(DN('cn=%s' % fqdn, 'cn=masters,cn=ipa,cn=etc', api.env.basedn))
master_dn = DN(('cn', fqdn), ('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
try:
(dn, entry_attrs) = ldap.get_entry(master_dn, ['objectclass'])
raise errors.ValidationError(name='hostname', error=_('An IPA master host cannot be deleted or disabled'))
@ -518,9 +524,11 @@ class LDAPObject(Object):
return self.backend.make_dn_from_attr(
self.primary_key.name, keys[-1], parent_dn
)
assert isinstance(parent_dn, DN)
return parent_dn
def get_primary_key_from_dn(self, dn):
assert isinstance(dn, DN)
try:
if self.rdn_attribute:
(dn, entry_attrs) = self.backend.get_entry(
@ -532,8 +540,6 @@ class LDAPObject(Object):
return ''
except errors.NotFound:
pass
# DN object assures we're returning a decoded (unescaped) value
dn = DN(dn)
try:
return dn[self.primary_key.name]
except KeyError:
@ -567,7 +573,7 @@ class LDAPObject(Object):
for member in entry_attrs.setdefault(attr, []):
for ldap_obj_name in self.attribute_members[attr]:
ldap_obj = self.api.Object[ldap_obj_name]
if member.find(ldap_obj.container_dn) > 0:
if ldap_obj.container_dn in member:
new_attr = '%s_%s' % (attr, ldap_obj.name)
entry_attrs.setdefault(new_attr, []).append(
ldap_obj.get_primary_key_from_dn(member)
@ -623,7 +629,6 @@ class LDAPObject(Object):
def __json__(self):
ldap = self.backend
ldap.get_schema()
json_dict = dict(
(a, getattr(self, a)) for a in self.json_friendly_attributes
)
@ -777,52 +782,47 @@ last, after all sets and adds."""),
_callback_registry = dict(pre={}, post={}, exc={}, interactive_prompt={})
def _convert_2_dict(self, attrs):
def _convert_2_dict(self, ldap, attrs):
"""
Convert a string in the form of name/value pairs into a dictionary.
:param attrs: A list of name/value pair strings, in the "name=value"
format. May also be a single string, or None.
"""
if attrs is None:
return {}
if not isinstance(attrs, (tuple, list)):
attrs = [attrs]
newdict = {}
if attrs is None:
attrs = []
elif not type(attrs) in (list, tuple):
attrs = [attrs]
for a in attrs:
m = re.match("^\s*(?P<attr>.*?)\s*=\s*(?P<value>.*?)\s*$", a)
attr = str(m.group('attr').lower())
value = m.group('value')
m = re.match("\s*(.*?)\s*=\s*(.*?)\s*$", a)
attr = str(m.group(1)).lower()
value = m.group(2)
if attr in self.obj.params and attr not in self.params:
# The attribute is managed by IPA, but it didn't get cloned
# to the command. This happens with no_update/no_create attrs.
raise errors.ValidationError(
name=attr, error=_('attribute is not configurable'))
if len(value) == 0:
# None means "delete this attribute"
value = None
newdict.setdefault(attr, []).append(value)
if ldap.has_dn_syntax(attr):
value = DN(value)
if attr in newdict:
if type(value) in (tuple,):
newdict[attr] += list(value)
else:
newdict[attr].append(value)
else:
if type(value) in (tuple,):
newdict[attr] = list(value)
else:
newdict[attr] = [value]
return newdict
def _convert_entry(self, entry_attrs):
result = {}
for attr, val in entry_attrs.iteritems():
if val is None:
val = []
elif not isinstance(val, (tuple, list)):
val = [val]
result[attr] = []
for v in val:
if isinstance(v, str):
# This is a Binary value, base64 encode it
v = base64.b64encode(v)
result[attr].append(unicode(v))
return result
def process_attr_options(self, entry_attrs, dn, keys, options):
"""
Process all --setattr, --addattr, and --delattr options and add the
@ -847,14 +847,15 @@ last, after all sets and adds."""),
:param keys: List of command arguments
:param options: List of options
"""
if all(k not in options for k in ("setattr", "addattr", "delattr")):
return
ldap = self.obj.backend
adddict = self._convert_2_dict(options.get('addattr', []))
setdict = self._convert_2_dict(options.get('setattr', []))
deldict = self._convert_2_dict(options.get('delattr', []))
adddict = self._convert_2_dict(ldap, options.get('addattr', []))
setdict = self._convert_2_dict(ldap, options.get('setattr', []))
deldict = self._convert_2_dict(ldap, options.get('delattr', []))
setattrs = set(setdict.keys())
addattrs = set(adddict.keys())
@ -865,24 +866,24 @@ last, after all sets and adds."""),
direct_del = delattrs
needldapattrs = []
else:
assert isinstance(dn, DN)
direct_add = setattrs & addattrs
direct_del = setattrs & delattrs
needldapattrs = list((addattrs | delattrs) - setattrs)
mod_attrs = self._convert_entry(entry_attrs)
for attr, val in setdict.iteritems():
mod_attrs[attr] = val
entry_attrs[attr] = val
for attr in direct_add:
mod_attrs.setdefault(attr, []).extend(adddict[attr])
entry_attrs.setdefault(attr, []).extend(adddict[attr])
for attr in direct_del:
for delval in deldict[attr]:
try:
mod_attrs[attr].remove(delval)
entry_attrs[attr].remove(delval)
except ValueError:
raise errors.AttrValueNotFound(attr=attr, value=delval)
raise errors.AttrValueNotFound(attr=attr,
value=delval)
if needldapattrs:
try:
@ -901,27 +902,28 @@ last, after all sets and adds."""),
raise errors.ValidationError(name=del_nonexisting.pop(),
error=_('No such attribute on this entry'))
old_entry = self._convert_entry(old_entry)
for attr in needldapattrs:
mod_attrs[attr] = old_entry.get(attr, [])
entry_attrs[attr] = old_entry.get(attr, [])
if attr in addattrs:
mod_attrs[attr].extend(adddict.get(attr, []))
entry_attrs[attr].extend(adddict.get(attr, []))
for delval in deldict.get(attr, []):
try:
mod_attrs[attr].remove(delval)
entry_attrs[attr].remove(delval)
except ValueError:
if isinstance(delval, str):
# This is a Binary value, base64 encode it
delval = unicode(base64.b64encode(delval))
raise errors.AttrValueNotFound(attr=attr, value=delval)
# normalize all values
changedattrs = setattrs | addattrs | delattrs
for attr in changedattrs:
value = mod_attrs[attr]
if attr in self.params and self.params[attr].attribute:
param = self.params[attr]
# convert single-value params to scalars
param = self.params[attr]
value = entry_attrs[attr]
if not param.multivalue:
if len(value) == 1:
value = value[0]
@ -931,19 +933,19 @@ last, after all sets and adds."""),
raise errors.OnlyOneValueAllowed(attr=attr)
# validate, convert and encode params
try:
value = param(value)
value = param(value)
except errors.ValidationError, err:
raise errors.ValidationError(name=attr, error=err.error)
except errors.ConversionError, err:
raise errors.ConversionError(name=attr, error=err.error)
entry_attrs[attr] = value
else:
# unknown attribute: remove duplicite and invalid values
value = list(set([val for val in value if val]))
if not value:
value = None
elif isinstance(value, (tuple, list)) and len(value) == 1:
value = value[0]
entry_attrs[attr] = value
entry_attrs[attr] = list(set([val for val in entry_attrs[attr] if val]))
if not entry_attrs[attr]:
entry_attrs[attr] = None
elif isinstance(entry_attrs[attr], (tuple, list)) and len(entry_attrs[attr]) == 1:
entry_attrs[attr] = entry_attrs[attr][0]
@classmethod
def register_pre_callback(cls, callback, first=False):
@ -1021,8 +1023,13 @@ class LDAPCreate(BaseLDAPCommand, crud.Create):
entry_attrs[self.obj.uuid_attribute] = 'autogenerate'
dn = self.obj.get_dn(*keys, **options)
assert isinstance(dn, DN)
if self.obj.rdn_attribute:
if not dn.startswith('%s=' % self.obj.primary_key.name):
try:
dn_attr = dn[0].attr
except (IndexError, KeyError):
dn_attr = None
if dn_attr != self.obj.primary_key.name:
self.obj.handle_duplicate_entry(*keys)
dn = ldap.make_dn(
entry_attrs, self.obj.rdn_attribute, self.obj.container_dn
@ -1038,9 +1045,9 @@ class LDAPCreate(BaseLDAPCommand, crud.Create):
for callback in self.get_callbacks('pre'):
dn = callback(
self, ldap, dn, entry_attrs, attrs_list, *keys, **options)
assert isinstance(dn, DN)
_check_single_value_attrs(self.params, entry_attrs)
ldap.get_schema()
_check_limit_object_class(self.api.Backend.ldap2.schema.attribute_types(self.obj.limit_object_classes), entry_attrs.keys(), allow_only=True)
_check_limit_object_class(self.api.Backend.ldap2.schema.attribute_types(self.obj.disallow_object_classes), entry_attrs.keys(), allow_only=False)
@ -1074,16 +1081,19 @@ class LDAPCreate(BaseLDAPCommand, crud.Create):
self.obj.primary_key.name, keys[-1], object_class, attrs_list,
self.obj.container_dn
)
assert isinstance(dn, DN)
else:
(dn, entry_attrs) = self._exc_wrapper(keys, options, ldap.get_entry)(
dn, attrs_list, normalize=self.obj.normalize_dn
)
assert isinstance(dn, DN)
except errors.NotFound:
self.obj.handle_not_found(*keys)
for callback in self.get_callbacks('post'):
dn = callback(self, ldap, dn, entry_attrs, *keys, **options)
assert isinstance(dn, DN)
entry_attrs['dn'] = dn
self.obj.convert_attribute_members(entry_attrs, *keys, **options)
@ -1092,9 +1102,11 @@ class LDAPCreate(BaseLDAPCommand, crud.Create):
return dict(result=entry_attrs, value=u'')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return dn
def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs):
@ -1181,6 +1193,7 @@ class LDAPRetrieve(LDAPQuery):
ldap = self.obj.backend
dn = self.obj.get_dn(*keys, **options)
assert isinstance(dn, DN)
if options.get('all', False):
attrs_list = ['*'] + self.obj.default_attributes
@ -1189,11 +1202,13 @@ class LDAPRetrieve(LDAPQuery):
for callback in self.get_callbacks('pre'):
dn = callback(self, ldap, dn, attrs_list, *keys, **options)
assert isinstance(dn, DN)
try:
(dn, entry_attrs) = self._exc_wrapper(keys, options, ldap.get_entry)(
dn, attrs_list, normalize=self.obj.normalize_dn
)
assert isinstance(dn, DN)
except errors.NotFound:
self.obj.handle_not_found(*keys)
@ -1202,17 +1217,21 @@ class LDAPRetrieve(LDAPQuery):
for callback in self.get_callbacks('post'):
dn = callback(self, ldap, dn, entry_attrs, *keys, **options)
assert isinstance(dn, DN)
self.obj.convert_attribute_members(entry_attrs, *keys, **options)
assert isinstance(dn, DN)
entry_attrs['dn'] = dn
if self.obj.primary_key and keys[-1] is not None:
return dict(result=entry_attrs, value=keys[-1])
return dict(result=entry_attrs, value=u'')
def pre_callback(self, ldap, dn, attrs_list, *keys, **options):
assert isinstance(dn, DN)
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return dn
def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs):
@ -1261,6 +1280,7 @@ class LDAPUpdate(LDAPQuery, crud.Update):
raise errors.EmptyModlist()
dn = self.obj.get_dn(*keys, **options)
assert isinstance(dn, DN)
entry_attrs = self.args_options_2_entry(**options)
@ -1279,8 +1299,8 @@ class LDAPUpdate(LDAPQuery, crud.Update):
for callback in self.get_callbacks('pre'):
dn = callback(
self, ldap, dn, entry_attrs, attrs_list, *keys, **options)
assert isinstance(dn, DN)
ldap.get_schema()
_check_limit_object_class(self.api.Backend.ldap2.schema.attribute_types(self.obj.limit_object_classes), entry_attrs.keys(), allow_only=True)
_check_limit_object_class(self.api.Backend.ldap2.schema.attribute_types(self.obj.disallow_object_classes), entry_attrs.keys(), allow_only=False)
@ -1294,10 +1314,10 @@ class LDAPUpdate(LDAPQuery, crud.Update):
if self.obj.rdn_is_primary_key and self.obj.primary_key.name in entry_attrs:
# RDN change
self._exc_wrapper(keys, options, ldap.update_entry_rdn)(dn,
unicode('%s=%s' % (self.obj.primary_key.name,
entry_attrs[self.obj.primary_key.name])))
RDN((self.obj.primary_key.name, entry_attrs[self.obj.primary_key.name])))
rdnkeys = keys[:-1] + (entry_attrs[self.obj.primary_key.name], )
dn = self.obj.get_dn(*rdnkeys)
assert isinstance(dn, DN)
del entry_attrs[self.obj.primary_key.name]
options['rdnupdate'] = True
rdnupdate = True
@ -1306,6 +1326,7 @@ class LDAPUpdate(LDAPQuery, crud.Update):
# to decide what to do. An EmptyModlist in this context doesn't
# mean an error occurred, just that there were no other updates to
# perform.
assert isinstance(dn, DN)
self._exc_wrapper(keys, options, ldap.update_entry)(dn, entry_attrs, normalize=self.obj.normalize_dn)
except errors.EmptyModlist, e:
if not rdnupdate:
@ -1327,6 +1348,7 @@ class LDAPUpdate(LDAPQuery, crud.Update):
for callback in self.get_callbacks('post'):
dn = callback(self, ldap, dn, entry_attrs, *keys, **options)
assert isinstance(dn, DN)
self.obj.convert_attribute_members(entry_attrs, *keys, **options)
if self.obj.primary_key and keys[-1] is not None:
@ -1334,9 +1356,11 @@ class LDAPUpdate(LDAPQuery, crud.Update):
return dict(result=entry_attrs, value=u'')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return dn
def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs):
@ -1360,11 +1384,14 @@ class LDAPDelete(LDAPMultiQuery):
def delete_entry(pkey):
nkeys = keys[:-1] + (pkey, )
dn = self.obj.get_dn(*nkeys, **options)
assert isinstance(dn, DN)
for callback in self.get_callbacks('pre'):
dn = callback(self, ldap, dn, *nkeys, **options)
assert isinstance(dn, DN)
def delete_subtree(base_dn):
assert isinstance(base_dn, DN)
truncated = True
while truncated:
try:
@ -1412,9 +1439,11 @@ class LDAPDelete(LDAPMultiQuery):
return dict(result=dict(failed=u''), value=u'')
def pre_callback(self, ldap, dn, *keys, **options):
assert isinstance(dn, DN)
return dn
def post_callback(self, ldap, dn, *keys, **options):
assert isinstance(dn, DN)
return True
def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs):
@ -1495,14 +1524,17 @@ class LDAPAddMember(LDAPModMember):
(member_dns, failed) = self.get_member_dns(**options)
dn = self.obj.get_dn(*keys, **options)
assert isinstance(dn, DN)
for callback in self.get_callbacks('pre'):
dn = callback(self, ldap, dn, member_dns, failed, *keys, **options)
assert isinstance(dn, DN)
completed = 0
for (attr, objs) in member_dns.iteritems():
for ldap_obj_name in objs:
for m_dn in member_dns[attr][ldap_obj_name]:
assert isinstance(m_dn, DN)
if not m_dn:
continue
try:
@ -1534,7 +1566,9 @@ class LDAPAddMember(LDAPModMember):
(completed, dn) = callback(
self, ldap, completed, failed, dn, entry_attrs, *keys,
**options)
assert isinstance(dn, DN)
assert isinstance(dn, DN)
entry_attrs['dn'] = dn
self.obj.convert_attribute_members(entry_attrs, *keys, **options)
return dict(
@ -1544,9 +1578,11 @@ class LDAPAddMember(LDAPModMember):
)
def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
assert isinstance(dn, DN)
return dn
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return (completed, dn)
def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs):
@ -1583,14 +1619,17 @@ class LDAPRemoveMember(LDAPModMember):
(member_dns, failed) = self.get_member_dns(**options)
dn = self.obj.get_dn(*keys, **options)
assert isinstance(dn, DN)
for callback in self.get_callbacks('pre'):
dn = callback(self, ldap, dn, member_dns, failed, *keys, **options)
assert isinstance(dn, DN)
completed = 0
for (attr, objs) in member_dns.iteritems():
for ldap_obj_name, m_dns in objs.iteritems():
for m_dn in m_dns:
assert isinstance(m_dn, DN)
if not m_dn:
continue
try:
@ -1625,7 +1664,9 @@ class LDAPRemoveMember(LDAPModMember):
(completed, dn) = callback(
self, ldap, completed, failed, dn, entry_attrs, *keys,
**options)
assert isinstance(dn, DN)
assert isinstance(dn, DN)
entry_attrs['dn'] = dn
self.obj.convert_attribute_members(entry_attrs, *keys, **options)
@ -1636,9 +1677,11 @@ class LDAPRemoveMember(LDAPModMember):
)
def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
assert isinstance(dn, DN)
return dn
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return (completed, dn)
def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs):
@ -1765,6 +1808,7 @@ class LDAPSearch(BaseLDAPCommand, crud.Search):
base_dn = self.api.Object[self.obj.parent_object].get_dn(*args[:-1])
else:
base_dn = self.obj.container_dn
assert isinstance(base_dn, DN)
search_kw = self.args_options_2_entry(**options)
@ -1812,6 +1856,7 @@ class LDAPSearch(BaseLDAPCommand, crud.Search):
for callback in self.get_callbacks('pre'):
(filter, base_dn, scope) = callback(
self, ldap, filter, attrs_list, base_dn, scope, *args, **options)
assert isinstance(base_dn, DN)
try:
(entries, truncated) = self._exc_wrapper(args, options, ldap.find_entries)(
@ -1827,14 +1872,16 @@ class LDAPSearch(BaseLDAPCommand, crud.Search):
if self.sort_result_entries:
if self.obj.primary_key:
sortfn=lambda x,y: cmp(x[1][self.obj.primary_key.name][0].lower(), y[1][self.obj.primary_key.name][0].lower())
entries.sort(sortfn)
def sort_key(x):
return x[1][self.obj.primary_key.name][0].lower()
entries.sort(key=sort_key)
if not options.get('raw', False):
for e in entries:
self.obj.convert_attribute_members(e[1], *args, **options)
for e in entries:
assert isinstance(e[0], DN)
e[1]['dn'] = e[0]
entries = [e for (dn, e) in entries]
@ -1845,6 +1892,7 @@ class LDAPSearch(BaseLDAPCommand, crud.Search):
)
def pre_callback(self, ldap, filters, attrs_list, base_dn, scope, *args, **options):
assert isinstance(base_dn, DN)
return (filters, base_dn, scope)
def post_callback(self, ldap, entries, truncated, *args, **options):
@ -1926,9 +1974,11 @@ class LDAPAddReverseMember(LDAPModReverseMember):
# Ensure our target exists
result = self.api.Command[self.show_command](keys[-1])['result']
dn = result['dn']
assert isinstance(dn, DN)
for callback in self.get_callbacks('pre'):
dn = callback(self, ldap, dn, *keys, **options)
assert isinstance(dn, DN)
if options.get('all', False):
attrs_list = ['*'] + self.obj.default_attributes
@ -1967,7 +2017,9 @@ class LDAPAddReverseMember(LDAPModReverseMember):
(completed, dn) = callback(
self, ldap, completed, failed, dn, entry_attrs, *keys,
**options)
assert isinstance(dn, DN)
assert isinstance(dn, DN)
entry_attrs['dn'] = dn
return dict(
completed=completed,
@ -1976,9 +2028,11 @@ class LDAPAddReverseMember(LDAPModReverseMember):
)
def pre_callback(self, ldap, dn, *keys, **options):
assert isinstance(dn, DN)
return dn
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return (completed, dn)
def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs):
@ -2022,9 +2076,11 @@ class LDAPRemoveReverseMember(LDAPModReverseMember):
# Ensure our target exists
result = self.api.Command[self.show_command](keys[-1])['result']
dn = result['dn']
assert isinstance(dn, DN)
for callback in self.get_callbacks('pre'):
dn = callback(self, ldap, dn, *keys, **options)
assert isinstance(dn, DN)
if options.get('all', False):
attrs_list = ['*'] + self.obj.default_attributes
@ -2063,7 +2119,9 @@ class LDAPRemoveReverseMember(LDAPModReverseMember):
(completed, dn) = callback(
self, ldap, completed, failed, dn, entry_attrs, *keys,
**options)
assert isinstance(dn, DN)
assert isinstance(dn, DN)
entry_attrs['dn'] = dn
return dict(
completed=completed,
@ -2072,9 +2130,11 @@ class LDAPRemoveReverseMember(LDAPModReverseMember):
)
def pre_callback(self, ldap, dn, *keys, **options):
assert isinstance(dn, DN)
return dn
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return (completed, dn)
def exc_callback(self, keys, options, exc, call_func, *call_args, **call_kwargs):

View File

@ -19,7 +19,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from ipalib import api
from ipalib import Bool, Int, Str, IA5Str, StrEnum
from ipalib import Bool, Int, Str, IA5Str, StrEnum, DNParam
from ipalib.plugins.baseldap import *
from ipalib import _
from ipalib.errors import ValidationError
@ -149,7 +149,7 @@ class config(LDAPObject):
label=_('Enable migration mode'),
doc=_('Enable migration mode'),
),
Str('ipacertificatesubjectbase',
DNParam('ipacertificatesubjectbase',
cli_name='subject',
label=_('Certificate Subject base'),
doc=_('Base for certificate subjects (OU=Test,O=Example)'),
@ -199,7 +199,7 @@ class config(LDAPObject):
)
def get_dn(self, *keys, **kwargs):
return 'cn=ipaconfig,cn=etc'
return DN(('cn', 'ipaconfig'), ('cn', 'etc'))
api.register(config)
@ -208,6 +208,7 @@ class config_mod(LDAPUpdate):
__doc__ = _('Modify configuration options.')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
if 'ipadefaultprimarygroup' in entry_attrs:
group=entry_attrs['ipadefaultprimarygroup']
try:

View File

@ -35,7 +35,6 @@ from ipalib.util import (validate_zonemgr, normalize_zonemgr,
validate_hostname, validate_dns_label, validate_domain_name,
get_dns_forward_zone_update_policy, get_dns_reverse_zone_update_policy)
from ipapython.ipautil import valid_ip, CheckedIPAddress, is_host_resolvable
from ldap import explode_dn
__doc__ = _("""
Domain Name System (DNS)
@ -802,10 +801,10 @@ class DNSRecord(Str):
# callbacks for per-type special record behavior
def dnsrecord_add_pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
pass
assert isinstance(dn, DN)
def dnsrecord_add_post_callback(self, ldap, dn, entry_attrs, *keys, **options):
pass
assert isinstance(dn, DN)
class ForwardRecord(DNSRecord):
extra = (
@ -817,6 +816,7 @@ class ForwardRecord(DNSRecord):
)
def dnsrecord_add_pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
reverse_option = self._convert_dnsrecord_extra(self.extra[0])
if options.get(reverse_option.name):
records = entry_attrs.get(self.name, [])
@ -832,6 +832,7 @@ class ForwardRecord(DNSRecord):
setattr(context, '%s_reverse' % self.name, entry_attrs.get(self.name))
def dnsrecord_add_post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
rev_records = getattr(context, '%s_reverse' % self.name, [])
if rev_records:
@ -1727,6 +1728,7 @@ class dnszone_add(LDAPCreate):
)
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
if not dns_container_exists(self.api.Backend.ldap2):
raise errors.NotFound(reason=_('DNS is not configured'))
@ -1751,6 +1753,7 @@ class dnszone_add(LDAPCreate):
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
if 'ip_address' in options:
nameserver = entry_attrs['idnssoamname'][0][:-1] # ends with a dot
nsparts = nameserver.split('.')
@ -1813,6 +1816,7 @@ class dnszone_find(LDAPSearch):
)
def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options):
assert isinstance(base_dn, DN)
if options.get('forward_only', False):
search_kw = {}
search_kw['idnsname'] = _valid_reverse_zones.keys()
@ -1980,6 +1984,7 @@ class dnsrecord(LDAPObject):
)
def _nsrecord_pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
nsrecords = entry_attrs.get('nsrecord')
if options.get('force', False) or nsrecords is None:
return
@ -1987,6 +1992,7 @@ class dnsrecord(LDAPObject):
check_ns_rec_resolvable(keys[0], nsrecord)
def _ptrrecord_pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
ptrrecords = entry_attrs.get('ptrrecord')
if ptrrecords is None:
return
@ -2015,6 +2021,7 @@ class dnsrecord(LDAPObject):
% dict(name=zone_name, count=zone_len, user_count=ip_addr_comp_count)))
def run_precallback_validators(self, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
ldap = self.api.Backend.ldap2
for rtype in entry_attrs:
@ -2049,7 +2056,7 @@ class dnsrecord(LDAPObject):
def get_dns_masters(self):
ldap = self.api.Backend.ldap2
base_dn = 'cn=masters,cn=ipa,cn=etc,%s' % self.api.env.basedn
base_dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), self.api.env.basedn)
ldap_filter = '(&(objectClass=ipaConfigObject)(cn=DNS))'
dns_masters = []
@ -2058,9 +2065,12 @@ class dnsrecord(LDAPObject):
for entry in entries:
master_dn = entry[0]
if master_dn.startswith('cn='):
master = explode_dn(master_dn)[1].replace('cn=','')
assert isinstance(master_dn, DN)
try:
master = master_dn[1]['cn']
dns_masters.append(master)
except (IndexError, KeyError):
pass
except errors.NotFound:
return []
@ -2254,6 +2264,7 @@ class dnsrecord_add(LDAPCreate):
kw.update(user_options)
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
precallback_attrs = []
processed_attrs = []
for option in options:
@ -2354,6 +2365,7 @@ class dnsrecord_add(LDAPCreate):
raise exc
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
for attr in getattr(context, 'dnsrecord_precallback_attrs', []):
param = self.params[attr]
param.dnsrecord_add_post_callback(ldap, dn, entry_attrs, *keys, **options)
@ -2382,6 +2394,7 @@ class dnsrecord_mod(LDAPUpdate):
return super(dnsrecord_mod, self).args_options_2_entry(*keys, **options)
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
if options.get('rename') and self.obj.is_pkey_zone_record(*keys):
# zone rename is not allowed
raise errors.ValidationError(name='rename',
@ -2466,10 +2479,12 @@ class dnsrecord_mod(LDAPUpdate):
return result
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
if self.obj.is_pkey_zone_record(*keys):
entry_attrs[self.obj.primary_key.name] = [_dns_zone_record]
self.obj.postprocess_record(entry_attrs, **options)
return dn
def interactive_prompt_callback(self, kw):
try:
@ -2564,6 +2579,7 @@ class dnsrecord_del(LDAPUpdate):
yield option
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
try:
(dn_, old_entry) = ldap.get_entry(
dn, _record_attributes,
@ -2626,9 +2642,11 @@ class dnsrecord_del(LDAPUpdate):
return result
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
if self.obj.is_pkey_zone_record(*keys):
entry_attrs[self.obj.primary_key.name] = [_dns_zone_record]
self.obj.postprocess_record(entry_attrs, **options)
return dn
def args_options_2_entry(self, *keys, **options):
self.obj.has_cli_options(options, self.no_option_msg)
@ -2697,6 +2715,7 @@ class dnsrecord_show(LDAPRetrieve):
)
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
if self.obj.is_pkey_zone_record(*keys):
entry_attrs[self.obj.primary_key.name] = [_dns_zone_record]
self.obj.postprocess_record(entry_attrs, **options)
@ -2723,6 +2742,7 @@ class dnsrecord_find(LDAPSearch):
yield option
def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options):
assert isinstance(base_dn, DN)
# include zone record (root entry) in the search
return (filter, base_dn, ldap.SCOPE_SUBTREE)
@ -2774,7 +2794,7 @@ class dns_is_enabled(Command):
NO_CLI = True
has_output = output.standard_value
base_dn = 'cn=masters,cn=ipa,cn=etc,%s' % api.env.basedn
base_dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
filter = '(&(objectClass=ipaConfigObject)(cn=DNS))'
def execute(self, *args, **options):

View File

@ -318,6 +318,7 @@ class entitle_consume(LDAPUpdate):
return result
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
quantity = keys[-1]
os.environ['LANG'] = 'en_US'
@ -361,6 +362,7 @@ class entitle_consume(LDAPUpdate):
Returning the certificates isn't very interesting. Return the
status of entitlements instead.
"""
assert isinstance(dn, DN)
if 'usercertificate' in entry_attrs:
del entry_attrs['usercertificate']
if 'userpkcs12' in entry_attrs:
@ -504,7 +506,7 @@ class entitle_register(LDAPCreate):
"""
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
dn = '%s,%s' % (self.obj.container_dn, self.api.env.basedn)
dn = DN(self.obj.container_dn, self.api.env.basedn)
if not ldap.can_add(dn):
raise errors.ACIError(info='No permission to register')
os.environ['LANG'] = 'en_US'
@ -604,6 +606,7 @@ class entitle_import(LDAPUpdate):
)
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
try:
(db, uuid, certfile, keyfile) = get_uuid(ldap)
if db is not None:
@ -622,7 +625,7 @@ class entitle_import(LDAPUpdate):
raise errors.CertificateFormatError(error=_('Not an entitlement certificate'))
except M2Crypto.X509.X509Error:
raise errors.CertificateFormatError(error=_('Not an entitlement certificate'))
dn = 'ipaentitlementid=%s,%s' % (entry_attrs['ipaentitlementid'], dn)
dn = DN(('ipaentitlementid', entry_attrs['ipaentitlementid']), dn)
(dn, current_attrs) = ldap.get_entry(
dn, ['*'], normalize=self.obj.normalize_dn
)
@ -689,6 +692,7 @@ class entitle_sync(LDAPUpdate):
)
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
os.environ['LANG'] = 'en_US'
locale.setlocale(locale.LC_ALL, '')
@ -719,6 +723,7 @@ class entitle_sync(LDAPUpdate):
Returning the certificates isn't very interesting. Return the
status of entitlements instead.
"""
assert isinstance(dn, DN)
if 'usercertificate' in entry_attrs:
del entry_attrs['usercertificate']
if 'userpkcs12' in entry_attrs:

View File

@ -156,6 +156,7 @@ class group_add(LDAPCreate):
# As both 'external' and 'nonposix' options have default= set for
# them, they will always be present in options dict, thus we can
# safely reference the values
assert isinstance(dn, DN)
if options['external']:
entry_attrs['objectclass'].append('ipaexternalgroup')
if 'gidnumber' in options:
@ -176,6 +177,7 @@ class group_del(LDAPDelete):
msg_summary = _('Deleted group "%(value)s"')
def pre_callback(self, ldap, dn, *keys, **options):
assert isinstance(dn, DN)
config = ldap.get_ipa_config()[1]
def_primary_group = config.get('ipadefaultprimarygroup', '')
def_primary_group_dn = group_dn = self.obj.get_dn(def_primary_group)
@ -192,6 +194,7 @@ class group_del(LDAPDelete):
return dn
def post_callback(self, ldap, dn, *keys, **options):
assert isinstance(dn, DN)
try:
api.Command['pwpolicy_del'](keys[-1])
except errors.NotFound:
@ -220,6 +223,7 @@ class group_mod(LDAPUpdate):
)
def pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
if ('posix' in options and options['posix']) or 'gidnumber' in options:
(dn, old_entry_attrs) = ldap.get_entry(dn, ['objectclass'])
if 'ipaexternalgroup' in old_entry_attrs['objectclass']:
@ -275,6 +279,7 @@ class group_find(LDAPSearch):
)
def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options):
assert isinstance(base_dn, DN)
# if looking for private groups, we need to create a new search filter,
# because private groups have different object classes
if options['private']:
@ -319,6 +324,7 @@ class group_add_member(LDAPAddMember):
)
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
result = (completed, dn)
if 'ipaexternalmember' in options:
if not _dcerpc_bindings_installed:
@ -367,6 +373,7 @@ class group_remove_member(LDAPRemoveMember):
)
def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
assert isinstance(dn, DN)
if keys[0] == protected_group_name:
result = api.Command.group_show(protected_group_name)
users_left = set(result['result'].get('member_user', []))
@ -377,6 +384,7 @@ class group_remove_member(LDAPRemoveMember):
return dn
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
result = (completed, dn)
if 'ipaexternalmember' in options:
sids = options['ipaexternalmember']

View File

@ -231,6 +231,7 @@ class hbacrule_add(LDAPCreate):
msg_summary = _('Added HBAC rule "%(value)s"')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
# HBAC rules are enabled by default
entry_attrs['ipaenabledflag'] = 'TRUE'
return dn
@ -244,6 +245,7 @@ class hbacrule_del(LDAPDelete):
msg_summary = _('Deleted HBAC rule "%(value)s"')
def pre_callback(self, ldap, dn, *keys, **options):
assert isinstance(dn, DN)
kw = dict(seealso=keys[0])
_entries = api.Command.selinuxusermap_find(None, **kw)
if _entries['count']:
@ -260,6 +262,7 @@ class hbacrule_mod(LDAPUpdate):
msg_summary = _('Modified HBAC rule "%(value)s"')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
try:
(dn, entry_attrs) = ldap.get_entry(dn, attrs_list)
except errors.NotFound:
@ -436,6 +439,7 @@ class hbacrule_add_user(LDAPAddMember):
member_count_out = ('%i object added.', '%i objects added.')
def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
assert isinstance(dn, DN)
try:
(dn, entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes)
except errors.NotFound:
@ -464,6 +468,7 @@ class hbacrule_add_host(LDAPAddMember):
member_count_out = ('%i object added.', '%i objects added.')
def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
assert isinstance(dn, DN)
try:
(dn, entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes)
except errors.NotFound:
@ -492,6 +497,7 @@ class hbacrule_add_sourcehost(LDAPAddMember):
member_count_out = ('%i object added.', '%i objects added.')
def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
assert isinstance(dn, DN)
try:
(dn, entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes)
except errors.NotFound:
@ -502,6 +508,7 @@ class hbacrule_add_sourcehost(LDAPAddMember):
return add_external_pre_callback('host', ldap, dn, keys, options)
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return add_external_post_callback('sourcehost', 'host', 'externalhost', ldap, completed, failed, dn, entry_attrs, keys, options)
api.register(hbacrule_add_sourcehost)
@ -514,6 +521,7 @@ class hbacrule_remove_sourcehost(LDAPRemoveMember):
member_count_out = ('%i object removed.', '%i objects removed.')
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return remove_external_post_callback('sourcehost', 'host', 'externalhost', ldap, completed, failed, dn, entry_attrs, keys, options)
api.register(hbacrule_remove_sourcehost)
@ -526,6 +534,7 @@ class hbacrule_add_service(LDAPAddMember):
member_count_out = ('%i object added.', '%i objects added.')
def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
assert isinstance(dn, DN)
try:
(dn, entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes)
except errors.NotFound:

View File

@ -38,10 +38,10 @@ from ipalib.plugins.dns import (dns_container_exists, _record_types,
from ipalib.plugins.dns import get_reverse_zone
from ipalib import _, ngettext
from ipalib import x509
from ipalib.dn import *
from ipalib.request import context
from ipalib.util import validate_sshpubkey, output_sshpubkey
from ipapython.ipautil import ipa_generate_password, CheckedIPAddress, make_sshfp
from ipapython.dn import DN
__doc__ = _("""
Hosts/Machines
@ -379,6 +379,7 @@ class host_add(LDAPCreate):
)
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
if options.get('ip_address') and dns_container_exists(ldap):
parts = keys[-1].split('.')
host = parts[0]
@ -423,6 +424,7 @@ class host_add(LDAPCreate):
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
exc = None
if dns_container_exists(ldap):
try:
@ -483,6 +485,7 @@ class host_del(LDAPDelete):
)
def pre_callback(self, ldap, dn, *keys, **options):
assert isinstance(dn, DN)
# If we aren't given a fqdn, find it
if _hostname_validator(None, keys[-1]) is not None:
hostentry = api.Command['host_show'](keys[-1])['result']
@ -599,6 +602,7 @@ class host_mod(LDAPUpdate):
)
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
# Allow an existing OTP to be reset but don't allow a OTP to be
# added to an enrolled host.
if options.get('userpassword') or options.get('random'):
@ -690,6 +694,7 @@ class host_mod(LDAPUpdate):
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
if options.get('random', False):
entry_attrs['randompassword'] = unicode(getattr(context, 'randompassword'))
set_certificate_attrs(entry_attrs)
@ -728,6 +733,7 @@ class host_find(LDAPSearch):
yield option
def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options):
assert isinstance(base_dn, DN)
if 'locality' in attrs_list:
attrs_list.remove('locality')
attrs_list.append('l')
@ -808,6 +814,7 @@ class host_show(LDAPRetrieve):
member_attributes = ['managedby']
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
self.obj.get_password_attributes(ldap, dn, entry_attrs)
if entry_attrs['has_password']:
# If an OTP is set there is no keytab, at least not one
@ -891,8 +898,7 @@ class host_disable(LDAPQuery):
try:
serial = unicode(x509.get_serial_number(cert, x509.DER))
try:
result = api.Command['cert_show'](unicode(serial))['result'
]
result = api.Command['cert_show'](unicode(serial))['result']
if 'revocation_reason' not in result:
try:
api.Command['cert_revoke'](unicode(serial), revocation_reason=4)
@ -928,6 +934,7 @@ class host_disable(LDAPQuery):
)
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
self.obj.suppress_netgroup_memberof(entry_attrs)
return dn
@ -941,6 +948,7 @@ class host_add_managedby(LDAPAddMember):
allow_same = True
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
self.obj.suppress_netgroup_memberof(entry_attrs)
return (completed, dn)
@ -954,6 +962,7 @@ class host_remove_managedby(LDAPRemoveMember):
has_output_params = LDAPRemoveMember.has_output_params + host_output_params
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
self.obj.suppress_netgroup_memberof(entry_attrs)
return (completed, dn)

View File

@ -21,7 +21,7 @@
from ipalib.plugins.baseldap import *
from ipalib import api, Int, _, ngettext, errors
from ipalib.plugins.netgroup import NETGROUP_PATTERN, NETGROUP_PATTERN_ERRMSG
from ipalib.dn import DN
from ipapython.dn import DN
__doc__ = _("""
Groups of hosts.
@ -119,6 +119,7 @@ class hostgroup_add(LDAPCreate):
msg_summary = _('Added hostgroup "%(value)s"')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
try:
# check duplicity with hostgroups first to provide proper error
netgroup = api.Command['hostgroup_show'](keys[-1])
@ -140,6 +141,7 @@ class hostgroup_add(LDAPCreate):
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
# Always wait for the associated netgroup to be created so we can
# be sure to ignore it in memberOf
newentry = wait_for_value(ldap, dn, 'objectclass', 'mepOriginEntry')
@ -166,6 +168,7 @@ class hostgroup_mod(LDAPUpdate):
msg_summary = _('Modified hostgroup "%(value)s"')
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
self.obj.suppress_netgroup_memberof(dn, entry_attrs)
return dn
@ -195,6 +198,7 @@ class hostgroup_show(LDAPRetrieve):
__doc__ = _('Display information about a hostgroup.')
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
self.obj.suppress_netgroup_memberof( dn, entry_attrs)
return dn
@ -205,6 +209,7 @@ class hostgroup_add_member(LDAPAddMember):
__doc__ = _('Add members to a hostgroup.')
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
self.obj.suppress_netgroup_memberof(dn, entry_attrs)
return (completed, dn)
@ -215,6 +220,7 @@ class hostgroup_remove_member(LDAPRemoveMember):
__doc__ = _('Remove members from a hostgroup.')
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
self.obj.suppress_netgroup_memberof(dn, entry_attrs)
return (completed, dn)

View File

@ -71,7 +71,7 @@ class krbtpolicy(LDAPObject):
"""
Kerberos Ticket Policy object
"""
container_dn = 'cn=%s,cn=kerberos' % api.env.realm
container_dn = DN(('cn', api.env.realm), ('cn', 'kerberos'))
object_name = _('kerberos ticket policy settings')
default_attributes = ['krbmaxticketlife', 'krbmaxrenewableage']
limit_object_classes = ['krbticketpolicyaux']
@ -112,6 +112,7 @@ class krbtpolicy_mod(LDAPUpdate):
__doc__ = _('Modify Kerberos ticket policy.')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
# disable all flag
# ticket policies are attached to objects with unrelated attributes
if options.get('all'):
@ -125,6 +126,7 @@ class krbtpolicy_show(LDAPRetrieve):
__doc__ = _('Display the current Kerberos ticket policy.')
def pre_callback(self, ldap, dn, attrs_list, *keys, **options):
assert isinstance(dn, DN)
# disable all flag
# ticket policies are attached to objects with unrelated attributes
if options.get('all'):
@ -132,6 +134,7 @@ class krbtpolicy_show(LDAPRetrieve):
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
if keys[-1] is not None:
# if policy for a specific user isn't set, display global values
if 'krbmaxticketlife' not in entry_attrs or \

View File

@ -21,10 +21,8 @@ import re
import ldap as _ldap
from ipalib import api, errors, output
from ipalib import Command, Password, Str, Flag, StrEnum
from ipalib import Command, Password, Str, Flag, StrEnum, DNParam
from ipalib.cli import to_cli
from ipalib.util import validate_dn_param
from ipalib.dn import *
from ipalib.plugins.user import NO_UPG_MAGIC
if api.env.in_server and api.env.context in ['lite', 'server']:
try:
@ -32,6 +30,7 @@ if api.env.in_server and api.env.context in ['lite', 'server']:
except StandardError, e:
raise e
from ipalib import _
from ipapython.dn import DN
__doc__ = _("""
Migration to IPA
@ -114,18 +113,10 @@ _dn_err_msg = _('Malformed DN')
_supported_schemas = (u'RFC2307bis', u'RFC2307')
_compat_dn = "cn=Schema Compatibility,cn=plugins,cn=config"
def is_DN_syntax(ldap, attr):
"""
Check the schema to see if the attribute uses DN syntax.
Returns True/False
"""
obj = ldap.schema.get_obj(_ldap.schema.AttributeType, attr)
return obj is not None and obj.syntax == '1.3.6.1.4.1.1466.115.121.1.12'
_compat_dn = DN(('cn', 'Schema Compatibility'), ('cn', 'plugins'), ('cn', 'config'))
def _pre_migrate_user(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwargs):
assert isinstance(dn, DN)
attr_blacklist = ['krbprincipalkey','memberofindirect','memberindirect']
attr_blacklist.extend(kwargs.get('attr_blacklist', []))
ds_ldap = ctx['ds_ldap']
@ -198,17 +189,18 @@ def _pre_migrate_user(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwargs
# tree
for attr in entry_attrs.keys():
if is_DN_syntax(ldap, attr):
if ldap.has_dn_syntax(attr):
for ind, value in enumerate(entry_attrs[attr]):
assert isinstance(value, DN)
try:
(remote_dn, remote_entry) = ds_ldap.get_entry(value, [api.Object.user.primary_key.name, api.Object.group.primary_key.name])
except errors.NotFound:
api.log.warn('%s: attribute %s refers to non-existent entry %s' % (pkey, attr, value))
continue
if value.lower().endswith(search_bases['user']):
if value.endswith(search_bases['user']):
primary_key = api.Object.user.primary_key.name
container = api.env.container_user
elif value.lower().endswith(search_bases['group']):
elif value.endswith(search_bases['group']):
primary_key = api.Object.group.primary_key.name
container = api.env.container_group
else:
@ -221,15 +213,13 @@ def _pre_migrate_user(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwargs
api.log.debug('converting DN value %s for %s in %s' % (value, attr, dn))
rdnval = remote_entry[primary_key][0].lower()
entry_attrs[attr][ind] = \
str(DN((primary_key, rdnval),
container,
api.env.basedn))
entry_attrs[attr][ind] = DN((primary_key, rdnval), container, api.env.basedn)
return dn
def _post_migrate_user(ldap, pkey, dn, entry_attrs, failed, config, ctx):
assert isinstance(dn, DN)
# add user to the default group
try:
ldap.add_entry_to_group(dn, ctx['def_group_dn'])
@ -246,6 +236,7 @@ def _post_migrate_user(ldap, pkey, dn, entry_attrs, failed, config, ctx):
# GROUP MIGRATION CALLBACKS AND VARS
def _pre_migrate_group(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwargs):
def convert_members_rfc2307bis(member_attr, search_bases, overwrite=False):
"""
Convert DNs in member attributes to work in IPA.
@ -253,24 +244,19 @@ def _pre_migrate_group(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwarg
new_members = []
entry_attrs.setdefault(member_attr, [])
for m in entry_attrs[member_attr]:
assert isinstance(m, DN)
try:
# what str2dn returns looks like [[('cn', 'foo', 4)], [('dc', 'example', 1)], [('dc', 'com', 1)]]
rdn = _ldap.dn.str2dn(m ,flags=_ldap.DN_FORMAT_LDAPV3)[0]
rdnval = rdn[0][1]
rdnval = m[0].value
except IndexError:
api.log.error('Malformed DN %s has no RDN?' % m)
continue
if m.lower().endswith(search_bases['user']):
if m.endswith(search_bases['user']):
api.log.info('migrating user %s' % m)
m = '%s=%s,%s' % (api.Object.user.primary_key.name,
rdnval,
api.env.container_user)
elif m.lower().endswith(search_bases['group']):
m = DN((api.Object.user.primary_key.name, rdnval), api.env.container_user)
elif m.endswith(search_bases['group']):
api.log.info('migrating group %s' % m)
m = '%s=%s,%s' % (api.Object.group.primary_key.name,
rdnval,
api.env.container_group)
m = DN((api.Object.group.primary_key.name, rdnval), api.env.container_group)
else:
api.log.error('entry %s does not belong into any known container' % m)
continue
@ -290,12 +276,11 @@ def _pre_migrate_group(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwarg
new_members = []
entry_attrs.setdefault(member_attr, [])
for m in entry_attrs[member_attr]:
memberdn = '%s=%s,%s' % (api.Object.user.primary_key.name,
m,
api.env.container_user)
memberdn = DN((api.Object.user.primary_key.name, m), api.env.container_user)
new_members.append(ldap.normalize_dn(memberdn))
entry_attrs['member'] = new_members
assert isinstance(dn, DN)
attr_blacklist = ['memberofindirect','memberindirect']
attr_blacklist.extend(kwargs.get('attr_blacklist', []))
@ -330,6 +315,7 @@ def _pre_migrate_group(ldap, pkey, dn, entry_attrs, failed, config, ctx, **kwarg
def _group_exc_callback(ldap, dn, entry_attrs, exc, options):
assert isinstance(dn, DN)
if isinstance(exc, errors.DuplicateEntry):
if options.get('groupoverwritegid', False) and \
entry_attrs.get('gidnumber') is not None:
@ -424,24 +410,24 @@ class migrate_ds(Command):
)
takes_options = (
Str('binddn?', validate_dn_param,
DNParam('binddn?',
cli_name='bind_dn',
label=_('Bind DN'),
default=u'cn=directory manager',
default=DN(('cn', 'directory manager')),
autofill=True,
),
Str('usercontainer', validate_dn_param,
DNParam('usercontainer',
cli_name='user_container',
label=_('User container'),
doc=_('DN of container for users in DS relative to base DN'),
default=u'ou=people',
default=DN(('ou', 'people')),
autofill=True,
),
Str('groupcontainer', validate_dn_param,
DNParam('groupcontainer',
cli_name='group_container',
label=_('Group container'),
doc=_('DN of container for groups in DS relative to base DN'),
default=u'ou=groups',
default=DN(('ou', 'groups')),
autofill=True,
),
Str('userobjectclass+',
@ -511,7 +497,7 @@ class migrate_ds(Command):
doc=_('Continuous operation mode. Errors are reported but the process continues'),
default=False,
),
Str('basedn?',
DNParam('basedn?',
cli_name='base_dn',
label=_('Base DN'),
doc=_('Base DN on remote LDAP server'),
@ -594,11 +580,9 @@ can use their Kerberos accounts.''')
def _get_search_bases(self, options, ds_base_dn, migrate_order):
search_bases = dict()
ds_base_dn = DN(ds_base_dn)
for ldap_obj_name in migrate_order:
container = options.get('%scontainer' % to_cli(ldap_obj_name))
if container:
container = DN(container)
# Don't append base dn if user already appended it in the container dn
if container.endswith(ds_base_dn):
search_base = container
@ -606,13 +590,14 @@ can use their Kerberos accounts.''')
search_base = DN(container, ds_base_dn)
else:
search_base = ds_base_dn
search_bases[ldap_obj_name] = str(search_base)
search_bases[ldap_obj_name] = search_base
return search_bases
def migrate(self, ldap, config, ds_ldap, ds_base_dn, options):
"""
Migrate objects from DS to LDAP.
"""
assert isinstance(ds_base_dn, DN)
migrated = {} # {'OBJ': ['PKEY1', 'PKEY2', ...], ...}
failed = {} # {'OBJ': {'PKEY1': 'Failed 'cos blabla', ...}, ...}
search_bases = self._get_search_bases(options, ds_base_dn, self.migrate_order)
@ -703,6 +688,7 @@ can use their Kerberos accounts.''')
continue
dn = ldap_obj.get_dn(pkey)
assert isinstance(dn, DN)
entry_attrs['objectclass'] = list(
set(
config.get(
@ -722,6 +708,7 @@ can use their Kerberos accounts.''')
valid_gids = valid_gids,
**blacklists
)
assert isinstance(dn, DN)
if not dn:
continue
except errors.NotFound, e:
@ -760,6 +747,8 @@ can use their Kerberos accounts.''')
config = ldap.get_ipa_config()[1]
ds_base_dn = options.get('basedn')
if ds_base_dn is not None:
assert isinstance(ds_base_dn, DN)
# check if migration mode is enabled
if config.get('ipamigrationenabled', ('FALSE', ))[0] == 'FALSE':
@ -773,6 +762,7 @@ can use their Kerberos accounts.''')
if not options.get('compat'):
try:
(dn,check_compat) = ldap.get_entry(_compat_dn, normalize=False)
assert isinstance(dn, DN)
if check_compat is not None and \
check_compat.get('nsslapd-pluginenabled', [''])[0].lower() == 'on':
return dict(result={}, failed={}, enabled=True, compat=False)
@ -782,14 +772,16 @@ can use their Kerberos accounts.''')
if not ds_base_dn:
# retrieve base DN from remote LDAP server
(entries, truncated) = ds_ldap.find_entries(
'', ['namingcontexts', 'defaultnamingcontext'], '',
'', ['namingcontexts', 'defaultnamingcontext'], DN(''),
_ldap.SCOPE_BASE, size_limit=-1, time_limit=0,
)
if 'defaultnamingcontext' in entries[0][1]:
ds_base_dn = entries[0][1]['defaultnamingcontext'][0]
ds_base_dn = DN(entries[0][1]['defaultnamingcontext'][0])
assert isinstance(ds_base_dn, DN)
else:
try:
ds_base_dn = entries[0][1]['namingcontexts'][0]
ds_base_dn = DN(entries[0][1]['namingcontexts'][0])
assert isinstance(ds_base_dn, DN)
except (IndexError, KeyError), e:
raise StandardError(str(e))

View File

@ -162,6 +162,7 @@ class netgroup_add(LDAPCreate):
u'Hostgroups and netgroups share a common namespace')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
entry_attrs.setdefault('nisdomainname', self.api.env.domain)
try:
@ -203,6 +204,7 @@ class netgroup_mod(LDAPUpdate):
msg_summary = _('Modified netgroup "%(value)s"')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
try:
(dn, entry_attrs) = ldap.get_entry(dn, attrs_list)
except errors.NotFound:
@ -238,6 +240,7 @@ class netgroup_find(LDAPSearch):
)
def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options):
assert isinstance(base_dn, DN)
# Do not display private mepManagedEntry netgroups by default
# If looking for managed groups, we need to omit the negation search filter
@ -267,8 +270,11 @@ class netgroup_add_member(LDAPAddMember):
member_attributes = ['memberuser', 'memberhost', 'member']
has_output_params = LDAPAddMember.has_output_params + output_params
def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
assert isinstance(dn, DN)
return add_external_pre_callback('host', ldap, dn, keys, options)
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return add_external_post_callback('memberhost', 'host', 'externalhost', ldap, completed, failed, dn, entry_attrs, keys, options)
api.register(netgroup_add_member)
@ -280,6 +286,7 @@ class netgroup_remove_member(LDAPRemoveMember):
member_attributes = ['memberuser', 'memberhost', 'member']
has_output_params = LDAPRemoveMember.has_output_params + output_params
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return remove_external_post_callback('memberhost', 'host', 'externalhost', ldap, completed, failed, dn, entry_attrs, keys, options)
api.register(netgroup_remove_member)

View File

@ -24,6 +24,7 @@ from ipalib import _
from ipalib import output
from ipalib.plugins.user import split_principal, validate_principal, normalize_principal
from ipalib.request import context
from ipapython.dn import DN
__doc__ = _("""
Set a user's password
@ -104,7 +105,7 @@ class passwd(Command):
(dn, entry_attrs) = ldap.find_entry_by_attr(
'krbprincipalname', principal, 'posixaccount', [''],
",".join([api.env.container_user, api.env.basedn])
DN(api.env.container_user, api.env.basedn)
)
if principal == getattr(context, 'principal') and \

View File

@ -22,6 +22,7 @@ from ipalib import api, _, ngettext
from ipalib import Flag, Str, StrEnum
from ipalib.request import context
from ipalib import errors
from ipapython.dn import DN, EditableDN
__doc__ = _("""
Permissions
@ -202,6 +203,7 @@ class permission_add(LDAPCreate):
has_output_params = LDAPCreate.has_output_params + output_params
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
# Test the ACI before going any further
opts = self.obj.filter_aci_attributes(options)
opts['test'] = True
@ -219,6 +221,7 @@ class permission_add(LDAPCreate):
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
# Now actually add the aci.
opts = self.obj.filter_aci_attributes(options)
opts['test'] = False
@ -275,6 +278,7 @@ class permission_add_noaci(LDAPCreate):
yield option
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
permission_type = options.get('permissiontype')
if permission_type:
entry_attrs['ipapermissiontype'] = [ permission_type ]
@ -297,6 +301,7 @@ class permission_del(LDAPDelete):
)
def pre_callback(self, ldap, dn, *keys, **options):
assert isinstance(dn, DN)
if not options.get('force') and not self.obj.check_system(ldap, dn, *keys):
raise errors.ACIError(info='A SYSTEM permission may not be removed')
# remove permission even when the underlying ACI is missing
@ -316,6 +321,7 @@ class permission_mod(LDAPUpdate):
has_output_params = LDAPUpdate.has_output_params + output_params
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
if not self.obj.check_system(ldap, dn, *keys):
raise errors.ACIError(info='A SYSTEM permission may not be modified')
@ -332,10 +338,13 @@ class permission_mod(LDAPUpdate):
if 'rename' in options:
if options['rename']:
try:
new_dn = dn.replace(keys[-1].lower(), options['rename'], 1)
(new_dn, attrs) = ldap.get_entry(
new_dn, attrs_list, normalize=self.obj.normalize_dn
)
try:
new_dn = EditableDN(dn)
new_dn[0]['cn'] # assure the first RDN has cn as it's type
except (IndexError, KeyError), e:
raise ValueError("expected dn starting with 'cn=' but got '%s'" % dn)
new_dn[0].value = options['rename']
(new_dn, attrs) = ldap.get_entry(new_dn, attrs_list, normalize=self.obj.normalize_dn)
raise errors.DuplicateEntry()
except errors.NotFound:
pass # permission may be renamed, continue
@ -371,6 +380,7 @@ class permission_mod(LDAPUpdate):
raise exc
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
# rename the underlying ACI after the change to permission
cn = keys[-1]
@ -480,6 +490,7 @@ class permission_show(LDAPRetrieve):
has_output_params = LDAPRetrieve.has_output_params + output_params
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
try:
common_options = filter_options(options, ['all', 'raw'])
aci = self.api.Command.aci_show(keys[-1], aciprefix=ACI_PREFIX,

View File

@ -21,6 +21,7 @@ from ipalib import api, errors
from ipalib import Int, Str
from ipalib import Object, Command
from ipalib import _
from ipapython.dn import DN
__doc__ = _("""
Kerberos pkinit options
@ -67,9 +68,7 @@ class pkinit_anonymous(Command):
__doc__ = _('Enable or Disable Anonymous PKINIT.')
princ_name = 'WELLKNOWN/ANONYMOUS@%s' % api.env.realm
default_dn = 'krbprincipalname=%s,cn=%s,cn=kerberos,%s' % (
princ_name, api.env.realm, api.env.basedn
)
default_dn = DN(('krbprincipalname', princ_name), ('cn', api.env.realm), ('cn', 'kerberos'), api.env.basedn)
takes_args = (
Str('action', valid_arg),

View File

@ -19,11 +19,12 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from ipalib import api
from ipalib import Int, Str
from ipalib import Int, Str, DNParam
from ipalib.plugins.baseldap import *
from ipalib import _
from ipalib.request import context
from ipapython.ipautil import run
from ipapython.dn import DN
from distutils import version
__doc__ = _("""
@ -75,13 +76,13 @@ class cosentry(LDAPObject):
"""
NO_CLI = True
container_dn = 'cn=costemplates,%s' % api.env.container_accounts
container_dn = DN(('cn', 'costemplates'), api.env.container_accounts)
object_class = ['top', 'costemplate', 'extensibleobject', 'krbcontainer']
default_attributes = ['cn', 'cospriority', 'krbpwdpolicyreference']
takes_params = (
Str('cn', primary_key=True),
Str('krbpwdpolicyreference'),
DNParam('krbpwdpolicyreference'),
Int('cospriority', minvalue=0),
)
@ -102,8 +103,7 @@ class cosentry(LDAPObject):
)['result']
if len(entries) > 0:
group_name = self.api.Object.group.get_primary_key_from_dn(
entries[0]['cn'][0]
)
DN(entries[0]['cn'][0]))
raise errors.ValidationError(
name='priority',
error=self.priority_not_unique_msg % {
@ -119,6 +119,7 @@ class cosentry_add(LDAPCreate):
NO_CLI = True
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
# check for existence of the group
result = self.api.Command.group_show(keys[-1], all=True)['result']
oc = map(lambda x:x.lower(),result['objectclass'])
@ -141,6 +142,7 @@ class cosentry_mod(LDAPUpdate):
NO_CLI = True
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
new_cospriority = options.get('cospriority')
if new_cospriority is not None:
cos_entry = self.api.Command.cosentry_show(keys[-1])['result']
@ -167,13 +169,13 @@ api.register(cosentry_find)
global_policy_name = 'global_policy'
global_policy_dn = 'cn=%s,cn=%s,cn=kerberos,%s' % (global_policy_name, api.env.realm, api.env.basedn)
global_policy_dn = DN(('cn', global_policy_name), ('cn', api.env.realm), ('cn', 'kerberos'), api.env.basedn)
class pwpolicy(LDAPObject):
"""
Password Policy object
"""
container_dn = 'cn=%s,cn=kerberos' % api.env.realm
container_dn = DN(('cn', api.env.realm), ('cn', 'kerberos'))
object_name = _('password policy')
object_name_plural = _('password policies')
object_class = ['top', 'nscontainer', 'krbpwdpolicy']
@ -339,6 +341,7 @@ class pwpolicy_add(LDAPCreate):
yield self.obj.primary_key.clone(attribute=True, required=True)
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
self.obj.convert_time_on_input(entry_attrs)
self.obj.validate_lifetime(entry_attrs, True)
self.api.Command.cosentry_add(
@ -348,6 +351,7 @@ class pwpolicy_add(LDAPCreate):
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
self.log.info('%r' % entry_attrs)
# attribute rights are not allowed for pwpolicy_add
self.obj.add_cospriority(entry_attrs, keys[-1], rights=False)
@ -366,7 +370,8 @@ class pwpolicy_del(LDAPDelete):
)
def pre_callback(self, ldap, dn, *keys, **options):
if dn.lower() == global_policy_dn.lower():
assert isinstance(dn, DN)
if dn == global_policy_dn:
raise errors.ValidationError(
name='group',
error=_('cannot delete global password policy')
@ -374,6 +379,7 @@ class pwpolicy_del(LDAPDelete):
return dn
def post_callback(self, ldap, dn, *keys, **options):
assert isinstance(dn, DN)
try:
self.api.Command.cosentry_del(keys[-1])
except errors.NotFound:
@ -387,6 +393,7 @@ class pwpolicy_mod(LDAPUpdate):
__doc__ = _('Modify a group password policy.')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
self.obj.convert_time_on_input(entry_attrs)
self.obj.validate_lifetime(entry_attrs, False, *keys)
setattr(context, 'cosupdate', False)
@ -408,6 +415,7 @@ class pwpolicy_mod(LDAPUpdate):
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
rights = options.get('all', False) and options.get('rights', False)
self.obj.add_cospriority(entry_attrs, keys[-1], rights)
self.obj.convert_time_for_output(entry_attrs, **options)
@ -436,6 +444,7 @@ class pwpolicy_show(LDAPRetrieve):
)
def pre_callback(self, ldap, dn, attrs_list, *keys, **options):
assert isinstance(dn, DN)
if options.get('user') is not None:
user_entry = self.api.Command.user_show(
options['user'], all=True
@ -445,6 +454,7 @@ class pwpolicy_show(LDAPRetrieve):
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
rights = options.get('all', False) and options.get('rights', False)
self.obj.add_cospriority(entry_attrs, keys[-1], rights)
self.obj.convert_time_for_output(entry_attrs, **options)

View File

@ -96,6 +96,7 @@ class range_add(LDAPCreate):
msg_summary = _('Added ID range "%(value)s"')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
if ('ipanttrusteddomainsid' not in options and
'ipasecondarybaserid' not in options):
raise errors.ValidationError(name=_('Range setup'),
@ -110,6 +111,7 @@ class range_add(LDAPCreate):
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
self.obj.handle_iparangetype(entry_attrs, options, keep_objectclass=True)
return dn
@ -128,6 +130,7 @@ class range_find(LDAPSearch):
# Since all range types are stored within separate containers under
# 'cn=ranges,cn=etc' search can be done on a one-level scope
def pre_callback(self, ldap, filters, attrs_list, base_dn, scope, *args, **options):
assert isinstance(base_dn, DN)
attrs_list.append('objectclass')
return (filters, base_dn, ldap.SCOPE_ONELEVEL)
@ -140,10 +143,12 @@ class range_show(LDAPRetrieve):
__doc__ = _('Display information about a range.')
def pre_callback(self, ldap, dn, attrs_list, *keys, **options):
assert isinstance(dn, DN)
attrs_list.append('objectclass')
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
self.obj.handle_iparangetype(entry_attrs, options)
return dn
@ -153,10 +158,12 @@ class range_mod(LDAPUpdate):
msg_summary = _('Modified ID range "%(value)s"')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
attrs_list.append('objectclass')
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
self.obj.handle_iparangetype(entry_attrs, options)
return dn
@ -166,4 +173,3 @@ api.register(range_mod)
api.register(range_del)
api.register(range_find)
api.register(range_show)

View File

@ -234,6 +234,7 @@ class selinuxusermap_add(LDAPCreate):
msg_summary = _('Added SELinux User Map "%(value)s"')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
# rules are enabled by default
entry_attrs['ipaenabledflag'] = 'TRUE'
validate_selinuxuser_inlist(ldap, entry_attrs['ipaselinuxuser'])
@ -243,6 +244,7 @@ class selinuxusermap_add(LDAPCreate):
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
self.obj._convert_seealso(ldap, entry_attrs, **options)
return dn
@ -264,6 +266,7 @@ class selinuxusermap_mod(LDAPUpdate):
msg_summary = _('Modified SELinux User Map "%(value)s"')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
try:
(_dn, _entry_attrs) = ldap.get_entry(dn, attrs_list)
except errors.NotFound:
@ -288,6 +291,7 @@ class selinuxusermap_mod(LDAPUpdate):
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
self.obj._convert_seealso(ldap, entry_attrs, **options)
return dn
@ -331,6 +335,7 @@ class selinuxusermap_show(LDAPRetrieve):
__doc__ = _('Display the properties of a SELinux User Map rule.')
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
self.obj._convert_seealso(ldap, entry_attrs, **options)
return dn
@ -398,6 +403,7 @@ class selinuxusermap_add_user(LDAPAddMember):
member_count_out = ('%i object added.', '%i objects added.')
def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
assert isinstance(dn, DN)
try:
(dn, entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes)
except errors.NotFound:
@ -428,6 +434,7 @@ class selinuxusermap_add_host(LDAPAddMember):
member_count_out = ('%i object added.', '%i objects added.')
def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
assert isinstance(dn, DN)
try:
(dn, entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes)
except errors.NotFound:

View File

@ -278,6 +278,7 @@ class service_add(LDAPCreate):
),
)
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
(service, hostname, realm) = split_principal(keys[-1])
if service.lower() == 'host' and not options['force']:
raise errors.HostService()
@ -322,6 +323,7 @@ class service_del(LDAPDelete):
msg_summary = _('Deleted service "%(value)s"')
member_attributes = ['managedby']
def pre_callback(self, ldap, dn, *keys, **options):
assert isinstance(dn, DN)
# In the case of services we don't want IPA master services to be
# deleted. This is a limited few though. If the user has their own
# custom services allow them to manage them.
@ -367,6 +369,7 @@ class service_mod(LDAPUpdate):
member_attributes = ['managedby']
def pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
if 'usercertificate' in options:
(service, hostname, realm) = split_principal(keys[-1])
cert = options.get('usercertificate')
@ -386,7 +389,9 @@ class service_mod(LDAPUpdate):
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
set_certificate_attrs(entry_attrs)
return dn
api.register(service_mod)
@ -402,6 +407,7 @@ class service_find(LDAPSearch):
has_output_params = LDAPSearch.has_output_params + output_params
def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *args, **options):
assert isinstance(base_dn, DN)
# lisp style!
custom_filter = '(&(objectclass=ipaService)' \
'(!(objectClass=posixAccount))' \
@ -439,6 +445,7 @@ class service_show(LDAPRetrieve):
has_output_params = LDAPRetrieve.has_output_params + output_params
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
self.obj.get_password_attributes(ldap, dn, entry_attrs)
set_certificate_attrs(entry_attrs)

View File

@ -246,6 +246,7 @@ class sudorule_add(LDAPCreate):
__doc__ = _('Create new Sudo Rule.')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
self.obj.check_order_uniqueness(*keys, **options)
# Sudo Rules are enabled by default
entry_attrs['ipaenabledflag'] = 'TRUE'
@ -269,6 +270,7 @@ class sudorule_mod(LDAPUpdate):
msg_summary = _('Modified Sudo Rule "%(value)s"')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
if 'sudoorder' in options:
new_order = options.get('sudoorder')
old_entry = self.api.Command.sudorule_show(keys[-1])['result']
@ -371,6 +373,7 @@ class sudorule_add_allow_command(LDAPAddMember):
member_count_out = ('%i object added.', '%i objects added.')
def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
assert isinstance(dn, DN)
try:
(_dn, _entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes)
except errors.NotFound:
@ -399,6 +402,7 @@ class sudorule_add_deny_command(LDAPAddMember):
member_count_out = ('%i object added.', '%i objects added.')
def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
assert isinstance(dn, DN)
try:
(_dn, _entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes)
except errors.NotFound:
@ -426,6 +430,7 @@ class sudorule_add_user(LDAPAddMember):
member_count_out = ('%i object added.', '%i objects added.')
def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
assert isinstance(dn, DN)
try:
(_dn, _entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes)
except errors.NotFound:
@ -435,6 +440,7 @@ class sudorule_add_user(LDAPAddMember):
return add_external_pre_callback('user', ldap, dn, keys, options)
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return add_external_post_callback('memberuser', 'user', 'externaluser', ldap, completed, failed, dn, entry_attrs, keys, options)
api.register(sudorule_add_user)
@ -447,6 +453,7 @@ class sudorule_remove_user(LDAPRemoveMember):
member_count_out = ('%i object removed.', '%i objects removed.')
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return remove_external_post_callback('memberuser', 'user', 'externaluser', ldap, completed, failed, dn, entry_attrs, keys, options)
api.register(sudorule_remove_user)
@ -459,6 +466,7 @@ class sudorule_add_host(LDAPAddMember):
member_count_out = ('%i object added.', '%i objects added.')
def pre_callback(self, ldap, dn, found, not_found, *keys, **options):
assert isinstance(dn, DN)
try:
(_dn, _entry_attrs) = ldap.get_entry(dn, self.obj.default_attributes)
except errors.NotFound:
@ -468,6 +476,7 @@ class sudorule_add_host(LDAPAddMember):
return add_external_pre_callback('host', ldap, dn, keys, options)
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return add_external_post_callback('memberhost', 'host', 'externalhost', ldap, completed, failed, dn, entry_attrs, keys, options)
api.register(sudorule_add_host)
@ -480,6 +489,7 @@ class sudorule_remove_host(LDAPRemoveMember):
member_count_out = ('%i object removed.', '%i objects removed.')
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return remove_external_post_callback('memberhost', 'host', 'externalhost', ldap, completed, failed, dn, entry_attrs, keys, options)
api.register(sudorule_remove_host)
@ -491,6 +501,7 @@ class sudorule_add_runasuser(LDAPAddMember):
member_count_out = ('%i object added.', '%i objects added.')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
def check_validity(runas):
v = unicode(runas)
if v.upper() == u'ALL':
@ -521,6 +532,7 @@ class sudorule_add_runasuser(LDAPAddMember):
return add_external_pre_callback('user', ldap, dn, keys, options)
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return add_external_post_callback('ipasudorunas', 'user', 'ipasudorunasextuser', ldap, completed, failed, dn, entry_attrs, keys, options)
api.register(sudorule_add_runasuser)
@ -533,6 +545,7 @@ class sudorule_remove_runasuser(LDAPRemoveMember):
member_count_out = ('%i object removed.', '%i objects removed.')
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return remove_external_post_callback('ipasudorunas', 'user', 'ipasudorunasextuser', ldap, completed, failed, dn, entry_attrs, keys, options)
api.register(sudorule_remove_runasuser)
@ -545,6 +558,7 @@ class sudorule_add_runasgroup(LDAPAddMember):
member_count_out = ('%i object added.', '%i objects added.')
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
def check_validity(runas):
v = unicode(runas)
if v.upper() == u'ALL':
@ -569,6 +583,7 @@ class sudorule_add_runasgroup(LDAPAddMember):
return add_external_pre_callback('group', ldap, dn, keys, options)
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return add_external_post_callback('ipasudorunasgroup', 'group', 'ipasudorunasextgroup', ldap, completed, failed, dn, entry_attrs, keys, options)
api.register(sudorule_add_runasgroup)
@ -581,6 +596,7 @@ class sudorule_remove_runasgroup(LDAPRemoveMember):
member_count_out = ('%i object removed.', '%i objects removed.')
def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
return remove_external_post_callback('ipasudorunasgroup', 'group', 'ipasudorunasextgroup', ldap, completed, failed, dn, entry_attrs, keys, options)
api.register(sudorule_remove_runasgroup)

View File

@ -107,9 +107,10 @@ class trust(LDAPObject):
)
def make_trust_dn(env, trust_type, dn):
assert isinstance(dn, DN)
if trust_type in trust.trust_types:
container_dn = DN(('cn', trust_type), env.container_trusts, env.basedn)
return unicode(DN(DN(dn)[0], container_dn))
return DN(dn[0], container_dn)
return dn
class trust_add(LDAPCreate):
@ -214,6 +215,7 @@ class trust_del(LDAPDelete):
msg_summary = _('Deleted trust "%(value)s"')
def pre_callback(self, ldap, dn, *keys, **options):
assert isinstance(dn, DN)
try:
result = self.api.Command.trust_show(keys[-1])
except errors.NotFound, e:
@ -226,6 +228,7 @@ class trust_mod(LDAPUpdate):
msg_summary = _('Modified trust "%(value)s"')
def pre_callback(self, ldap, dn, *keys, **options):
assert isinstance(dn, DN)
result = None
try:
result = self.api.Command.trust_show(keys[-1])
@ -245,6 +248,7 @@ class trust_find(LDAPSearch):
# Since all trusts types are stored within separate containers under 'cn=trusts',
# search needs to be done on a sub-tree scope
def pre_callback(self, ldap, filters, attrs_list, base_dn, scope, *args, **options):
assert isinstance(base_dn, DN)
return (filters, base_dn, ldap.SCOPE_SUBTREE)
class trust_show(LDAPRetrieve):
@ -271,6 +275,7 @@ class trust_show(LDAPRetrieve):
return result
def pre_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
if 'trust_show_type' in options:
return make_trust_dn(self.env, options['trust_show_type'], dn)
return dn
@ -281,4 +286,3 @@ api.register(trust_mod)
api.register(trust_del)
api.register(trust_find)
api.register(trust_show)

View File

@ -375,11 +375,12 @@ class user(LDAPObject):
if not manager:
return None
if isinstance(manager, basestring):
if not isinstance(manager, list):
manager = [manager]
try:
container_dn = DN(self.container_dn, api.env.basedn)
for m in xrange(len(manager)):
if manager[m].endswith('%s,%s' % (self.container_dn, api.env.basedn)):
if isinstance(manager[m], DN) and manager[m].endswith(container_dn):
continue
(dn, entry_attrs) = self.backend.find_entry_by_attr(
self.primary_key.name, manager[m], self.object_class, [''],
@ -420,6 +421,7 @@ class user_add(LDAPCreate):
)
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
if not options.get('noprivate', False):
try:
# The Managed Entries plugin will allow a user to be created
@ -459,7 +461,9 @@ class user_add(LDAPCreate):
homes_root = config.get('ipahomesrootdir', ['/home'])[0]
# build user's home directory based on his uid
entry_attrs['homedirectory'] = posixpath.join(homes_root, keys[-1])
entry_attrs.setdefault('krbpwdpolicyreference', 'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn))
entry_attrs.setdefault('krbpwdpolicyreference',
DN(('cn', 'global_policy'), ('cn', api.env.realm), ('cn', 'kerberos'),
api.env.basedn))
entry_attrs.setdefault('krbprincipalname', '%s@%s' % (entry_attrs['uid'], api.env.realm))
if entry_attrs.get('gidnumber', DNA_MAGIC) == DNA_MAGIC:
@ -496,6 +500,7 @@ class user_add(LDAPCreate):
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
config = ldap.get_ipa_config()[1]
# add the user we just created into the default primary group
def_primary_group = config.get('ipadefaultprimarygroup')
@ -544,6 +549,7 @@ class user_del(LDAPDelete):
msg_summary = _('Deleted user "%(value)s"')
def pre_callback(self, ldap, dn, *keys, **options):
assert isinstance(dn, DN)
protected_group_name = u'admins'
result = api.Command.group_show(protected_group_name)
if result['result'].get('member_user', []) == [keys[-1]]:
@ -562,6 +568,7 @@ class user_mod(LDAPUpdate):
has_output_params = LDAPUpdate.has_output_params + user_output_params
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN)
if options.get('rename') is not None:
config = ldap.get_ipa_config()[1]
if 'ipamaxusernamelength' in config:
@ -592,6 +599,7 @@ class user_mod(LDAPUpdate):
return dn
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
if options.get('random', False):
try:
entry_attrs['randompassword'] = unicode(getattr(context, 'randompassword'))
@ -621,6 +629,7 @@ class user_find(LDAPSearch):
)
def pre_callback(self, ldap, filter, attrs_list, base_dn, scope, *keys, **options):
assert isinstance(base_dn, DN)
if options.get('whoami'):
return ("(&(objectclass=posixaccount)(krbprincipalname=%s))"%\
getattr(context, 'principal'), base_dn, scope)
@ -651,6 +660,7 @@ class user_show(LDAPRetrieve):
has_output_params = LDAPRetrieve.has_output_params + user_output_params
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
assert isinstance(dn, DN)
convert_nsaccountlock(entry_attrs)
self.obj._convert_manager(entry_attrs, **options)
self.obj.get_password_attributes(ldap, dn, entry_attrs)
@ -763,7 +773,7 @@ class user_status(LDAPQuery):
# Get list of masters
try:
(masters, truncated) = ldap.find_entries(
None, ['*'], 'cn=masters,cn=ipa,cn=etc,%s' % api.env.basedn,
None, ['*'], DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn),
ldap.SCOPE_ONELEVEL
)
except errors.NotFound:

View File

@ -23,6 +23,7 @@ Base classes for non-LDAP backend plugins.
from ipalib import api
from ipalib import Command
from ipalib import errors
from ipapython.dn import DN
class VirtualCommand(Command):
"""
@ -55,7 +56,7 @@ class VirtualCommand(Command):
ldap = self.api.Backend.ldap2
self.log.debug("IPA: virtual verify %s" % operation)
operationdn = "cn=%s,%s,%s" % (operation, self.api.env.container_virtual, self.api.env.basedn)
operationdn = DN(('cn', operation), self.api.env.container_virtual, self.api.env.basedn)
try:
if not ldap.can_write(operationdn, "objectclass"):

View File

@ -57,6 +57,7 @@ from nss.error import NSPRError
from urllib2 import urlparse
from ipalib.krb_utils import KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, KRB5KRB_AP_ERR_TKT_EXPIRED, \
KRB5_FCC_PERM, KRB5_FCC_NOFILE, KRB5_CC_FORMAT, KRB5_REALM_CANT_RESOLVE
from ipapython.dn import DN
COOKIE_NAME = 'ipa_session_cookie:%s'
@ -83,7 +84,7 @@ def xml_wrap(value):
"""
if type(value) in (list, tuple):
return tuple(xml_wrap(v) for v in value)
if type(value) is dict:
if isinstance(value, dict):
return dict(
(k, xml_wrap(v)) for (k, v) in value.iteritems()
)
@ -92,6 +93,8 @@ def xml_wrap(value):
if type(value) is Decimal:
# transfer Decimal as a string
return unicode(value)
if isinstance(value, DN):
return str(value)
assert type(value) in (unicode, int, float, bool, NoneType)
return value

View File

@ -628,7 +628,7 @@ mod_auth_kerb. Everything else remains the same.
default_max_session_duration = 60*60 # number of seconds
ISO8601_DATETIME_FMT = '%Y-%m-%dT%H:%M:%S' # FIXME jrd, this should be defined elsewhere
ISO8601_DATETIME_FMT = '%Y-%m-%dT%H:%M:%S' # FIXME, this should be defined elsewhere
def fmt_time(timestamp):
return time.strftime(ISO8601_DATETIME_FMT, time.localtime(timestamp))

View File

@ -33,8 +33,8 @@ from dns.exception import DNSException
from ipalib import errors
from ipalib.text import _
from ipalib.dn import DN, RDN
from ipapython.ipautil import decode_ssh_pubkey
from ipapython.dn import DN, RDN
def json_serialize(obj):
@ -472,10 +472,3 @@ def validate_rdn_param(ugettext, value):
except Exception, e:
return str(e)
return None
def validate_dn_param(ugettext, value):
try:
rdn = DN(value)
except Exception, e:
return str(e)
return None

View File

@ -42,7 +42,7 @@ from ipalib import api
from ipalib import _
from ipalib import util
from ipalib import errors
from ipalib.dn import DN
from ipapython.dn import DN
PEM = 0
DER = 1

File diff suppressed because it is too large Load Diff

View File

@ -18,6 +18,7 @@
import copy
from ipapython import ipautil
from ipapython.dn import DN
def copy_CIDict(x):
"""Do a deep copy of a CIDict"""
@ -45,19 +46,25 @@ class Entity:
if isinstance(entrydata,tuple):
self.dn = entrydata[0]
self.data = ipautil.CIDict(entrydata[1])
elif isinstance(entrydata,str) or isinstance(entrydata,unicode):
elif isinstance(entrydata, DN):
self.dn = entrydata
self.data = ipautil.CIDict()
elif isinstance(entrydata, basestring):
self.dn = DN(entrydata)
self.data = ipautil.CIDict()
elif isinstance(entrydata,dict):
self.dn = entrydata['dn']
del entrydata['dn']
self.data = ipautil.CIDict(entrydata)
else:
self.dn = ''
self.dn = DN()
self.data = ipautil.CIDict()
assert isinstance(self.dn, DN)
self.orig_data = ipautil.CIDict(copy_CIDict(self.data))
dn = ipautil.dn_attribute_property('_dn')
def __nonzero__(self):
"""This allows us to do tests like if entry: returns false if there is no data,
true otherwise"""
@ -67,23 +74,8 @@ class Entity:
"""Return True if this entry has an attribute named name, False otherwise"""
return self.data and self.data.has_key(name)
def __setattr__(self,name,value):
"""One should use setValue() or setValues() to set values except for
dn and data which are special."""
if name != 'dn' and name != 'data' and name != 'orig_data':
raise KeyError, 'use setValue() or setValues()'
else:
self.__dict__[name] = value
def __getattr__(self,name):
"""If name is the name of an LDAP attribute, return the first value for that
attribute - equivalent to getValue - this allows the use of
entry.cn
instead of
entry.getValue('cn')
This also allows us to return None if an attribute is not found rather than
throwing an exception"""
return self.getValue(name)
def __str__(self):
return "dn: %s data: %s" % (self.dn, self.data)
def getValues(self,name):
"""Get the list (array) of values for the attribute named name"""
@ -150,6 +142,7 @@ class Entity:
def toDict(self):
"""Convert the attrs and values to a dict. The dict is keyed on the
attribute name. The value is either single value or a list of values."""
assert isinstance(self.dn, DN)
result = ipautil.CIDict(self.data)
result['dn'] = self.dn
return result
@ -160,6 +153,7 @@ class Entity:
def origDataDict(self):
"""Returns a dict of the original values of the user. Used for updates."""
assert isinstance(self.dn, DN)
result = ipautil.CIDict(self.orig_data)
result['dn'] = self.dn
return result

View File

@ -101,10 +101,10 @@ class IPALogManager(LogManager):
in the Env config must begin with "log_logger_level\_" and then be
followed by a symbolic or numeric log level, for example::
log_logger_level_debug = ipalib\.dn\..*
log_logger_level_debug = ipapython\.dn\..*
log_logger_level_35 = ipalib\.plugins\.dogtag
The first line says any logger belonging to the ipalib.dn module
The first line says any logger belonging to the ipapython.dn module
will have it's level configured to debug.
The second line say the ipa.plugins.dogtag logger will be

View File

@ -49,6 +49,7 @@ from dns.exception import DNSException
from ipapython.ipa_log_manager import *
from ipapython import ipavalidate
from ipapython import config
from ipapython.dn import DN
try:
from subprocess import CalledProcessError
@ -200,10 +201,16 @@ def format_netloc(host, port=None):
return '%s:%s' % (host, str(port))
def realm_to_suffix(realm_name):
"""Convert a kerberos realm into the IPA suffix."""
'Convert a kerberos realm to a IPA suffix.'
s = realm_name.split(".")
terms = ["dc=" + x.lower() for x in s]
return ",".join(terms)
suffix_dn = DN(*[('dc', x.lower()) for x in s])
return suffix_dn
def suffix_to_realm(suffix_dn):
'Convert a IPA suffix to a kerberos realm.'
assert isinstance(suffix_dn, DN)
realm = '.'.join([x.value for x in suffix_dn])
return realm
def template_str(txt, vars):
val = string.Template(txt).substitute(vars)
@ -1111,3 +1118,33 @@ def kinit_hostprincipal(keytab, ccachedir, principal):
return ccache_file
except krbV.Krb5Error, e:
raise StandardError('Error initializing principal %s in %s: %s' % (principal, keytab, str(e)))
def dn_attribute_property(private_name):
'''
Create a property for a dn attribute which assures the attribute
is a DN or None. If the value is not None the setter converts it to
a DN. The getter assures it's either None or a DN instance.
The private_name parameter is the class internal attribute the property
shadows.
For example if a class has an attribute called base_dn, then:
base_dn = dn_attribute_property('_base_dn')
Thus the class with have an attriubte called base_dn which can only
ever be None or a DN instance. The actual value is stored in _base_dn.
'''
def setter(self, value):
if value is not None:
value = DN(value)
setattr(self, private_name, value)
def getter(self):
value = getattr(self, private_name)
if value is not None:
assert isinstance(value, DN)
return value
return property(getter, setter)

View File

@ -1,69 +0,0 @@
# Authors: Rob Crittenden <rcritten@redhat.com>
#
# Copyright (C) 2008 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
import krbV
import ldap
import ldap.dn
import ipaldap
class IPAConn:
def __init__(self, host, port, krbccache, debug=None):
self._conn = None
# Save the arguments
self._host = host
self._port = port
self._krbccache = krbccache
self._debug = debug
self._ctx = krbV.default_context()
ccache = krbV.CCache(name=krbccache, context=self._ctx)
cprinc = ccache.principal()
self._conn = ipaldap.IPAdmin(host,port,None,None,None,debug)
# This will bind the connection
try:
self._conn.set_krbccache(krbccache, cprinc.name)
except ldap.UNWILLING_TO_PERFORM, e:
raise e
except Exception, e:
raise e
def __del__(self):
# take no chances on unreleased connections
self.releaseConn()
def getConn(self):
return self._conn
def releaseConn(self):
if self._conn is None:
return
self._conn.unbind_s()
self._conn = None
return
if __name__ == "__main__":
ipaconn = IPAConn("localhost", 389, "FILE:/tmp/krb5cc_500")
x = ipaconn.getConn().getEntry("dc=example,dc=com", ldap.SCOPE_SUBTREE, "uid=admin", ["cn"])
print "%s" % x

View File

@ -101,7 +101,7 @@ class DomainValidator(object):
def is_configured(self):
cn_trust_local = DN(('cn', self.api.env.domain), self.api.env.container_cifsdomains, self.api.env.basedn)
try:
(dn, entry_attrs) = self.ldap.get_entry(unicode(cn_trust_local), [self.ATTR_FLATNAME, self.ATTR_SID])
(dn, entry_attrs) = self.ldap.get_entry(cn_trust_local, [self.ATTR_FLATNAME, self.ATTR_SID])
self.flatname = entry_attrs[self.ATTR_FLATNAME][0]
self.sid = entry_attrs[self.ATTR_SID][0]
self.dn = dn
@ -115,7 +115,7 @@ class DomainValidator(object):
try:
search_kw = {'objectClass': 'ipaNTTrustedDomain'}
filter = self.ldap.make_filter(search_kw, rules=self.ldap.MATCH_ALL)
(entries, truncated) = self.ldap.find_entries(filter=filter, base_dn=unicode(cn_trust),
(entries, truncated) = self.ldap.find_entries(filter=filter, base_dn=cn_trust,
attrs_list=[self.ATTR_TRUSTED_SID, 'dn'])
return entries
@ -447,5 +447,3 @@ class TrustDomainJoins(object):
self.__populate_remote_domain(realm, realm_server, realm_passwd=None)
self.local_domain.establish_trust(self.remote_domain, trustdom_passwd)
return dict(local=self.local_domain, remote=self.remote_domain)

View File

@ -29,11 +29,12 @@ from ipaserver.install.dsinstance import realm_to_serverid
from ipaserver.install.bindinstance import get_rr, add_rr, del_rr, \
dns_zone_exists
from ipalib import errors, api
from ipalib.dn import DN
from ipapython.dn import DN
from ipapython import sysrestore
from ipapython import ipautil
from ipapython.ipa_log_manager import *
from ipapython import services as ipaservices
from ipapython.dn import DN
import string
import struct
@ -103,7 +104,7 @@ class ADTRUSTInstance(service.Service):
self.netbios_name = None
self.no_msdcs = None
self.smbd_user = None
self.suffix = None
self.suffix = DN()
self.ldapi_socket = None
self.smb_conf = None
self.smb_dn = None
@ -129,11 +130,10 @@ class ADTRUSTInstance(service.Service):
return "S-1-5-21-%d-%d-%d" % (sub_ids[0], sub_ids[1], sub_ids[2])
def __add_admin_sids(self):
admin_dn = str(DN(('uid', 'admin'), api.env.container_user,
self.suffix))
admin_group_dn = str(DN(('cn', 'admins'), api.env.container_group,
self.suffix))
admin_dn = DN(('uid', 'admin'), api.env.container_user,
self.suffix)
admin_group_dn = DN(('cn', 'admins'), api.env.container_group,
self.suffix)
try:
dom_entry = self.admin_conn.getEntry(self.smb_dom_dn, \
ldap.SCOPE_BASE)
@ -186,10 +186,9 @@ class ADTRUSTInstance(service.Service):
"""
try:
res = self.admin_conn.search_s(str(DN(api.env.container_ranges,
self.suffix)),
ldap.SCOPE_ONELEVEL,
"(objectclass=ipaDomainIDRange)")
res = self.admin_conn.getList(DN(api.env.container_ranges, self.suffix),
ldap.SCOPE_ONELEVEL,
"(objectclass=ipaDomainIDRange)")
if len(res) != 1:
root_logger.critical("Found more than one ID range for the " \
"local domain.")
@ -230,17 +229,18 @@ class ADTRUSTInstance(service.Service):
pass
for new_dn in (self.trust_dn, \
str(DN(('cn', 'ad'), self.trust_dn)), \
str(DN(api.env.container_cifsdomains, self.suffix))):
DN(('cn', 'ad'), self.trust_dn), \
DN(api.env.container_cifsdomains, self.suffix)):
try:
self.admin_conn.getEntry(new_dn, ldap.SCOPE_BASE)
except errors.NotFound:
entry = ipaldap.Entry(new_dn)
entry.setValues("objectclass", ["nsContainer"])
name = new_dn.split('=')[1].split(',')[0]
if not name:
print "Cannot extract RDN attribute value from [%s]" % \
new_dn
try:
name = new_dn[1].attr
except Exception, e:
print 'Cannot extract RDN attribute value from "%s": %s' % \
(new_dn, e)
return
entry.setValues("cn", name)
self.admin_conn.addEntry(entry)
@ -474,16 +474,16 @@ class ADTRUSTInstance(service.Service):
self.smb_conf = "/etc/samba/smb.conf"
self.smb_dn = str(DN(('cn', 'adtrust agents'), ('cn', 'sysaccounts'),
('cn', 'etc'), self.suffix))
self.smb_dn = DN(('cn', 'adtrust agents'), ('cn', 'sysaccounts'),
('cn', 'etc'), self.suffix)
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.trust_dn = DN(api.env.container_trusts, self.suffix)
self.smb_dom_dn = DN(('cn', self.domain_name),
api.env.container_cifsdomains, self.suffix)
self.cifs_principal = "cifs/" + self.fqdn + "@" + self.realm
self.cifs_agent = str(DN(('krbprincipalname', self.cifs_principal.lower()),
api.env.container_service,
self.suffix))
self.cifs_agent = DN(('krbprincipalname', self.cifs_principal.lower()),
api.env.container_service,
self.suffix)
self.selinux_booleans = ["samba_portmapper"]
self.__setup_sub_dict()
@ -491,16 +491,13 @@ class ADTRUSTInstance(service.Service):
def find_local_id_range(self):
self.ldap_connect()
if self.admin_conn.search_s(str(DN(api.env.container_ranges,
self.suffix)),
if self.admin_conn.search_s(DN(api.env.container_ranges, self.suffix),
ldap.SCOPE_ONELEVEL,
"objectclass=ipaDomainIDRange"):
return
try:
entry = self.admin_conn.getEntry(str(DN(('cn', 'admins'),
api.env.container_group,
self.suffix)),
entry = self.admin_conn.getEntry(DN(('cn', 'admins'), api.env.container_group, self.suffix),
ldap.SCOPE_BASE)
except errors.NotFound:
raise ValueError("No local ID range and no admins group found.\n" \
@ -523,9 +520,9 @@ class ADTRUSTInstance(service.Service):
"range.\nAdd local ID range manually and try " \
"again!")
entry = ipaldap.Entry(str(DN(('cn', ('%s_id_range' % self.realm)),
api.env.container_ranges,
self.suffix)))
entry = ipaldap.Entry(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))
entry.setValue('ipaBaseID', str(base_id))

View File

@ -38,6 +38,7 @@ from ipapython.ipa_log_manager import *
import ipalib
from ipalib import api, util, errors
from ipapython.dn import DN
NAMED_CONF = '/etc/named.conf'
RESOLV_CONF = '/etc/resolv.conf'
@ -166,10 +167,11 @@ def dns_container_exists(fqdn, suffix, dm_password=None, ldapi=False, realm=None
Test whether the dns container exists.
"""
def object_exists(dn):
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.search_ext_s(dn, ldap.SCOPE_BASE)
except ldap.NO_SUCH_OBJECT:
@ -177,6 +179,7 @@ def dns_container_exists(fqdn, suffix, dm_password=None, ldapi=False, realm=None
else:
return True
assert isinstance(suffix, DN)
try:
# At install time we may need to use LDAPI to avoid chicken/egg
# issues with SSL certs and truting CAs
@ -192,7 +195,7 @@ def dns_container_exists(fqdn, suffix, dm_password=None, ldapi=False, realm=None
except ldap.SERVER_DOWN:
raise RuntimeError('LDAP server on %s is not responding. Is IPA installed?' % fqdn)
ret = object_exists("cn=dns,%s" % suffix)
ret = object_exists(DN(('cn', 'dns'), suffix))
conn.unbind_s()
return ret
@ -288,11 +291,14 @@ def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None, ns_ip_addres
ns_main = ns_hostname
ns_replicas = []
if ns_ip_address is not None:
ns_ip_address = unicode(ns_ip_address)
try:
api.Command.dnszone_add(unicode(name),
idnssoamname=unicode(ns_main+'.'),
idnssoarname=unicode(zonemgr),
ip_address=unicode(ns_ip_address),
ip_address=ns_ip_address,
idnsallowdynupdate=True,
idnsupdatepolicy=unicode(update_policy),
idnsallowquery=u'any',
@ -329,11 +335,14 @@ def add_reverse_zone(zone, ns_hostname=None, ns_ip_address=None,
ns_main = ns_hostname
ns_replicas = []
if ns_ip_address is not None:
ns_ip_address = unicode(ns_ip_address)
try:
api.Command.dnszone_add(unicode(zone),
idnssoamname=unicode(ns_main+'.'),
idnsallowdynupdate=True,
ip_address=unicode(ns_ip_address),
ip_address=ns_ip_address,
idnsupdatepolicy=unicode(update_policy),
idnsallowquery=u'any',
idnsallowtransfer=u'none',)
@ -465,6 +474,8 @@ class BindInstance(service.Service):
else:
self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
suffix = ipautil.dn_attribute_property('_suffix')
def setup(self, fqdn, ip_address, realm_name, domain_name, forwarders, ntp,
reverse_zone, named_user="named", zonemgr=None,
zone_refresh=0, persistent_search=True, serial_autoincrement=True):
@ -574,7 +585,7 @@ class BindInstance(service.Service):
if self.ntp:
optional_ntp = "\n;ntp server\n"
optional_ntp += "_ntp._udp\t\tIN SRV 0 100 123\t%s""" % self.host_in_rr
optional_ntp += "_ntp._udp\t\tIN SRV 0 100 123\t%s" % self.host_in_rr
else:
optional_ntp = ""
@ -654,7 +665,8 @@ class BindInstance(service.Service):
p = self.move_service(dns_principal)
if p is None:
# the service has already been moved, perhaps we're doing a DNS reinstall
dns_principal = "krbprincipalname=%s,cn=services,cn=accounts,%s" % (dns_principal, self.suffix)
dns_principal = DN(('krbprincipalname', dns_principal),
('cn', 'services'), ('cn', 'accounts'), self.suffix)
else:
dns_principal = p
@ -667,9 +679,7 @@ class BindInstance(service.Service):
# it can host the memberof attribute, then also add it to the
# dnsserver role group, this way the DNS is allowed to perform
# DNS Updates
dns_group = "cn=DNS Servers,cn=privileges,cn=pbac,%s" % self.suffix
if isinstance(dns_principal, unicode):
dns_principal = dns_principal.encode('utf-8')
dns_group = DN(('cn', 'DNS Servers'), ('cn', 'privileges'), ('cn', 'pbac'), self.suffix)
mod = [(ldap.MOD_ADD, 'member', dns_principal)]
try:

View File

@ -39,7 +39,7 @@ from ipapython import dogtag
from ipapython.certdb import get_ca_nickname
from ipapython import certmonger
from ipalib import pkcs10, x509
from ipalib.dn import DN
from ipapython.dn import DN
import subprocess
from nss.error import NSPRError
@ -243,7 +243,9 @@ class CADSInstance(service.Service):
self.suffix = ipautil.realm_to_suffix(self.realm_name)
self.__setup_sub_dict()
else:
self.suffix = None
self.suffix = DN()
subject_base = ipautil.dn_attribute_property('_subject_base')
def create_instance(self, realm_name, host_name, domain_name,
dm_password, pkcs12_info=None, ds_port=DEFAULT_DSPORT,
@ -268,7 +270,7 @@ class CADSInstance(service.Service):
def __setup_sub_dict(self):
server_root = dsinstance.find_server_root()
self.sub_dict = dict(FQDN=self.fqdn, SERVERID=self.serverid,
PASSWORD=self.dm_password, SUFFIX=self.suffix.lower(),
PASSWORD=self.dm_password, SUFFIX=self.suffix,
REALM=self.realm_name, USER=PKI_DS_USER,
SERVER_ROOT=server_root, DOMAIN=self.domain,
TIME=int(time.time()), DSPORT=self.ds_port,
@ -342,7 +344,7 @@ class CADSInstance(service.Service):
def enable_ssl(self):
conn = ipaldap.IPAdmin("127.0.0.1", port=DEFAULT_DSPORT)
conn.simple_bind_s("cn=directory manager", self.dm_password)
conn.simple_bind_s(DN(('cn', 'directory manager')), self.dm_password)
mod = [(ldap.MOD_REPLACE, "nsSSLClientAuth", "allowed"),
(ldap.MOD_REPLACE, "nsSSL3Ciphers",
@ -350,13 +352,13 @@ class CADSInstance(service.Service):
+rsa_des_sha,+rsa_fips_des_sha,+rsa_3des_sha,+rsa_fips_3des_sha,+fortezza,\
+fortezza_rc4_128_sha,+fortezza_null,+tls_rsa_export1024_with_rc4_56_sha,\
+tls_rsa_export1024_with_des_cbc_sha")]
conn.modify_s("cn=encryption,cn=config", mod)
conn.modify_s(DN(('cn', 'encryption'), ('cn', 'config')), mod)
mod = [(ldap.MOD_ADD, "nsslapd-security", "on"),
(ldap.MOD_ADD, "nsslapd-secureport", str(DEFAULT_DSPORT+1))]
conn.modify_s("cn=config", mod)
conn.modify_s(DN(('cn', 'config')), mod)
entry = ipaldap.Entry("cn=RSA,cn=encryption,cn=config")
entry = ipaldap.Entry(DN(('cn', 'RSA'), ('cn', 'encryption'), ('cn', 'config')))
entry.setValues("objectclass", "top", "nsEncryptionModule")
entry.setValues("cn", "RSA")
@ -460,7 +462,7 @@ class CAInstance(service.Service):
# will already have been initialized by Apache by the time
# mod_python wants to do things.
self.canickname = get_ca_nickname(realm)
self.basedn = "o=ipaca"
self.basedn = DN(('o', 'ipaca'))
self.ca_agent_db = tempfile.mkdtemp(prefix = "tmp-")
self.ra_agent_db = ra_db
self.ra_agent_pwd = self.ra_agent_db + "/pwdfile.txt"
@ -506,7 +508,7 @@ class CAInstance(service.Service):
self.clone = True
self.master_host = master_host
if subject_base is None:
self.subject_base = "O=%s" % self.realm
self.subject_base = DN(('O', self.realm))
else:
self.subject_base = subject_base
@ -615,12 +617,12 @@ class CAInstance(service.Service):
"-agent_name", "ipa-ca-agent",
"-agent_key_size", "2048",
"-agent_key_type", "rsa",
"-agent_cert_subject", "CN=ipa-ca-agent,%s" % self.subject_base,
"-agent_cert_subject", str(DN(('CN', 'ipa-ca-agent'), self.subject_base)),
"-ldap_host", self.fqdn,
"-ldap_port", str(self.ds_port),
"-bind_dn", "cn=Directory Manager",
"-bind_password", self.dm_password,
"-base_dn", self.basedn,
"-base_dn", str(self.basedn),
"-db_name", "ipaca",
"-key_size", "2048",
"-key_type", "rsa",
@ -629,11 +631,12 @@ class CAInstance(service.Service):
"-backup_pwd", self.admin_password,
"-subsystem_name", self.service_name,
"-token_name", "internal",
"-ca_subsystem_cert_subject_name", "CN=CA Subsystem,%s" % self.subject_base,
"-ca_ocsp_cert_subject_name", "CN=OCSP Subsystem,%s" % self.subject_base,
"-ca_server_cert_subject_name", "CN=%s,%s" % (self.fqdn, self.subject_base),
"-ca_audit_signing_cert_subject_name", "CN=CA Audit,%s" % self.subject_base,
"-ca_sign_cert_subject_name", "CN=Certificate Authority,%s" % self.subject_base ]
"-ca_subsystem_cert_subject_name", str(DN(('CN', 'CA Subsystem'), self.subject_base)),
"-ca_subsystem_cert_subject_name", str(DN(('CN', 'CA Subsystem'), self.subject_base)),
"-ca_ocsp_cert_subject_name", str(DN(('CN', 'OCSP Subsystem'), self.subject_base)),
"-ca_server_cert_subject_name", str(DN(('CN', self.fqdn), self.subject_base)),
"-ca_audit_signing_cert_subject_name", str(DN(('CN', 'CA Audit'), self.subject_base)),
"-ca_sign_cert_subject_name", str(DN(('CN', 'Certificate Authority'), self.subject_base)) ]
if self.external == 1:
args.append("-external")
args.append("true")
@ -836,13 +839,12 @@ class CAInstance(service.Service):
# Create an RA user in the CA LDAP server and add that user to
# the appropriate groups so it can issue certificates without
# manual intervention.
ld = ldap.initialize("ldap://%s" % ipautil.format_netloc(self.fqdn, self.ds_port))
ld.protocol_version=ldap.VERSION3
ld.simple_bind_s("cn=Directory Manager", self.dm_password)
conn = ipaldap.IPAdmin(self.fqdn, self.ds_port)
conn.simple_bind_s(DN(('cn', 'Directory Manager')), self.dm_password)
decoded = base64.b64decode(self.ra_cert)
entry_dn = "uid=%s,ou=People,%s" % ("ipara", self.basedn)
entry_dn = DN(('uid', "ipara"), ('ou', 'People'), self.basedn)
entry = [
('objectClass', ['top', 'person', 'organizationalPerson', 'inetOrgPerson', 'cmsuser']),
('uid', "ipara"),
@ -851,19 +853,23 @@ class CAInstance(service.Service):
('usertype', "agentType"),
('userstate', "1"),
('userCertificate', decoded),
('description', '2;%s;CN=Certificate Authority,%s;CN=IPA RA,%s' % (str(self.requestId), self.subject_base, self.subject_base)),]
('description', '2;%s;%s;%s' % \
(str(self.requestId),
DN(('CN', 'Certificate Authority'), self.subject_base),
DN(('CN', 'IPA RA'), self.subject_base))),
]
ld.add_s(entry_dn, entry)
conn.add_s(entry_dn, entry)
dn = "cn=Certificate Manager Agents,ou=groups,%s" % self.basedn
dn = DN(('cn', 'Certificate Manager Agents'), ('ou', 'groups'), self.basedn)
modlist = [(0, 'uniqueMember', '%s' % entry_dn)]
ld.modify_s(dn, modlist)
conn.modify_s(dn, modlist)
dn = "cn=Registration Manager Agents,ou=groups,%s" % self.basedn
dn = DN(('cn', 'Registration Manager Agents'), ('ou', 'groups'), self.basedn)
modlist = [(0, 'uniqueMember', '%s' % entry_dn)]
ld.modify_s(dn, modlist)
conn.modify_s(dn, modlist)
ld.unbind_s()
conn.unbind_s()
def __run_certutil(self, args, database=None, pwd_file=None,stdin=None):
if not database:
@ -969,7 +975,7 @@ class CAInstance(service.Service):
# Generate our CSR. The result gets put into stdout
try:
(stdout, stderr, returncode) = self.__run_certutil(["-R", "-k", "rsa", "-g", "2048", "-s", "CN=IPA RA,%s" % self.subject_base, "-z", noise_name, "-a"])
(stdout, stderr, returncode) = self.__run_certutil(["-R", "-k", "rsa", "-g", "2048", "-s", str(DN(('CN', 'IPA RA'), self.subject_base)), "-z", noise_name, "-a"])
finally:
os.remove(noise_name)
@ -1071,7 +1077,7 @@ class CAInstance(service.Service):
def __set_subject_in_config(self):
# dogtag ships with an IPA-specific profile that forces a subject
# format. We need to update that template with our base subject
if installutils.update_file(IPA_SERVICE_PROFILE, 'OU=pki-ipa, O=IPA', self.subject_base):
if installutils.update_file(IPA_SERVICE_PROFILE, 'OU=pki-ipa, O=IPA', str(self.subject_base)):
print "Updating subject_base in CA template failed"
def uninstall(self):

View File

@ -39,7 +39,7 @@ from ipalib import pkcs10
from ConfigParser import RawConfigParser, MissingSectionHeaderError
from ipapython import services as ipaservices
from ipalib import x509
from ipalib.dn import DN
from ipapython.dn import DN
from ipalib.errors import CertificateOperationError
from nss.error import NSPRError
@ -224,8 +224,7 @@ class CertDB(object):
self.self_signed_ca = ipa_self_signed()
if not subject_base:
self.subject_base = "O=IPA"
self.subject_format = "CN=%%s,%s" % self.subject_base
self.subject_base = DN(('O', 'IPA'))
self.cacert_name = get_ca_nickname(self.realm)
self.valid_months = "120"
@ -245,6 +244,8 @@ class CertDB(object):
else:
self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
subject_base = ipautil.dn_attribute_property('_subject_base')
def __del__(self):
if self.reqdir is not None:
shutil.rmtree(self.reqdir, ignore_errors=True)
@ -381,11 +382,11 @@ class CertDB(object):
def create_ca_cert(self):
os.chdir(self.secdir)
subject = "cn=%s Certificate Authority" % self.realm
subject = DN(('cn', '%s Certificate Authority' % self.realm))
p = subprocess.Popen(["/usr/bin/certutil",
"-d", self.secdir,
"-S", "-n", self.cacert_name,
"-s", subject,
"-s", str(subject),
"-x",
"-t", "CT,,C",
"-1",
@ -565,7 +566,7 @@ class CertDB(object):
if not cdb:
cdb = self
if subject is None:
subject=self.subject_format % hostname
subject=DN(('CN', hostname), self.subject_base)
self.request_cert(subject)
cdb.issue_server_cert(self.certreq_fname, self.certder_fname)
self.add_cert(self.certder_fname, nickname)
@ -583,7 +584,7 @@ class CertDB(object):
if not cdb:
cdb = self
if subject is None:
subject=self.subject_format % hostname
subject=DN(('CN', hostname), self.subject_base)
self.request_cert(subject)
cdb.issue_signing_cert(self.certreq_fname, self.certder_fname)
self.add_cert(self.certder_fname, nickname)
@ -591,9 +592,10 @@ class CertDB(object):
os.unlink(self.certder_fname)
def request_cert(self, subject, certtype="rsa", keysize="2048"):
assert isinstance(subject, DN)
self.create_noise_file()
self.setup_cert_request()
args = ["-R", "-s", subject,
args = ["-R", "-s", str(subject),
"-o", self.certreq_fname,
"-k", certtype,
"-g", keysize,
@ -1046,19 +1048,19 @@ class CertDB(object):
# Prepare a simple cert request
req_dict = dict(PASSWORD=self.gen_password(),
SUBJBASE=self.subject_base,
CERTNAME="CN="+nickname)
CERTNAME=DN(('CN', nickname)))
req_template = ipautil.SHARE_DIR + reqcfg + ".template"
conf = ipautil.template_file(req_template, req_dict)
fd = open(reqcfg, "w+")
fd.write(conf)
fd.close()
base = self.subject_base.replace(",", "/")
esc_subject = "CN=%s/%s" % (nickname, base)
base = str(self.subject_base).replace(",", "/")
esc_subject = DN(('CN', '%s/%s' % (nickname, base)))
ipautil.run(["/usr/bin/openssl", "req", "-new",
"-config", reqcfg,
"-subj", esc_subject,
"-subj", str(esc_subject),
"-key", key_fname,
"-out", "kdc.req"])

View File

@ -36,12 +36,12 @@ import service
import installutils
import certs
import ldap
from ldap.dn import escape_dn_chars
from ipaserver import ipaldap
from ipaserver.install import ldapupdate
from ipaserver.install import httpinstance
from ipaserver.install import replication
from ipalib import util, errors
from ipapython.dn import DN
from ipaserver.plugins.ldap2 import ldap2
SERVER_ROOT_64 = "/usr/lib64/dirsrv"
@ -177,7 +177,7 @@ class DsInstance(service.Service):
self.suffix = ipautil.realm_to_suffix(self.realm_name)
self.__setup_sub_dict()
else:
self.suffix = None
self.suffix = DN()
if fstore:
self.fstore = fstore
@ -185,6 +185,8 @@ class DsInstance(service.Service):
self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
subject_base = ipautil.dn_attribute_property('_subject_base')
def __common_setup(self):
self.step("creating directory server user", self.__create_ds_user)
@ -299,7 +301,7 @@ class DsInstance(service.Service):
self.fqdn,
self.dm_password)
repl.setup_replication(self.master_fqdn,
r_binddn="cn=Directory Manager",
r_binddn=DN(('cn', 'Directory Manager')),
r_bindpw=self.dm_password)
self.run_init_memberof = repl.needs_memberof_fixup()
@ -314,12 +316,12 @@ class DsInstance(service.Service):
self.sub_dict = dict(FQDN=self.fqdn, SERVERID=self.serverid,
PASSWORD=self.dm_password,
RANDOM_PASSWORD=self.generate_random(),
SUFFIX=self.suffix.lower(),
SUFFIX=self.suffix,
REALM=self.realm_name, USER=DS_USER,
SERVER_ROOT=server_root, DOMAIN=self.domain,
TIME=int(time.time()), IDSTART=self.idstart,
IDMAX=self.idmax, HOST=self.fqdn,
ESCAPED_SUFFIX= escape_dn_chars(self.suffix.lower()),
ESCAPED_SUFFIX=str(self.suffix),
GROUP=DS_GROUP,
IDRANGE_SIZE=self.idmax-self.idstart+1
)
@ -445,11 +447,12 @@ class DsInstance(service.Service):
self._ldap_mod("memberof-task.ldif", self.sub_dict)
# Note, keep dn in sync with dn in install/share/memberof-task.ldif
dn = "cn=IPA install %s,cn=memberof task,cn=tasks,cn=config" % self.sub_dict["TIME"]
dn = DN(('cn', 'IPA install %s' % self.sub_dict["TIME"]), ('cn', 'memberof task'),
('cn', 'tasks'), ('cn', 'config'))
root_logger.debug("Waiting for memberof task to complete.")
conn = ipaldap.IPAdmin("127.0.0.1")
if self.dm_password:
conn.simple_bind_s("cn=directory manager", self.dm_password)
conn.simple_bind_s(DN(('cn', 'directory manager')), self.dm_password)
else:
conn.do_sasl_gssapi_bind()
conn.checkTask(dn, dowait=True)
@ -543,7 +546,7 @@ class DsInstance(service.Service):
dsdb.create_pin_file()
conn = ipaldap.IPAdmin("127.0.0.1")
conn.simple_bind_s("cn=directory manager", self.dm_password)
conn.simple_bind_s(DN(('cn', 'directory manager')), self.dm_password)
mod = [(ldap.MOD_REPLACE, "nsSSLClientAuth", "allowed"),
(ldap.MOD_REPLACE, "nsSSL3Ciphers",
@ -551,12 +554,12 @@ class DsInstance(service.Service):
+rsa_des_sha,+rsa_fips_des_sha,+rsa_3des_sha,+rsa_fips_3des_sha,+fortezza,\
+fortezza_rc4_128_sha,+fortezza_null,+tls_rsa_export1024_with_rc4_56_sha,\
+tls_rsa_export1024_with_des_cbc_sha")]
conn.modify_s("cn=encryption,cn=config", mod)
conn.modify_s(DN(('cn', 'encryption'), ('cn', 'config')), mod)
mod = [(ldap.MOD_ADD, "nsslapd-security", "on")]
conn.modify_s("cn=config", mod)
conn.modify_s(DN(('cn', 'config')), mod)
entry = ipaldap.Entry("cn=RSA,cn=encryption,cn=config")
entry = ipaldap.Entry(DN(('cn', 'RSA'), ('cn', 'encryption'), ('cn', 'config')))
entry.setValues("objectclass", "top", "nsEncryptionModule")
entry.setValues("cn", "RSA")
@ -612,9 +615,9 @@ class DsInstance(service.Service):
os.close(admpwdfd)
args = ["/usr/bin/ldappasswd", "-h", self.fqdn,
"-ZZ", "-x", "-D", "cn=Directory Manager",
"-ZZ", "-x", "-D", str(DN(('cn', 'Directory Manager'))),
"-y", dmpwdfile, "-T", admpwdfile,
"uid=admin,cn=users,cn=accounts,"+self.suffix]
str(DN(('uid', 'admin'), ('cn', 'users'), ('cn', 'accounts'), self.suffix))]
try:
env = { 'LDAPTLS_CACERTDIR':os.path.dirname(CACERT),
'LDAPTLS_CACERT':CACERT }
@ -801,22 +804,19 @@ class DsInstance(service.Service):
def replica_populate(self):
self.ldap_connect()
dn = "cn=default,ou=profile,%s" % self.suffix
dn = DN(('cn', 'default'), ('ou', 'profile'), self.suffix)
try:
ret = self.admin_conn.search_s(dn, ldap.SCOPE_BASE,
'(objectclass=*)')[0]
srvlist = ret.data.get('defaultServerList')
if len(srvlist) > 0:
srvlist = srvlist[0].split()
entry = self.admin_conn.getEntry(dn, ldap.SCOPE_BASE, '(objectclass=*)')
srvlist = entry.getValue('defaultServerList', '')
srvlist = srvlist.split()
if not self.fqdn in srvlist:
srvlist.append(self.fqdn)
attr = ' '.join(srvlist)
mod = [(ldap.MOD_REPLACE, 'defaultServerList', attr)]
self.admin_conn.modify_s(dn, mod)
except ldap.NO_SUCH_OBJECT:
except errors.NotFound:
pass
except ldap.TYPE_OR_VALUE_EXISTS:
pass
self.ldap_disconnect()

View File

@ -57,6 +57,8 @@ class HTTPInstance(service.Service):
else:
self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
subject_base = ipautil.dn_attribute_property('_subject_base')
def create_instance(self, realm, fqdn, domain_name, dm_password=None, autoconfig=True, pkcs12_info=None, self_signed_ca=False, subject_base=None, auto_redirect=True):
self.fqdn = fqdn
self.realm = realm

View File

@ -44,6 +44,7 @@ from ipapython.ipa_log_manager import *
from ipalib.util import validate_hostname
from ipapython import config
from ipalib import errors
from ipapython.dn import DN
# Used to determine install status
IPA_MODULES = ['httpd', 'kadmin', 'dirsrv', 'pki-cad', 'pkids', 'install', 'krb5kdc', 'ntpd', 'named', 'ipa_memcached']
@ -71,9 +72,11 @@ class ReplicaConfig:
self.dirman_password = ""
self.host_name = ""
self.dir = ""
self.subject_base = ""
self.subject_base = None
self.setup_ca = False
subject_base = ipautil.dn_attribute_property('_subject_base')
def get_fqdn():
fqdn = ""
try:

View File

@ -150,6 +150,8 @@ class LDAPUpdater_Upgrade(LDAPUpdater):
class LDAPUpdater_NonUpgrade(LDAPUpdater):
log_file_name = '/var/log/ipaupgrade.log'
def validate_options(self):
super(LDAPUpdater_NonUpgrade, self).validate_options()
options = self.options

View File

@ -33,6 +33,7 @@ from ipapython import services as ipaservices
from ipalib import util
from ipalib import errors
from ipapython.ipa_log_manager import *
from ipapython.dn import DN
from ipaserver import ipaldap
from ipaserver.install import replication
@ -84,6 +85,7 @@ class KrbInstance(service.Service):
self.admin_password = None
self.master_password = None
self.suffix = None
self.subject_base = None
self.kdc_password = None
self.sub_dict = None
self.pkcs12_info = None
@ -94,8 +96,11 @@ class KrbInstance(service.Service):
else:
self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
suffix = ipautil.dn_attribute_property('_suffix')
subject_base = ipautil.dn_attribute_property('_subject_base')
def get_realm_suffix(self):
return "cn=%s,cn=kerberos,%s" % (self.realm, self.suffix)
return DN(('cn', self.realm), ('cn', 'kerberos'), self.suffix)
def move_service_to_host(self, principal):
"""
@ -103,12 +108,12 @@ class KrbInstance(service.Service):
cn=kerberos to reside under the host entry.
"""
service_dn = "krbprincipalname=%s,%s" % (principal, self.get_realm_suffix())
service_dn = DN(('krbprincipalname', principal), self.get_realm_suffix())
service_entry = self.admin_conn.getEntry(service_dn, ldap.SCOPE_BASE)
self.admin_conn.deleteEntry(service_dn)
# Create a host entry for this master
host_dn = "fqdn=%s,cn=computers,cn=accounts,%s" % (self.fqdn, self.suffix)
host_dn = DN(('fqdn', self.fqdn), ('cn', 'computers'), ('cn', 'accounts'), self.suffix)
host_entry = ipaldap.Entry(host_dn)
host_entry.setValues('objectclass', ['top', 'ipaobject', 'nshost', 'ipahost', 'ipaservice', 'pkiuser', 'krbprincipalaux', 'krbprincipal', 'krbticketpolicyaux', 'ipasshhost'])
host_entry.setValues('krbextradata', service_entry.getValues('krbextradata'))
@ -251,7 +256,7 @@ class KrbInstance(service.Service):
# they may conflict.
try:
res = self.admin_conn.search_s("cn=mapping,cn=sasl,cn=config",
res = self.admin_conn.search_s(DN(('cn', 'mapping'), ('cn', 'sasl'), ('cn', 'config')),
ldap.SCOPE_ONELEVEL,
"(objectclass=nsSaslMapping)")
for r in res:
@ -264,7 +269,7 @@ class KrbInstance(service.Service):
root_logger.critical("Error while enumerating SASL mappings %s" % str(e))
raise e
entry = ipaldap.Entry("cn=Full Principal,cn=mapping,cn=sasl,cn=config")
entry = ipaldap.Entry(DN(('cn', 'Full Principal'), ('cn', 'mapping'), ('cn', 'sasl'), ('cn', 'config')))
entry.setValues("objectclass", "top", "nsSaslMapping")
entry.setValues("cn", "Full Principal")
entry.setValues("nsSaslMapRegexString", '\(.*\)@\(.*\)')
@ -277,7 +282,7 @@ class KrbInstance(service.Service):
root_logger.critical("failed to add Full Principal Sasl mapping")
raise e
entry = ipaldap.Entry("cn=Name Only,cn=mapping,cn=sasl,cn=config")
entry = ipaldap.Entry(DN(('cn', 'Name Only'), ('cn', 'mapping'), ('cn', 'sasl'), ('cn', 'config')))
entry.setValues("objectclass", "top", "nsSaslMapping")
entry.setValues("cn", "Name Only")
entry.setValues("nsSaslMapRegexString", '^[^:@]+$')
@ -358,7 +363,7 @@ class KrbInstance(service.Service):
root_logger.critical("Could not find master key in DS")
raise e
krbMKey = pyasn1.codec.ber.decoder.decode(entry.krbmkey)
krbMKey = pyasn1.codec.ber.decoder.decode(entry.getValue('krbmkey'))
keytype = int(krbMKey[0][1][0])
keydata = str(krbMKey[0][1][1])
@ -431,7 +436,7 @@ class KrbInstance(service.Service):
# Create the special anonymous principal
installutils.kadmin_addprinc(princ_realm)
dn = "krbprincipalname=%s,%s" % (princ_realm, self.get_realm_suffix())
dn = DN(('krbprincipalname', princ_realm), self.get_realm_suffix())
self.admin_conn.inactivateEntry(dn, False)
def __convert_to_gssapi_replication(self):
@ -439,7 +444,7 @@ class KrbInstance(service.Service):
self.fqdn,
self.dm_password)
repl.convert_to_gssapi_replication(self.master_fqdn,
r_binddn="cn=Directory Manager",
r_binddn=DN(('cn', 'Directory Manager')),
r_bindpw=self.dm_password)
def uninstall(self):

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,7 @@
from ipaserver.install.plugins import MIDDLE
from ipaserver.install.plugins.baseupdate import PostUpdate
from ipalib import api, errors
from ipalib.dn import DN
from ipapython.dn import DN
from ipapython.ipa_log_manager import *
DEFAULT_ID_RANGE_SIZE = 200000
@ -34,7 +34,7 @@ class update_default_range(PostUpdate):
def execute(self, **options):
ldap = self.obj.backend
dn = str(DN(api.env.container_ranges, api.env.basedn))
dn = DN(api.env.container_ranges, api.env.basedn)
search_filter = "objectclass=ipaDomainIDRange"
try:
(entries, truncated) = ldap.find_entries(search_filter, [], dn)
@ -44,7 +44,7 @@ class update_default_range(PostUpdate):
root_logger.debug("default_range: ipaDomainIDRange entry found, skip plugin")
return (False, False, [])
dn = str(DN(('cn', 'admins'), api.env.container_group, api.env.basedn))
dn = DN(('cn', 'admins'), api.env.container_group, api.env.basedn)
try:
(dn, admins_entry) = ldap.get_entry(dn, ['gidnumber'])
except errors.NotFound:
@ -65,12 +65,10 @@ class update_default_range(PostUpdate):
]
updates = {}
dn = str(DN(('cn', '%s_id_range' % api.env.realm),
api.env.container_ranges, api.env.basedn))
dn = DN(('cn', '%s_id_range' % api.env.realm),
api.env.container_ranges, api.env.basedn)
# make sure everything is str or otherwise python-ldap would complain
range_entry = map(str, range_entry)
updates[dn] = {'dn' : dn, 'default' : range_entry}
updates[dn] = {'dn': dn, 'default': range_entry}
# Default range entry has a hard-coded range size to 200000 which is
# a default range size in ipa-server-install. This could cause issues
@ -78,7 +76,7 @@ class update_default_range(PostUpdate):
# bigger range (option --idmax).
# We should make our best to check if this is the case and provide
# user with an information how to fix it.
dn = str(DN(api.env.container_dna_posix_ids, api.env.basedn))
dn = DN(api.env.container_dna_posix_ids, api.env.basedn)
search_filter = "objectclass=dnaSharedConfig"
attrs = ['dnaHostname', 'dnaRemainingValues']
try:

View File

@ -21,7 +21,7 @@ from ipaserver.install.plugins import MIDDLE
from ipaserver.install.plugins.baseupdate import PostUpdate
from ipaserver.install.plugins import baseupdate
from ipalib import api, errors, util
from ipalib.dn import DN
from ipapython.dn import DN
from ipalib.plugins.dns import dns_container_exists
from ipapython.ipa_log_manager import *
@ -89,31 +89,29 @@ class update_dns_permissions(PostUpdate):
entries otherwise.
"""
_write_dns_perm_dn = DN('cn=Write DNS Configuration',
api.env.container_permission,
api.env.basedn)
_write_dns_perm_dn = DN(('cn', 'Write DNS Configuration'),
api.env.container_permission, api.env.basedn)
_write_dns_perm_entry = ['objectClass:groupofnames',
'objectClass:top',
'cn:Write DNS Configuration',
'description:Write DNS Configuration',
'member:cn=DNS Administrators,cn=privileges,cn=pbac,%s' \
% api.env.basedn,
'member:cn=DNS Servers,cn=privileges,cn=pbac,%s' \
% api.env.basedn]
'member:%s' % DN(('cn', 'DNS Administrators'), ('cn', 'privileges'), ('cn', 'pbac'),
api.env.basedn),
'member:%s' % DN(('cn', 'DNS Servers'), ('cn', 'privileges'), ('cn', 'pbac'),
api.env.basedn)]
_read_dns_perm_dn = DN('cn=Read DNS Entries',
api.env.container_permission,
api.env.basedn)
_read_dns_perm_dn = DN(('cn', 'Read DNS Entries'),
api.env.container_permission, api.env.basedn)
_read_dns_perm_entry = ['objectClass:top',
'objectClass:groupofnames',
'objectClass:ipapermission',
'cn:Read DNS Entries',
'description:Read DNS entries',
'ipapermissiontype:SYSTEM',
'member:cn=DNS Administrators,cn=privileges,cn=pbac,%s' \
% api.env.basedn,
'member:cn=DNS Servers,cn=privileges,cn=pbac,%s' \
% api.env.basedn,]
'member:%s' % DN(('cn', 'DNS Administrators'), ('cn', 'privileges'), ('cn', 'pbac'),
api.env.basedn),
'member:%s' % DN(('cn', 'DNS Servers'), ('cn', 'privileges'), ('cn', 'pbac'),
api.env.basedn),]
_write_dns_aci_dn = DN(api.env.basedn)
_write_dns_aci_entry = ['add:aci:\'(targetattr = "idnsforwardpolicy || idnsforwarders || idnsallowsyncptr || idnszonerefresh || idnspersistentsearch")(target = "ldap:///cn=dns,%(realm)s")(version 3.0;acl "permission:Write DNS Configuration";allow (write) groupdn = "ldap:///cn=Write DNS Configuration,cn=permissions,cn=pbac,%(realm)s";)\'' % dict(realm=api.env.basedn)]
@ -135,10 +133,7 @@ class update_dns_permissions(PostUpdate):
(self._write_dns_aci_dn, 'updates', self._write_dns_aci_entry),
(self._read_dns_aci_dn, 'updates', self._read_dns_aci_entry)):
dn = str(dn)
# make sure everything is str or otherwise python-ldap would complain
entry = map(str, entry)
dnsupdates[dn] = {'dn' : dn, container : entry}
dnsupdates[dn] = {'dn': dn, container: entry}
return (False, True, [dnsupdates])
@ -161,9 +156,9 @@ class update_dns_limits(PostUpdate):
return (False, False, [])
dns_principal = 'DNS/%s@%s' % (self.env.host, self.env.realm)
dns_service_dn = str(DN(('krbprincipalname', dns_principal),
self.env.container_service,
self.env.basedn))
dns_service_dn = DN(('krbprincipalname', dns_principal),
self.env.container_service,
self.env.basedn)
try:
(dn, entry) = ldap.get_entry(dns_service_dn, self.limit_attributes)

View File

@ -44,7 +44,7 @@ class update_replica_exclude_attribute_list(PreUpdate):
entries = repl.find_replication_agreements()
self.log.debug("Found %d agreement(s)", len(entries))
for replica in entries:
self.log.debug(replica.description)
self.log.debug(replica.getValue('description'))
attrlist = replica.getValue('nsDS5ReplicatedAttributeList')
if attrlist is None:
self.log.debug("Adding nsDS5ReplicatedAttributeList and nsDS5ReplicatedAttributeListTotal")
@ -68,7 +68,7 @@ class update_replica_exclude_attribute_list(PreUpdate):
self.log.debug("Attribute list needs updating")
current = replica.toDict()
replica.setValue('nsDS5ReplicatedAttributeList',
replica.nsDS5ReplicatedAttributeList + ' %s' % ' '.join(missing))
replica.getValue('nsDS5ReplicatedAttributeList') + ' %s' % ' '.join(missing))
try:
repl.conn.updateEntry(replica.dn, current, replica.toDict())
self.log.debug("Updated")

View File

@ -24,6 +24,7 @@ from ipalib.frontend import Updater
from ipaserver.install.plugins import baseupdate
from ipalib import api, errors
from ipapython import ipautil
from ipapython.dn import DN, EditableDN
import ldap as _ldap
def entry_to_update(entry):
@ -44,67 +45,99 @@ def entry_to_update(entry):
return update
def generate_update(ldap, deletes=False):
"""
We need to separate the deletes that need to happen from the
new entries that need to be added.
"""
suffix = ipautil.realm_to_suffix(api.env.realm)
searchfilter = '(objectclass=*)'
definitions_managed_entries = []
old_template_container = 'cn=etc,%s' % suffix
old_definition_container = 'cn=managed entries,cn=plugins,cn=config'
new = 'cn=Managed Entries,cn=etc,%s' % suffix
sub = ['cn=Definitions,', 'cn=Templates,']
new_managed_entries = []
old_templates = []
template = None
restart = False
class GenerateUpdateMixin(object):
def generate_update(self, deletes=False):
"""
We need to separate the deletes that need to happen from the
new entries that need to be added.
"""
ldap = self.obj.backend
# If the old entries don't exist the server has already been updated.
try:
(definitions_managed_entries, truncated) = ldap.find_entries(
searchfilter, ['*'], old_definition_container, _ldap.SCOPE_ONELEVEL, normalize=False
)
except errors.NotFound, e:
return (False, new_managed_entries)
suffix = ipautil.realm_to_suffix(api.env.realm)
searchfilter = '(objectclass=*)'
definitions_managed_entries = []
for entry in definitions_managed_entries:
new_definition = {}
definition_managed_entry_updates = {}
if deletes:
old_definition = {'dn': str(entry[0]), 'deleteentry': ['dn: %s' % str(entry[0])]}
old_template = str(entry[1]['managedtemplate'][0])
definition_managed_entry_updates[old_definition['dn']] = old_definition
old_templates.append(old_template)
else:
entry[1]['managedtemplate'] = str(entry[1]['managedtemplate'][0].replace(old_template_container, sub[1] + new))
new_definition['dn'] = str(entry[0].replace(old_definition_container, sub[0] + new))
new_definition['default'] = entry_to_update(entry[1])
definition_managed_entry_updates[new_definition['dn']] = new_definition
new_managed_entries.append(definition_managed_entry_updates)
for old_template in old_templates: # Only happens when deletes is True
old_template_container = DN(('cn', 'etc'), suffix)
new_template_container = DN(('cn', 'Templates'), ('cn', 'Managed Entries'), ('cn', 'etc'), suffix)
old_definition_container = DN(('cn', 'managed entries'), ('cn', 'plugins'), ('cn', 'config'), suffix)
new_definition_container = DN(('cn', 'Definitions'), ('cn', 'Managed Entries'), ('cn', 'etc'), suffix)
definitions_dn = DN(('cn', 'Definitions'))
update_list = []
restart = False
# If the old entries don't exist the server has already been updated.
try:
(dn, template) = ldap.get_entry(old_template, ['*'], normalize=False)
dn = str(dn)
new_template = {}
template_managed_entry_updates = {}
old_template = {'dn': dn, 'deleteentry': ['dn: %s' % dn]}
new_template['dn'] = str(dn.replace(old_template_container, sub[1] + new))
new_template['default'] = entry_to_update(template)
template_managed_entry_updates[new_template['dn']] = new_template
template_managed_entry_updates[old_template['dn']] = old_template
new_managed_entries.append(template_managed_entry_updates)
(definitions_managed_entries, truncated) = ldap.find_entries(
searchfilter, ['*'], old_definition_container, _ldap.SCOPE_ONELEVEL, normalize=False
)
except errors.NotFound, e:
pass
return (False, update_list)
if len(new_managed_entries) > 0:
restart = True
new_managed_entries.sort(reverse=True)
for entry in definitions_managed_entries:
assert isinstance(entry.dn, DN)
if deletes:
old_dn = entry.data['managedtemplate'][0]
assert isinstance(old_dn, DN)
try:
(old_dn, entry) = ldap.get_entry(old_dn, ['*'], normalize=False)
except errors.NotFound, e:
pass
else:
# Compute the new dn by replacing the old container with the new container
new_dn = EditableDN(old_dn)
if new_dn.replace(old_template_container, new_template_container) != 1:
self.error("unable to replace '%s' with '%s' in '%s'",
old_template_container, new_template_container, old_dn)
continue
return (restart, new_managed_entries)
new_dn = DN(new_dn)
class update_managed_post_first(PreUpdate):
# The old attributes become defaults for the new entry
new_update = {'dn': new_dn,
'default': entry_to_update(entry)}
# Delete the old entry
old_update = {'dn': old_dn, 'deleteentry': None}
# Add the delete and replacement updates to the list of all updates
update_list.append({old_dn: old_update, new_dn: new_update})
else:
# Update the template dn by replacing the old containter with the new container
old_dn = entry.data['managedtemplate'][0]
new_dn = EditableDN(old_dn)
if new_dn.replace(old_template_container, new_template_container) != 1:
self.error("unable to replace '%s' with '%s' in '%s'",
old_template_container, new_template_container, old_dn)
continue
new_dn = DN(new_dn)
entry.data['managedtemplate'] = new_dn
# Edit the dn, then convert it back to an immutable DN
old_dn = entry.dn
new_dn = EditableDN(old_dn)
if new_dn.replace(old_definition_container, new_definition_container) != 1:
self.error("unable to replace '%s' with '%s' in '%s'",
old_definition_container, new_definition_container, old_dn)
continue
new_dn = DN(new_dn)
# The old attributes become defaults for the new entry
new_update = {'dn': new_dn,
'default': entry_to_update(entry.data)}
# Add the replacement update to the collection of all updates
update_list.append({new_dn: new_update})
if len(update_list) > 0:
restart = True
update_list.sort(reverse=True)
return (restart, update_list)
class update_managed_post_first(PreUpdate, GenerateUpdateMixin):
"""
Update managed entries
"""
@ -112,21 +145,21 @@ class update_managed_post_first(PreUpdate):
def execute(self, **options):
# Never need to restart with the pre-update changes
(ignore, new_managed_entries) = generate_update(self.obj.backend, False)
(ignore, update_list) = self.generate_update(False)
return (False, True, new_managed_entries)
return (False, True, update_list)
api.register(update_managed_post_first)
class update_managed_post(PostUpdate):
class update_managed_post(PostUpdate, GenerateUpdateMixin):
"""
Update managed entries
"""
order=LAST
def execute(self, **options):
(restart, new_managed_entries) = generate_update(self.obj.backend, True)
(restart, update_list) = self.generate_update(True)
return (restart, True, new_managed_entries)
return (restart, True, update_list)
api.register(update_managed_post)

View File

@ -25,6 +25,7 @@ from ipaserver.install.ldapupdate import LDAPUpdate
from ipapython.ipautil import wait_for_open_socket
from ipalib import api
from ipalib import backend
from ipapython.dn import DN
import ldap as _ldap
class updateclient(backend.Executioner):
@ -44,7 +45,7 @@ class updateclient(backend.Executioner):
updates is a dictionary keyed on dn. The value of an update is a
dictionary with the following possible values:
- dn: str, duplicate of the key
- dn: DN, equal to the dn attribute
- updates: list of updates against the dn
- default: list of the default entry to be added if it doesn't
exist
@ -103,7 +104,7 @@ class updateclient(backend.Executioner):
autobind = False
else:
autobind = True
self.Backend.ldap2.connect(bind_dn='cn=Directory Manager', bind_pw=dm_password, autobind=autobind)
self.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')), bind_pw=dm_password, autobind=autobind)
def order(self, updatetype):
"""Return plugins of the given updatetype in sorted order.
@ -125,22 +126,12 @@ class updateclient(backend.Executioner):
(restart, apply_now, res) = self.run(update.name, **kw)
if restart:
self.restart(dm_password, live_run)
dn_list = {}
for upd in res:
for dn in upd:
dn_explode = _ldap.explode_dn(dn.lower())
l = len(dn_explode)
if dn_list.get(l):
if dn not in dn_list[l]:
dn_list[l].append(dn)
else:
dn_list[l] = [dn]
updates = {}
for entry in res:
updates.update(entry)
if apply_now:
ld.update_from_dict(dn_list, updates)
updates = {}
for entry in res:
updates.update(entry)
ld.update_from_dict(updates)
elif res:
result.extend(res)

View File

@ -28,17 +28,16 @@ from ipapython import services as ipaservices
from ldap import modlist
from ipalib import api, util, errors
from ipapython import ipautil
from ipalib.dn import DN
from ipapython.dn import DN
DIRMAN_CN = "cn=directory manager"
CACERT = "/etc/ipa/ca.crt"
# the default container used by AD for user entries
WIN_USER_CONTAINER = "cn=Users"
WIN_USER_CONTAINER = DN(('cn', 'Users'))
# the default container used by IPA for user entries
IPA_USER_CONTAINER = "cn=users,cn=accounts"
IPA_USER_CONTAINER = DN(('cn', 'users'), ('cn', 'accounts'))
PORT = 636
TIMEOUT = 120
REPL_MAN_DN = "cn=replication manager,cn=config"
REPL_MAN_DN = DN(('cn', 'replication manager'), ('cn', 'config'))
IPA_REPLICA = 1
WINSYNC = 2
@ -94,9 +93,10 @@ def enable_replication_version_checking(hostname, realm, dirman_passwd):
conn.do_simple_bind(bindpw=dirman_passwd)
else:
conn.do_sasl_gssapi_bind()
entry = conn.search_s('cn=IPA Version Replication,cn=plugins,cn=config', ldap.SCOPE_BASE, 'objectclass=*')
if entry[0].getValue('nsslapd-pluginenabled') == 'off':
conn.modify_s(entry[0].dn, [(ldap.MOD_REPLACE, 'nsslapd-pluginenabled', 'on')])
entry = conn.getEntry(DN(('cn', 'IPA Version Replication'), ('cn', 'plugins'), ('cn', 'config')),
ldap.SCOPE_BASE, 'objectclass=*')
if entry.getValue('nsslapd-pluginenabled') == 'off':
conn.modify_s(entry.dn, [(ldap.MOD_REPLACE, 'nsslapd-pluginenabled', 'on')])
conn.unbind()
serverid = "-".join(realm.split("."))
ipaservices.knownservices.dirsrv.restart(instance_name=serverid)
@ -112,8 +112,7 @@ class ReplicationManager(object):
self.dirman_passwd = dirman_passwd
self.realm = realm
self.starttls = starttls
tmp = ipautil.realm_to_suffix(realm)
self.suffix = str(DN(tmp)).lower()
self.suffix = ipautil.realm_to_suffix(realm)
self.need_memberof_fixup = False
# The caller is allowed to pass in an existing IPAdmin connection.
@ -150,25 +149,28 @@ class ReplicationManager(object):
"""
# First see if there is already one set
dn = self.replica_dn()
assert isinstance(dn, DN)
try:
replica = conn.search_s(dn, ldap.SCOPE_BASE, "objectclass=*")[0]
replica = conn.getEntry(dn, ldap.SCOPE_BASE, "objectclass=*")
except errors.NotFound:
pass
else:
if replica.getValue('nsDS5ReplicaId'):
return int(replica.getValue('nsDS5ReplicaId'))
except ldap.NO_SUCH_OBJECT:
pass
# Ok, either the entry doesn't exist or the attribute isn't set
# so get it from the other master
retval = -1
dn = str(DN(('cn','replication'),('cn','etc'), self.suffix))
dn = DN(('cn','replication'),('cn','etc'), self.suffix)
try:
replica = master_conn.search_s(dn, ldap.SCOPE_BASE, "objectclass=*")[0]
if not replica.getValue('nsDS5ReplicaId'):
root_logger.debug("Unable to retrieve nsDS5ReplicaId from remote server")
raise RuntimeError("Unable to retrieve nsDS5ReplicaId from remote server")
except ldap.NO_SUCH_OBJECT:
replica = master_conn.getEntry(dn, ldap.SCOPE_BASE, "objectclass=*")
except errors.NotFound:
root_logger.debug("Unable to retrieve nsDS5ReplicaId from remote server")
raise
else:
if replica.getValue('nsDS5ReplicaId') is None:
root_logger.debug("Unable to retrieve nsDS5ReplicaId from remote server")
raise RuntimeError("Unable to retrieve nsDS5ReplicaId from remote server")
# Now update the value on the master
retval = int(replica.getValue('nsDS5ReplicaId'))
@ -195,8 +197,9 @@ class ReplicationManager(object):
"""
filt = "(|(objectclass=nsDSWindowsReplicationAgreement)(objectclass=nsds5ReplicationAgreement))"
try:
ents = self.conn.search_s("cn=mapping tree,cn=config", ldap.SCOPE_SUBTREE, filt)
except ldap.NO_SUCH_OBJECT:
ents = self.conn.getList(DN(('cn', 'mapping tree'), ('cn', 'config')),
ldap.SCOPE_SUBTREE, filt)
except errors.NotFound:
ents = []
return ents
@ -212,13 +215,13 @@ class ReplicationManager(object):
filt = "(objectclass=nsds5ReplicationAgreement)"
try:
ents = self.conn.search_s("cn=mapping tree,cn=config",
ldap.SCOPE_SUBTREE, filt)
except ldap.NO_SUCH_OBJECT:
ents = self.conn.getList(DN(('cn', 'mapping tree'), ('cn', 'config')),
ldap.SCOPE_SUBTREE, filt)
except errors.NotFound:
return res
for ent in ents:
res.append(ent.nsds5replicahost)
res.append(ent.getValue('nsds5replicahost'))
return res
@ -234,24 +237,23 @@ class ReplicationManager(object):
filt = "(&(|(objectclass=nsds5ReplicationAgreement)(objectclass=nsDSWindowsReplicationAgreement))(nsDS5ReplicaHost=%s))" % hostname
try:
entry = self.conn.search_s("cn=mapping tree,cn=config",
ldap.SCOPE_SUBTREE, filt)
except ldap.NO_SUCH_OBJECT:
entries = self.conn.getList(DN(('cn', 'mapping tree'), ('cn', 'config')),
ldap.SCOPE_SUBTREE, filt)
except errors.NotFound:
return None
if len(entry) == 0:
if len(entries) == 0:
return None
else:
return entry[0] # There can be only one
return entries[0] # There can be only one
def add_replication_manager(self, conn, dn, pw):
"""
Create a pseudo user to use for replication.
"""
edn = ldap.dn.str2dn(dn)
rdn_attr = edn[0][0][0]
rdn_val = edn[0][0][1]
assert isinstance(dn, DN)
rdn_attr = dn[0].attr
rdn_val = dn[0].value
ent = ipaldap.Entry(dn)
ent.setValues("objectclass", "top", "person")
@ -266,6 +268,7 @@ class ReplicationManager(object):
pass
def delete_replication_manager(self, conn, dn=REPL_MAN_DN):
assert isinstance(dn, DN)
try:
conn.delete_s(dn)
except ldap.NO_SUCH_OBJECT:
@ -278,16 +281,18 @@ class ReplicationManager(object):
return "2"
def replica_dn(self):
return str(DN(('cn','replica'),('cn',self.suffix),('cn','mapping tree'),('cn','config')))
return DN(('cn','replica'),('cn',self.suffix),('cn','mapping tree'),('cn','config'))
def replica_config(self, conn, replica_id, replica_binddn):
assert isinstance(replica_binddn, DN)
dn = self.replica_dn()
assert isinstance(dn, DN)
try:
entry = conn.getEntry(dn, ldap.SCOPE_BASE)
managers = entry.getValues('nsDS5ReplicaBindDN')
for m in managers:
if DN(replica_binddn) == DN(m):
if replica_binddn == DN(m):
return
# Add the new replication manager
mod = [(ldap.MOD_ADD, 'nsDS5ReplicaBindDN', replica_binddn)]
@ -303,7 +308,7 @@ class ReplicationManager(object):
entry = ipaldap.Entry(dn)
entry.setValues('objectclass', "top", "nsds5replica", "extensibleobject")
entry.setValues('cn', "replica")
entry.setValues('nsds5replicaroot', self.suffix)
entry.setValues('nsds5replicaroot', str(self.suffix))
entry.setValues('nsds5replicaid', str(replica_id))
entry.setValues('nsds5replicatype', replica_type)
entry.setValues('nsds5flags', "1")
@ -313,7 +318,7 @@ class ReplicationManager(object):
conn.addEntry(entry)
def setup_changelog(self, conn):
dn = "cn=changelog5, cn=config"
dn = DN(('cn', 'changelog5'), ('cn', 'config'))
dirpath = conn.dbdir + "/cldb"
entry = ipaldap.Entry(dn)
entry.setValues('objectclass', "top", "extensibleobject")
@ -325,7 +330,7 @@ class ReplicationManager(object):
return
def setup_chaining_backend(self, conn):
chaindn = "cn=chaining database, cn=plugins, cn=config"
chaindn = DN(('cn', 'chaining database'), ('cn', 'plugins'), ('cn', 'config'))
benamebase = "chaindb"
urls = [self.to_ldap_url(conn)]
cn = ""
@ -334,11 +339,11 @@ class ReplicationManager(object):
while not done:
try:
cn = benamebase + str(benum) # e.g. localdb1
dn = "cn=" + cn + ", " + chaindn
dn = DN(('cn', cn), chaindn)
entry = ipaldap.Entry(dn)
entry.setValues('objectclass', 'top', 'extensibleObject', 'nsBackendInstance')
entry.setValues('cn', cn)
entry.setValues('nsslapd-suffix', self.suffix)
entry.setValues('nsslapd-suffix', str(self.suffix))
entry.setValues('nsfarmserverurl', urls)
entry.setValues('nsmultiplexorbinddn', self.repl_man_dn)
entry.setValues('nsmultiplexorcredentials', self.repl_man_passwd)
@ -365,7 +370,7 @@ class ReplicationManager(object):
def get_mapping_tree_entry(self):
try:
entry = self.conn.getEntry("cn=mapping tree,cn=config", ldap.SCOPE_ONELEVEL,
entry = self.conn.getEntry(DN(('cn', 'mapping tree'), ('cn', 'config')), ldap.SCOPE_ONELEVEL,
"(cn=\"%s\")" % (self.suffix))
except errors.NotFound, e:
root_logger.debug("failed to find mappting tree entry for %s" % self.suffix)
@ -378,7 +383,7 @@ class ReplicationManager(object):
mtent = self.get_mapping_tree_entry()
dn = mtent.dn
plgent = self.conn.getEntry("cn=Multimaster Replication Plugin,cn=plugins,cn=config",
plgent = self.conn.getEntry(DN(('cn', 'Multimaster Replication Plugin'), ('cn', 'plugins'), ('cn', 'config')),
ldap.SCOPE_BASE, "(objectclass=*)", ['nsslapd-pluginPath'])
path = plgent.getValue('nsslapd-pluginPath')
@ -397,7 +402,7 @@ class ReplicationManager(object):
self.enable_chain_on_update(chainbe)
def add_passsync_user(self, conn, password):
pass_dn = "uid=passsync,cn=sysaccounts,cn=etc,%s" % self.suffix
pass_dn = DN(('uid', 'passsync'), ('cn', 'sysaccounts'), ('cn', 'etc'), self.suffix)
print "The user for the Windows PassSync service is %s" % pass_dn
try:
conn.getEntry(pass_dn, ldap.SCOPE_BASE)
@ -414,7 +419,7 @@ class ReplicationManager(object):
conn.addEntry(entry)
# Add it to the list of users allowed to bypass password policy
extop_dn = "cn=ipa_pwd_extop,cn=plugins,cn=config"
extop_dn = DN(('cn', 'ipa_pwd_extop'), ('cn', 'plugins'), ('cn', 'config'))
entry = conn.getEntry(extop_dn, ldap.SCOPE_BASE)
pass_mgrs = entry.getValues('passSyncManagersDNs')
if not pass_mgrs:
@ -435,9 +440,9 @@ class ReplicationManager(object):
def setup_winsync_agmt(self, entry, win_subtree=None):
if win_subtree is None:
win_subtree = WIN_USER_CONTAINER + "," + self.ad_suffix
ds_subtree = IPA_USER_CONTAINER + "," + self.suffix
windomain = '.'.join(ldap.explode_dn(self.suffix, 1))
win_subtree = DN(WIN_USER_CONTAINER, self.ad_suffix)
ds_subtree = DN(IPA_USER_CONTAINER, self.suffix)
windomain = ipautil.suffix_to_realm(self.suffix)
entry.setValues("objectclass", "nsDSWindowsReplicationAgreement")
entry.setValues("nsds7WindowsReplicaSubtree", win_subtree)
@ -454,7 +459,7 @@ class ReplicationManager(object):
tell which side we want.
"""
cn = "meTo%s" % (hostname)
dn = "cn=%s, %s" % (cn, self.replica_dn())
dn = DN(('cn', cn), self.replica_dn())
return (cn, dn)
@ -469,6 +474,9 @@ class ReplicationManager(object):
isn't a dogtag replication agreement.
"""
if repl_man_dn is not None:
assert isinstance(repl_man_dn, DN)
cn, dn = self.agreement_dn(b_hostname, master=master)
try:
a_conn.getEntry(dn, ldap.SCOPE_BASE)
@ -482,7 +490,7 @@ class ReplicationManager(object):
entry.setValues('nsds5replicahost', b_hostname)
entry.setValues('nsds5replicaport', str(port))
entry.setValues('nsds5replicatimeout', str(TIMEOUT))
entry.setValues('nsds5replicaroot', self.suffix)
entry.setValues('nsds5replicaroot', str(self.suffix))
if master is None:
entry.setValues('nsDS5ReplicatedAttributeList',
'(objectclass=*) $ EXCLUDE %s' % " ".join(EXCLUDES))
@ -538,10 +546,15 @@ class ReplicationManager(object):
while (retries > 0 ):
root_logger.info('Getting ldap service principals for conversion: %s and %s' % (filter_a, filter_b))
a_entry = b.search_s(self.suffix, ldap.SCOPE_SUBTREE,
filterstr=filter_a)
b_entry = a.search_s(self.suffix, ldap.SCOPE_SUBTREE,
filterstr=filter_b)
try:
a_entry = b.search_s(self.suffix, ldap.SCOPE_SUBTREE, filterstr=filter_a)
except errors.NotFound:
pass
try:
b_entry = a.search_s(self.suffix, ldap.SCOPE_SUBTREE, filterstr=filter_b)
except errors.NotFound:
pass
if a_entry and b_entry:
root_logger.debug('Found both principals.')
@ -578,7 +591,10 @@ class ReplicationManager(object):
"""
rep_dn = self.replica_dn()
assert isinstance(rep_dn, DN)
(a_dn, b_dn) = self.get_replica_principal_dns(a, b, retries=10)
assert isinstance(a_dn, DN)
assert isinstance(b_dn, DN)
# Add kerberos principal DNs as valid bindDNs for replication
try:
@ -623,12 +639,10 @@ class ReplicationManager(object):
return self.conn.deleteEntry(dn)
def delete_referral(self, hostname):
esc1_suffix = self.suffix.replace('=', '\\3D').replace(',', '\\2C')
esc2_suffix = self.suffix.replace('=', '%3D').replace(',', '%2C')
dn = 'cn=%s,cn=mapping tree,cn=config' % esc1_suffix
dn = DN(('cn', self.suffix), ('cn', 'mapping tree'), ('cn', 'config'))
# TODO: should we detect proto/port somehow ?
mod = [(ldap.MOD_DELETE, 'nsslapd-referral',
'ldap://%s/%s' % (ipautil.format_netloc(hostname, 389), esc2_suffix))]
'ldap://%s/%s' % (ipautil.format_netloc(hostname, 389), self.suffix))]
try:
self.conn.modify_s(dn, mod)
@ -648,9 +662,9 @@ class ReplicationManager(object):
print "Error reading status from agreement", agmtdn
hasError = 1
else:
refresh = entry.nsds5BeginReplicaRefresh
inprogress = entry.nsds5replicaUpdateInProgress
status = entry.nsds5ReplicaLastInitStatus
refresh = entry.getValue('nsds5BeginReplicaRefresh')
inprogress = entry.getValue('nsds5replicaUpdateInProgress')
status = entry.getValue('nsds5ReplicaLastInitStatus')
if not refresh: # done - check status
if not status:
print "No status yet"
@ -683,10 +697,10 @@ class ReplicationManager(object):
print "Error reading status from agreement", agmtdn
hasError = 1
else:
inprogress = entry.nsds5replicaUpdateInProgress
status = entry.nsds5ReplicaLastUpdateStatus
start = entry.nsds5ReplicaLastUpdateStart
end = entry.nsds5ReplicaLastUpdateEnd
inprogress = entry.getValue('nsds5replicaUpdateInProgress')
status = entry.getValue('nsds5ReplicaLastUpdateStatus')
start = entry.getValue('nsds5ReplicaLastUpdateStart')
end = entry.getValue('nsds5ReplicaLastUpdateEnd')
# incremental update is done if inprogress is false and end >= start
done = inprogress and inprogress.lower() == 'false' and start and end and (start <= end)
root_logger.info("Replication Update in progress: %s: status: %s: start: %s: end: %s" %
@ -733,6 +747,7 @@ class ReplicationManager(object):
return self.wait_for_repl_init(conn, dn)
def basic_replication_setup(self, conn, replica_id, repldn, replpw):
assert isinstance(repldn, DN)
if replpw is not None:
self.add_replication_manager(conn, repldn, replpw)
self.replica_config(conn, replica_id, repldn)
@ -741,6 +756,7 @@ class ReplicationManager(object):
def setup_replication(self, r_hostname, r_port=389, r_sslport=636,
r_binddn=None, r_bindpw=None, starttls=False,
is_cs_replica=False):
assert isinstance(r_binddn, DN)
# note - there appears to be a bug in python-ldap - it does not
# allow connections using two different CA certs
if starttls:
@ -836,7 +852,7 @@ class ReplicationManager(object):
root_logger.info("Agreement is ready, starting replication . . .")
# Add winsync replica to the public DIT
dn = str(DN(('cn',ad_dc_name),('cn','replicas'),('cn','ipa'),('cn','etc'), self.suffix))
dn = DN(('cn',ad_dc_name),('cn','replicas'),('cn','ipa'),('cn','etc'), self.suffix)
entry = ipaldap.Entry(dn)
entry.setValues("objectclass", ["nsContainer", "ipaConfigObject"])
entry.setValues("cn", ad_dc_name)
@ -910,17 +926,17 @@ class ReplicationManager(object):
filter = '(&(nsDS5ReplicaHost=%s)' \
'(|(objectclass=nsDSWindowsReplicationAgreement)' \
'(objectclass=nsds5ReplicationAgreement)))' % hostname
entry = conn.search_s("cn=config", ldap.SCOPE_SUBTREE, filter)
if len(entry) == 0:
entries = conn.getList(DN(('cn', 'config')), ldap.SCOPE_SUBTREE, filter)
if len(entries) == 0:
root_logger.error("Unable to find replication agreement for %s" %
(hostname))
raise RuntimeError("Unable to proceed")
if len(entry) > 1:
if len(entries) > 1:
root_logger.error("Found multiple agreements for %s" % hostname)
root_logger.error("Using the first one only (%s)" % entry[0].dn)
root_logger.error("Using the first one only (%s)" % entries[0].dn)
dn = entry[0].dn
schedule = entry[0].nsds5replicaupdateschedule
dn = entries[0].dn
schedule = entries[0].getValue('nsds5replicaupdateschedule')
# On the remote chance of a match. We force a synch to happen right
# now by setting the schedule to something and quickly removing it.
@ -965,16 +981,14 @@ class ReplicationManager(object):
# delete master kerberos key and all its svc principals
try:
filter='(krbprincipalname=*/%s@%s)' % (replica, realm)
entries = self.conn.search_s(self.suffix, ldap.SCOPE_SUBTREE,
filterstr=filter)
entries = self.conn.getList(self.suffix, ldap.SCOPE_SUBTREE,
filterstr=filter)
if len(entries) != 0:
dnset = self.conn.get_dns_sorted_by_length(entries,
reverse=True)
for dns in dnset:
for dn in dns:
self.conn.deleteEntry(dn)
except ldap.NO_SUCH_OBJECT:
pass
except errors.NotFound:
pass
except Exception, e:
@ -984,18 +998,18 @@ class ReplicationManager(object):
err = e
# remove replica memberPrincipal from s4u2proxy configuration
dn1 = DN(u'cn=ipa-http-delegation', api.env.container_s4u2proxy, self.suffix)
dn1 = DN(('cn', 'ipa-http-delegation'), api.env.container_s4u2proxy, self.suffix)
member_principal1 = "HTTP/%(fqdn)s@%(realm)s" % dict(fqdn=replica, realm=realm)
dn2 = DN(u'cn=ipa-ldap-delegation-targets', api.env.container_s4u2proxy, self.suffix)
dn2 = DN(('cn', 'ipa-ldap-delegation-targets'), api.env.container_s4u2proxy, self.suffix)
member_principal2 = "ldap/%(fqdn)s@%(realm)s" % dict(fqdn=replica, realm=realm)
dn3 = DN(u'cn=ipa-cifs-delegation-targets', api.env.container_s4u2proxy, self.suffix)
dn3 = DN(('cn', 'ipa-cifs-delegation-targets'), api.env.container_s4u2proxy, self.suffix)
member_principal3 = "cifs/%(fqdn)s@%(realm)s" % dict(fqdn=replica, realm=realm)
for (dn, member_principal) in ((str(dn1), member_principal1),
(str(dn2), member_principal2),
(str(dn3), member_principal3)):
for (dn, member_principal) in ((dn1, member_principal1),
(dn2, member_principal2),
(dn3, member_principal3)):
try:
mod = [(ldap.MOD_DELETE, 'memberPrincipal', member_principal)]
self.conn.modify_s(dn, mod)
@ -1010,16 +1024,14 @@ class ReplicationManager(object):
# delete master entry with all active services
try:
dn = 'cn=%s,cn=masters,cn=ipa,cn=etc,%s' % (replica, self.suffix)
entries = self.conn.search_s(dn, ldap.SCOPE_SUBTREE)
dn = DN(('cn', replica), ('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), self.suffix)
entries = self.conn.getList(dn, ldap.SCOPE_SUBTREE)
if len(entries) != 0:
dnset = self.conn.get_dns_sorted_by_length(entries,
reverse=True)
for dns in dnset:
for dn in dns:
self.conn.deleteEntry(dn)
except ldap.NO_SUCH_OBJECT:
pass
except errors.NotFound:
pass
except Exception, e:
@ -1029,15 +1041,13 @@ class ReplicationManager(object):
err = e
try:
basedn = 'cn=etc,%s' % self.suffix
basedn = DN(('cn', 'etc'), self.suffix)
filter = '(dnaHostname=%s)' % replica
entries = self.conn.search_s(basedn, ldap.SCOPE_SUBTREE,
filterstr=filter)
entries = self.conn.getList(basedn, ldap.SCOPE_SUBTREE,
filterstr=filter)
if len(entries) != 0:
for e in entries:
self.conn.deleteEntry(e.dn)
except ldap.NO_SUCH_OBJECT:
pass
except errors.NotFound:
pass
except Exception, e:
@ -1047,18 +1057,16 @@ class ReplicationManager(object):
err = e
try:
dn = 'cn=default,ou=profile,%s' % self.suffix
ret = self.conn.search_s(dn, ldap.SCOPE_BASE,
'(objectclass=*)')[0]
srvlist = ret.data.get('defaultServerList')
if len(srvlist) > 0:
srvlist = srvlist[0].split()
dn = DN(('cn', 'default'), ('ou', 'profile'), self.suffix)
ret = self.conn.getEntry(dn, ldap.SCOPE_BASE, '(objectclass=*)')
srvlist = ret.getValue('defaultServerList', '')
srvlist = srvlist[0].split()
if replica in srvlist:
srvlist.remove(replica)
attr = ' '.join(srvlist)
mod = [(ldap.MOD_REPLACE, 'defaultServerList', attr)]
self.conn.modify_s(dn, mod)
except ldap.NO_SUCH_OBJECT:
except errors.NotFound:
pass
except ldap.NO_SUCH_ATTRIBUTE:
pass

View File

@ -25,6 +25,7 @@ from ipapython import sysrestore
from ipapython import ipautil
from ipapython import services as ipaservices
from ipalib import errors
from ipapython.dn import DN
import ldap
from ipaserver import ipaldap
import base64
@ -78,7 +79,7 @@ class Service(object):
self.sstore = sysrestore.StateFile('/var/lib/ipa/sysrestore')
self.realm = None
self.suffix = None
self.suffix = DN()
self.principal = None
self.dercert = None
@ -150,7 +151,7 @@ class Service(object):
# use URI of admin connection
if not self.admin_conn:
self.ldap_connect()
args += ["-H", self.admin_conn._uri]
args += ["-H", self.admin_conn.uri]
auth_parms = []
if self.dm_password:
@ -183,15 +184,15 @@ class Service(object):
cn=kerberos to cn=services
"""
dn = "krbprincipalname=%s,cn=%s,cn=kerberos,%s" % (principal, self.realm, self.suffix)
dn = DN(('krbprincipalname', principal), ('cn', self.realm), ('cn', 'kerberos'), self.suffix)
try:
entry = self.admin_conn.getEntry(dn, ldap.SCOPE_BASE)
except errors.NotFound:
# There is no service in the wrong location, nothing to do.
# This can happen when installing a replica
return
newdn = "krbprincipalname=%s,cn=services,cn=accounts,%s" % (principal, self.suffix)
hostdn = "fqdn=%s,cn=computers,cn=accounts,%s" % (self.fqdn, self.suffix)
return None
newdn = DN(('krbprincipalname', principal), ('cn', 'services'), ('cn', 'accounts'), self.suffix)
hostdn = DN(('fqdn', self.fqdn), ('cn', 'computers'), ('cn', 'accounts'), self.suffix)
self.admin_conn.deleteEntry(dn)
entry.dn = newdn
classes = entry.getValues("objectclass")
@ -211,8 +212,8 @@ class Service(object):
if not self.admin_conn:
self.ldap_connect()
dn = "krbprincipalname=%s,cn=services,cn=accounts,%s" % (principal, self.suffix)
hostdn = "fqdn=%s,cn=computers,cn=accounts,%s" % (self.fqdn, self.suffix)
dn = DN(('krbprincipalname', principal), ('cn', 'services'), ('cn', 'accounts'), self.suffix)
hostdn = DN(('fqdn', self.fqdn), ('cn', 'computers'), ('cn', 'accounts'), self.suffix)
entry = ipaldap.Entry(dn)
entry.setValues("objectclass", ["krbprincipal", "krbprincipalaux", "krbticketpolicyaux", "ipaobject", "ipaservice", "pkiuser"])
entry.setValue("krbprincipalname", principal)
@ -242,7 +243,7 @@ class Service(object):
self.ldap_disconnect()
self.ldap_connect()
dn = "krbprincipalname=%s,cn=services,cn=accounts,%s" % (self.principal, self.suffix)
dn = DN(('krbprincipalname', self.principal), ('cn', 'services'), ('cn', 'accounts'), self.suffix)
mod = [(ldap.MOD_ADD, 'userCertificate', self.dercert)]
try:
self.admin_conn.modify_s(dn, mod)
@ -327,13 +328,12 @@ class Service(object):
self.steps = []
def ldap_enable(self, name, fqdn, dm_password, ldap_suffix):
assert isinstance(ldap_suffix, DN)
self.disable()
if not self.admin_conn:
self.ldap_connect()
entry_name = "cn=%s,cn=%s,%s,%s" % (name, fqdn,
"cn=masters,cn=ipa,cn=etc",
ldap_suffix)
entry_name = DN(('cn', name), ('cn', fqdn), ('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), ldap_suffix)
order = SERVICE_LIST[name][1]
entry = ipaldap.Entry(entry_name)
entry.setValues("objectclass",
@ -362,6 +362,8 @@ class SimpleServiceInstance(Service):
self.step("configuring %s to start on boot" % self.service_name, self.__enable)
self.start_creation("Configuring %s" % self.service_name)
suffix = ipautil.dn_attribute_property('_ldap_suffix')
def __start(self):
self.backup_state("running", self.is_running())
self.restart()

View File

@ -34,9 +34,11 @@ import ldap.sasl
import ldapurl
from ldap.controls import LDAPControl
from ldap.ldapobject import SimpleLDAPObject
from ipapython.ipa_log_manager import *
from ipapython import ipautil
from ipalib import errors
from ipapython.ipautil import format_netloc, wait_for_open_socket, wait_for_open_ports
from ipapython.dn import DN
from ipapython.entity import Entity
from ipaserver.plugins.ldap2 import IPASimpleLDAPObject
@ -92,7 +94,7 @@ class Entry:
a list of values. In python-ldap, entries are returned as a list of
2-tuples. Instance variables:
* dn - string - the string DN of the entry
* dn - DN object - the DN of the entry
* data - CIDict - case insensitive dict of the attributes and values
"""
def __init__(self,entrydata):
@ -103,13 +105,22 @@ class Entry:
if isinstance(entrydata,tuple):
self.dn = entrydata[0]
self.data = ipautil.CIDict(entrydata[1])
elif isinstance(entrydata,str) or isinstance(entrydata,unicode):
elif isinstance(entrydata,DN):
self.dn = entrydata
self.data = ipautil.CIDict()
elif isinstance(entrydata, basestring):
self.dn = DN(entrydata)
self.data = ipautil.CIDict()
else:
raise TypeError("entrydata must be 2-tuple, DN, or basestring, got %s" % type(entrydata))
else:
self.dn = ''
self.dn = DN()
self.data = ipautil.CIDict()
assert isinstance(self.dn, DN)
dn = ipautil.dn_attribute_property('_dn')
def __nonzero__(self):
"""This allows us to do tests like if entry: returns false if there is no data,
true otherwise"""
@ -119,23 +130,16 @@ class Entry:
"""Return True if this entry has an attribute named name, False otherwise"""
return self.data and self.data.has_key(name)
def __getattr__(self,name):
"""If name is the name of an LDAP attribute, return the first value for that
attribute - equivalent to getValue - this allows the use of
entry.cn
instead of
entry.getValue('cn')
This also allows us to return None if an attribute is not found rather than
throwing an exception"""
return self.getValue(name)
def getValues(self,name):
"""Get the list (array) of values for the attribute named name"""
return self.data.get(name)
def getValue(self,name):
def getValue(self,name, default=None):
"""Get the first value for the attribute named name"""
return self.data.get(name,[None])[0]
value = self.data.get(name, default)
if isinstance(value, (list, tuple)):
return value[0]
return value
def setValue(self, name, *value):
"""
@ -179,6 +183,7 @@ class Entry:
def toDict(self):
"""Convert the attrs and values to a dict. The dict is keyed on the
attribute name. The value is either single value or a list of values."""
assert isinstance(self.dn, DN)
result = ipautil.CIDict(self.data)
for i in result.keys():
result[i] = ipautil.utf8_encode_values(result[i])
@ -206,7 +211,7 @@ class Entry:
# (1000)
newdata = {}
newdata.update(self.data)
ldif.LDIFWriter(sio,Entry.base64_attrs,1000).unparse(self.dn,newdata)
ldif.LDIFWriter(sio,Entry.base64_attrs,1000).unparse(str(self.dn),newdata)
return sio.getvalue()
class IPAdmin(IPAEntryLDAPObject):
@ -233,6 +238,7 @@ class IPAdmin(IPAEntryLDAPObject):
that we can call it from places other than instance creation
e.g. when we just need to reconnect
"""
log_mgr.get_logger(self, True)
if debug and debug.lower() == "on":
ldap.set_option(ldap.OPT_DEBUG_LEVEL,255)
if cacert is not None:
@ -251,7 +257,6 @@ class IPAdmin(IPAEntryLDAPObject):
self.ldapi = ldapi
self.realm = realm
self.suffixes = {}
self.schema = None
self.__localinit()
def __lateinit(self):
@ -260,7 +265,7 @@ class IPAdmin(IPAEntryLDAPObject):
values.
"""
try:
ent = self.getEntry('cn=config,cn=ldbm database,cn=plugins,cn=config',
ent = self.getEntry(DN(('cn', 'config'), ('cn', 'ldbm database'), ('cn', 'plugins'), ('cn', 'config')),
ldap.SCOPE_BASE, '(objectclass=*)',
[ 'nsslapd-directory' ])
@ -299,6 +304,9 @@ class IPAdmin(IPAEntryLDAPObject):
if not isinstance(e,ldap.TIMEOUT):
desc = e.args[0]['desc'].strip()
info = e.args[0].get('info','').strip()
arg_desc = kw.get('arg_desc')
if arg_desc is not None:
info += " arguments: %s" % arg_desc
else:
desc = ''
info = ''
@ -334,7 +342,7 @@ class IPAdmin(IPAEntryLDAPObject):
raise errors.DatabaseError(desc=desc,info=info)
def __wait_for_connection(self, timeout):
lurl = ldapurl.LDAPUrl(self._uri)
lurl = ldapurl.LDAPUrl(self.uri)
if lurl.urlscheme == 'ldapi':
wait_for_open_socket(lurl.hostport, timeout)
else:
@ -365,25 +373,25 @@ class IPAdmin(IPAEntryLDAPObject):
try:
if krbccache is not None:
os.environ["KRB5CCNAME"] = krbccache
self.sasl_interactive_bind_s("", SASL_AUTH)
self.sasl_interactive_bind_s(None, SASL_AUTH)
self.principal = principal
self.proxydn = None
except ldap.LDAPError, e:
self.__handle_errors(e)
def do_simple_bind(self, binddn="cn=directory manager", bindpw="", timeout=DEFAULT_TIMEOUT):
self.binddn = binddn
def do_simple_bind(self, binddn=DN(('cn', 'directory manager')), bindpw="", timeout=DEFAULT_TIMEOUT):
self.binddn = binddn # FIXME, self.binddn & self.bindpwd never referenced.
self.bindpwd = bindpw
self.__bind_with_wait(self.simple_bind_s, timeout, binddn, bindpw)
self.__lateinit()
def do_sasl_gssapi_bind(self, timeout=DEFAULT_TIMEOUT):
self.__bind_with_wait(self.sasl_interactive_bind_s, timeout, '', SASL_AUTH)
self.__bind_with_wait(self.sasl_interactive_bind_s, timeout, None, SASL_AUTH)
self.__lateinit()
def do_external_bind(self, user_name=None, timeout=DEFAULT_TIMEOUT):
auth_tokens = ldap.sasl.external(user_name)
self.__bind_with_wait(self.sasl_interactive_bind_s, timeout, '', auth_tokens)
self.__bind_with_wait(self.sasl_interactive_bind_s, timeout, None, auth_tokens)
self.__lateinit()
def getEntry(self, base, scope, filterstr='(objectClass=*)', attrlist=None, attrsonly=0):
@ -491,13 +499,15 @@ class IPAdmin(IPAEntryLDAPObject):
self.set_option(ldap.OPT_SERVER_CONTROLS, sctrl)
self.add_s(entry.dn, entry.toTupleList())
except ldap.LDAPError, e:
arg_desc = 'entry=%s' % (entry.toTupleList())
arg_desc = 'entry=%s: %s' % (entry.dn, entry.toTupleList())
self.__handle_errors(e, arg_desc=arg_desc)
return True
def updateRDN(self, dn, newrdn):
"""Wrap the modrdn function."""
assert isinstance(dn, DN)
assert isinstance(newrdn, DN)
sctrl = self.__get_server_controls()
if dn == newrdn:
@ -516,6 +526,7 @@ class IPAdmin(IPAEntryLDAPObject):
"""This wraps the mod function. It assumes that the entry is already
populated with all of the desired objectclasses and attributes"""
assert isinstance(dn, DN)
sctrl = self.__get_server_controls()
modlist = self.generateModList(oldentry, newentry)
@ -575,7 +586,7 @@ class IPAdmin(IPAEntryLDAPObject):
# You can't remove schema online. An add will automatically
# replace any existing schema.
if old_entry.get('dn') == 'cn=schema':
if old_entry.get('dn', DN()) == DN(('cn', 'schema')):
if len(adds) > 0:
modlist.append((ldap.MOD_ADD, key, adds))
else:
@ -590,11 +601,12 @@ class IPAdmin(IPAEntryLDAPObject):
return modlist
def inactivateEntry(self,dn,has_key):
def inactivateEntry(self,dn, has_key):
"""Rather than deleting entries we mark them as inactive.
has_key defines whether the entry already has nsAccountlock
set so we can determine which type of mod operation to run."""
assert isinstance(dn, DN)
sctrl = self.__get_server_controls()
modlist=[]
@ -616,6 +628,7 @@ class IPAdmin(IPAEntryLDAPObject):
def deleteEntry(self, dn):
"""This wraps the delete function. Use with caution."""
assert isinstance(dn, DN)
sctrl = self.__get_server_controls()
try:
@ -627,7 +640,7 @@ class IPAdmin(IPAEntryLDAPObject):
self.__handle_errors(e, arg_desc=arg_desc)
return True
def modifyPassword(self,dn,oldpass,newpass):
def modifyPassword(self, dn, oldpass, newpass):
"""Set the user password using RFC 3062, LDAP Password Modify Extended
Operation. This ends up calling the IPA password slapi plugin
handler so the Kerberos password gets set properly.
@ -635,6 +648,7 @@ class IPAdmin(IPAEntryLDAPObject):
oldpass is not mandatory
"""
assert isinstance(dn, DN)
sctrl = self.__get_server_controls()
try:
@ -656,6 +670,7 @@ class IPAdmin(IPAEntryLDAPObject):
if isinstance(dn,Entry):
dn = dn.dn
assert isinstance(dn, DN)
# wait for entry and/or attr to show up
if not quiet:
@ -691,6 +706,7 @@ class IPAdmin(IPAEntryLDAPObject):
running, true if done - if true, second is the exit code - if dowait
is True, this function will block until the task is complete
"""
assert isinstance(dn, DN)
attrlist = ['nsTaskLog', 'nsTaskStatus', 'nsTaskExitCode', 'nsTaskCurrentItem', 'nsTaskTotalItems']
done = False
exitCode = 0
@ -701,26 +717,13 @@ class IPAdmin(IPAEntryLDAPObject):
break
if verbose:
print entry
if entry.nsTaskExitCode:
exitCode = int(entry.nsTaskExitCode)
if entry.getValue('nsTaskExitCode'):
exitCode = int(entry.getValue('nsTaskExitCode'))
done = True
if dowait: time.sleep(1)
else: break
return (done, exitCode)
def get_schema(self):
"""
Retrieve cn=schema and convert it into a python-ldap schema
object.
"""
if self.schema:
return self.schema
schema = self.getEntry('cn=schema', ldap.SCOPE_BASE,
'(objectclass=*)', ['attributetypes', 'objectclasses'])
schema = schema.toDict()
self.schema = ldap.schema.SubSchema(schema)
return self.schema
def get_single_value(self, attr):
"""
Check the schema to see if the attribute is single-valued.
@ -730,8 +733,6 @@ class IPAdmin(IPAEntryLDAPObject):
If there is a problem loading the schema or the attribute is
not in the schema return None
"""
if not self.schema:
self.get_schema()
obj = self.schema.get_obj(ldap.schema.AttributeType, attr)
return obj and obj.single_value
@ -744,19 +745,27 @@ class IPAdmin(IPAEntryLDAPObject):
starting from the leafs and go up to delete nodes only when all its
leafs are removed.
Returns a "sorted" dict keyed by dn lengths and corresponding list
of DNs.
{'1': [dn1, dn2, dn3], '2': [dn4, dn5], ..}
Returns a list of list of dn's. Every dn in the dn list has
the same number of RDN's. The outer list is sorted according
to the number of RDN's in each inner list.
Example:
[['cn=bob', cn=tom], ['cn=bob,ou=people', cn=tom,ou=people]]
dn's in list[0] have 1 RDN
dn's in list[1] have 2 RDN's
"""
res = dict()
for e in entries:
sdn = ldap.dn.str2dn(e.dn)
l = len(sdn)
if not l in res:
res[l] = []
res[l].append(e.dn)
dn = e.dn
assert isinstance(dn, DN)
rdn_count = len(dn)
rdn_count_list = res.setdefault(rdn_count, [])
if dn not in rdn_count_list:
rdn_count_list.append(dn)
keys = res.keys()
keys.sort(reverse=reverse)

View File

@ -238,6 +238,8 @@ digits and nothing else follows.
from lxml import etree
import datetime
from ipapython.dn import DN
from ldap.filter import escape_filter_chars
# These are general status return values used when
# CMSServlet.outputError() is invoked.
@ -1239,8 +1241,8 @@ class ra(rabase.rabase):
Check if a specified host is a master for a specified service.
"""
base_dn = 'cn=%s,cn=masters,cn=ipa,cn=etc,%s' % (host, api.env.basedn)
filter = '(&(objectClass=ipaConfigObject)(cn=%s)(ipaConfigString=enabledService))' % service
base_dn = DN(('cn', host), ('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
filter = '(&(objectClass=ipaConfigObject)(cn=%s)(ipaConfigString=enabledService))' % escape_filter_chars(service)
try:
ldap2 = self.api.Backend.ldap2
ent,trunc = ldap2.find_entries(filter=filter, base_dn=base_dn)
@ -1258,14 +1260,16 @@ class ra(rabase.rabase):
Select any host which is a master for a specified service.
"""
base_dn = 'cn=masters,cn=ipa,cn=etc,%s' % api.env.basedn
filter = '(&(objectClass=ipaConfigObject)(cn=%s)(ipaConfigString=enabledService))' % service
base_dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
filter = '(&(objectClass=ipaConfigObject)(cn=%s)(ipaConfigString=enabledService))' % escape_filter_chars(service)
try:
ldap2 = self.api.Backend.ldap2
ent,trunc = ldap2.find_entries(filter=filter, base_dn=base_dn)
if len(ent):
entry = random.choice(ent)
return ldap.explode_dn(dn=entry[0],notypes=True)[1]
dn = entry[0]
assert isinstance(dn, DN)
return dn[1].value
except Exception, e:
pass
return None

File diff suppressed because it is too large Load Diff

View File

@ -39,6 +39,7 @@ from ipalib import Backend
from ipalib import errors
from ipalib import x509
from ipalib import pkcs10
from ipapython.dn import DN, EditableDN, RDN
from ipapython.certdb import get_ca_nickname
import subprocess
import os
@ -86,16 +87,14 @@ class ra(rabase.rabase):
"""
try:
config = api.Command['config_show']()['result']
subject_base = config.get('ipacertificatesubjectbase')[0]
subject_base = EditableDN(config.get('ipacertificatesubjectbase')[0])
hostname = get_csr_hostname(csr)
base = re.split(',\s*(?=\w+=)', subject_base)
base.insert(0,'CN=%s' % hostname)
subject_base = ",".join(base)
subject_base.insert(0, RDN(('CN', hostname)))
request = pkcs10.load_certificate_request(csr)
# python-nss normalizes the request subject
request_subject = str(pkcs10.get_subject(request))
request_subject = DN(pkcs10.get_subject(request))
if str(subject_base).lower() != request_subject.lower():
if subject_base != request_subject:
raise errors.CertificateOperationError(error=_('Request subject "%(request_subject)s" does not match the form "%(subject_base)s"') % \
{'request_subject' : request_subject, 'subject_base' : subject_base})
except errors.CertificateOperationError, e:

View File

@ -32,7 +32,7 @@ from ipalib.errors import PublicError, InternalError, CommandError, JSONError, C
from ipalib.request import context, Connection, destroy_context
from ipalib.rpc import xml_dumps, xml_loads
from ipalib.util import parse_time_duration
from ipalib.dn import DN
from ipapython.dn import DN
from ipaserver.plugins.ldap2 import ldap2
from ipapython.compat import json
from ipalib.session import session_mgr, AuthManager, get_ipa_ccache_name, load_ccache_data, bind_ipa_ccache, release_ipa_ccache, fmt_time, default_max_session_duration
@ -418,29 +418,17 @@ def json_encode_binary(val):
if isinstance(val, dict):
new_dict = {}
for k,v in val.items():
if isinstance(v, str):
new_dict[k] = {'__base64__' : base64.b64encode(v)}
else:
new_dict[k] = json_encode_binary(v)
del val
new_dict[k] = json_encode_binary(v)
return new_dict
elif isinstance(val, (list, tuple)):
new_list = []
n = len(val)
i = 0
while i < n:
v = val[i]
if isinstance(v, str):
new_list.append({'__base64__' : base64.b64encode(v)})
else:
new_list.append(json_encode_binary(v))
i += 1
del val
new_list = [json_encode_binary(v) for v in val]
return new_list
elif isinstance(val, str):
return {'__base64__' : base64.b64encode(val)}
elif isinstance(val, Decimal):
return {'__base64__' : base64.b64encode(str(val))}
elif isinstance(val, DN):
return str(val)
else:
return val
@ -474,7 +462,6 @@ def json_decode_binary(val):
new_dict[k] = base64.b64decode(v['__base64__'])
else:
new_dict[k] = json_decode_binary(v)
del val
return new_dict
elif isinstance(val, list):
new_list = []
@ -488,7 +475,6 @@ def json_decode_binary(val):
else:
new_list.append(json_decode_binary(v))
i += 1
del val
return new_list
else:
if isinstance(val, basestring):
@ -963,9 +949,9 @@ class login_password(Backend, KerberosSession, HTTP_Status):
# Ok, now why is this bad. Is the password simply bad or is the
# password expired?
try:
dn = str(DN(('uid', user),
self.api.env.container_user,
self.api.env.basedn))
dn = DN(('uid', user),
self.api.env.container_user,
self.api.env.basedn)
conn = ldap2(shared_instance=False,
ldap_uri=self.api.env.ldap_uri)
conn.connect(bind_dn=dn, bind_pw=password)
@ -1059,8 +1045,8 @@ class change_password(Backend, HTTP_Status):
result = 'error'
policy_error = None
bind_dn = str(DN((self.api.Object.user.primary_key.name, data['user']),
self.api.env.container_user, self.api.env.basedn))
bind_dn = DN((self.api.Object.user.primary_key.name, data['user']),
self.api.env.container_user, self.api.env.basedn)
try:
conn = ldap2(shared_instance=False,

View File

@ -65,6 +65,10 @@ class IPATypeChecker(TypeChecker):
'ipalib.parameters.Enum': ['values'],
'ipalib.parameters.File': ['stdin_if_missing'],
'urlparse.SplitResult': ['netloc'],
'ipaserver.install.ldapupdate.LDAPUpdate' : ['log', 'debug', 'info', 'warning', 'error', 'critical', 'exception'],
'ipaserver.plugins.ldap2.SchemaCache' : ['log', 'debug', 'info', 'warning', 'error', 'critical', 'exception'],
'ipaserver.plugins.ldap2.IPASimpleLDAPObject' : ['log', 'debug', 'info', 'warning', 'error', 'critical', 'exception'],
'ipaserver.plugins.ldap2.ldap2' : ['log', 'debug', 'info', 'warning', 'error', 'critical', 'exception'],
'ipaserver.rpcserver.KerberosSession' : ['api', 'log', 'debug', 'info', 'warning', 'error', 'critical', 'exception'],
'ipaserver.rpcserver.HTTP_Status' : ['log', 'debug', 'info', 'warning', 'error', 'critical', 'exception'],
'ipalib.krb_utils.KRB5_CCache' : ['log', 'debug', 'info', 'warning', 'error', 'critical', 'exception'],

View File

@ -31,6 +31,7 @@ import nss.nss as nss
from ipalib import api, x509, backend, errors
from ipaserver.plugins import rabase
from ipapython import ipautil
from ipapython.dn import DN
CERTPATH = 'tests/test_xmlrpc/service.crt'
@ -101,9 +102,9 @@ def makecert(reqdir):
subject_base = res['result']['ipacertificatesubjectbase'][0]
cert = None
subject = 'CN=%s,%s' % (api.env.host, subject_base)
subject = DN(('CN', api.env.host), subject_base)
princ = 'unittest/%s@%s' % (api.env.host, api.env.realm)
csr = unicode(generateCSR(reqdir, pwname, subject))
csr = unicode(generateCSR(reqdir, pwname, str(subject)))
try:
res = api.Backend.client.run('cert_request', csr, principal=princ,

View File

@ -31,7 +31,7 @@ import nose
import tempfile
import krbV
from ipaserver.plugins.ldap2 import ldap2
from ipalib.dn import *
from ipapython.dn import DN
def use_keytab(principal, keytab):
try:

View File

@ -1,5 +1,5 @@
dn: uid=tuser, cn=test, cn=accounts, $SUFFIX
deleteentry: reset: nada
deleteentry:
dn: cn=test, cn=accounts, $SUFFIX
deleteentry: reset: nada

View File

@ -20,19 +20,18 @@
Test the `ipaserver/install/ldapupdate.py` module.
"""
import unittest
import os
import sys
import ldap
import nose
from nose.tools import raises
from tests.util import PluginTester
from tests.data import unicode_str
from ipalib import api
from ipalib import errors
from ipaserver.install.ldapupdate import LDAPUpdate, BadSyntax, UPDATES_DIR
from ipaserver.install import installutils
from ipaserver import ipaldap
from ipapython import ipautil
from ipapython.dn import DN
"""
The updater works through files only so this is just a thin-wrapper controlling
@ -46,7 +45,7 @@ have occurred as expected.
The DM password needs to be set in ~/.ipa/.dmpw
"""
class test_update(object):
class test_update(unittest.TestCase):
"""
Test the LDAP updater.
"""
@ -70,13 +69,16 @@ class test_update(object):
else:
raise nose.SkipTest("Unable to find test update files")
self.container_dn = DN(self.updater._template_str('cn=test, cn=accounts, $SUFFIX'))
self.user_dn = DN(self.updater._template_str('uid=tuser, cn=test, cn=accounts, $SUFFIX'))
def tearDown(self):
if self.ld:
self.ld.unbind()
def test_0_reset(self):
"""
Reset the updater test data to a known initial state
Reset the updater test data to a known initial state (test_0_reset)
"""
try:
modified = self.updater.update([self.testdir + "0_reset.update"])
@ -84,96 +86,121 @@ class test_update(object):
# Just means the entry doesn't exist yet
modified = True
assert(modified == True)
self.assertTrue(modified)
with self.assertRaises(errors.NotFound):
entries = self.ld.getList(self.container_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
with self.assertRaises(errors.NotFound):
entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
def test_1_add(self):
"""
Test the updater with an add directive
Test the updater with an add directive (test_1_add)
"""
modified = self.updater.update([self.testdir + "1_add.update"])
assert(modified == True)
self.assertTrue(modified)
entries = self.ld.getList(self.container_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
self.assertEqual(len(entries), 1)
entry = entries[0]
objectclasses = entry.getValues('objectclass')
for item in ('top', 'nsContainer'):
self.assertTrue(item in objectclasses)
self.assertEqual(entry.getValue('cn'), 'test')
entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
self.assertEqual(len(entries), 1)
entry = entries[0]
objectclasses = entry.getValues('objectclass')
for item in ('top', 'person', 'posixaccount', 'krbprincipalaux', 'inetuser'):
self.assertTrue(item in objectclasses)
self.assertEqual(entry.getValue('loginshell'), '/bin/bash')
self.assertEqual(entry.getValue('sn'), 'User')
self.assertEqual(entry.getValue('uid'), 'tuser')
self.assertEqual(entry.getValue('cn'), 'Test User')
def test_2_update(self):
"""
Test the updater when adding an attribute to an existing entry
Test the updater when adding an attribute to an existing entry (test_2_update)
"""
modified = self.updater.update([self.testdir + "2_update.update"])
assert(modified == True)
self.assertTrue(modified)
# The update passed, lets look at the record and see if it is
# really updated
dn = self.updater._template_str('uid=tuser, cn=test, cn=accounts, $SUFFIX')
entry = self.ld.getList(dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
assert (len(entry) == 1)
assert(entry[0].gecos == 'Test User')
entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
self.assertEqual(len(entries), 1)
entry = entries[0]
self.assertEqual(entry.getValue('gecos'), 'Test User')
def test_3_update(self):
"""
Test the updater forcing an attribute to a given value
Test the updater forcing an attribute to a given value (test_3_update)
"""
modified = self.updater.update([self.testdir + "3_update.update"])
assert(modified == True)
self.assertTrue(modified)
# The update passed, lets look at the record and see if it is
# really updated
dn = self.updater._template_str('uid=tuser, cn=test, cn=accounts, $SUFFIX')
entry = self.ld.getList(dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
assert (len(entry) == 1)
assert(entry[0].gecos == 'Test User New')
entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
self.assertEqual(len(entries), 1)
entry = entries[0]
self.assertEqual(entry.getValue('gecos'), 'Test User New')
def test_4_update(self):
"""
Test the updater adding a new value to a single-valued attribute
Test the updater adding a new value to a single-valued attribute (test_4_update)
"""
modified = self.updater.update([self.testdir + "4_update.update"])
assert(modified == True)
self.assertTrue(modified)
entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
self.assertEqual(len(entries), 1)
entry = entries[0]
self.assertEqual(entry.getValue('gecos'), 'Test User New2')
def test_5_update(self):
"""
Test the updater adding a new value to a multi-valued attribute
Test the updater adding a new value to a multi-valued attribute (test_5_update)
"""
modified = self.updater.update([self.testdir + "5_update.update"])
assert(modified == True)
self.assertTrue(modified)
# The update passed, lets look at the record and see if it is
# really updated
dn = self.updater._template_str('uid=tuser, cn=test, cn=accounts, $SUFFIX')
entry = self.ld.getList(dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
assert (len(entry) == 1)
assert(entry[0].getValues('cn') == ['Test User', 'Test User New'])
entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
self.assertEqual(len(entries), 1)
entry = entries[0]
self.assertEqual(sorted(entry.getValues('cn')), sorted(['Test User', 'Test User New']))
def test_6_update(self):
"""
Test the updater removing a value from a multi-valued attribute
Test the updater removing a value from a multi-valued attribute (test_6_update)
"""
modified = self.updater.update([self.testdir + "6_update.update"])
assert(modified == True)
self.assertTrue(modified)
# The update passed, lets look at the record and see if it is
# really updated
dn = self.updater._template_str('uid=tuser, cn=test, cn=accounts, $SUFFIX')
entry = self.ld.getList(dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
assert (len(entry) == 1)
assert(entry[0].cn == 'Test User')
entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
self.assertEqual(len(entries), 1)
entry = entries[0]
self.assertEqual(sorted(entry.getValues('cn')), sorted(['Test User']))
def test_6_update_1(self):
"""
Test the updater removing a non-existent value from a multi-valued attribute
Test the updater removing a non-existent value from a multi-valued attribute (test_6_update_1)
"""
modified = self.updater.update([self.testdir + "6_update.update"])
assert(modified == False)
self.assertFalse(modified)
# The update passed, lets look at the record and see if it is
# really updated
dn = self.updater._template_str('uid=tuser, cn=test, cn=accounts, $SUFFIX')
entry = self.ld.getList(dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
assert (len(entry) == 1)
assert(entry[0].cn == 'Test User')
entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
self.assertEqual(len(entries), 1)
entry = entries[0]
self.assertEqual(sorted(entry.getValues('cn')), sorted(['Test User']))
def test_7_cleanup(self):
"""
Reset the test data to a known initial state
Reset the test data to a known initial state (test_7_cleanup)
"""
try:
modified = self.updater.update([self.testdir + "0_reset.update"])
@ -181,18 +208,113 @@ class test_update(object):
# Just means the entry doesn't exist yet
modified = True
assert(modified == True)
self.assertTrue(modified)
with self.assertRaises(errors.NotFound):
entries = self.ld.getList(self.container_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
with self.assertRaises(errors.NotFound):
entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
@raises(BadSyntax)
def test_8_badsyntax(self):
"""
Test the updater with an unknown keyword
Test the updater with an unknown keyword (test_8_badsyntax)
"""
modified = self.updater.update([self.testdir + "8_badsyntax.update"])
with self.assertRaises(BadSyntax):
modified = self.updater.update([self.testdir + "8_badsyntax.update"])
@raises(BadSyntax)
def test_9_badsyntax(self):
"""
Test the updater with an incomplete line
Test the updater with an incomplete line (test_9_badsyntax)
"""
modified = self.updater.update([self.testdir + "9_badsyntax.update"])
with self.assertRaises(BadSyntax):
modified = self.updater.update([self.testdir + "9_badsyntax.update"])
def test_from_dict(self):
"""
Test updating from a dict.
This replicates what was done in test 1.
"""
# First make sure we're clean
with self.assertRaises(errors.NotFound):
entries = self.ld.getList(self.container_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
with self.assertRaises(errors.NotFound):
entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
update = {
self.container_dn:
{'dn': self.container_dn,
'updates': ['add:objectClass: top',
'add:objectClass: nsContainer',
'add:cn: test'
],
},
self.user_dn:
{'dn': self.user_dn,
'updates': ['add:objectclass: top',
'add:objectclass: person',
'add:objectclass: posixaccount',
'add:objectclass: krbprincipalaux',
'add:objectclass: inetuser',
'add:homedirectory: /home/tuser',
'add:loginshell: /bin/bash',
'add:sn: User',
'add:uid: tuser',
'add:uidnumber: 999',
'add:gidnumber: 999',
'add:cn: Test User',
],
},
}
modified = self.updater.update_from_dict(update)
self.assertTrue(modified)
entries = self.ld.getList(self.container_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
self.assertEqual(len(entries), 1)
entry = entries[0]
objectclasses = entry.getValues('objectclass')
for item in ('top', 'nsContainer'):
self.assertTrue(item in objectclasses)
self.assertEqual(entry.getValue('cn'), 'test')
entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
self.assertEqual(len(entries), 1)
entry = entries[0]
objectclasses = entry.getValues('objectclass')
for item in ('top', 'person', 'posixaccount', 'krbprincipalaux', 'inetuser'):
self.assertTrue(item in objectclasses)
self.assertEqual(entry.getValue('loginshell'), '/bin/bash')
self.assertEqual(entry.getValue('sn'), 'User')
self.assertEqual(entry.getValue('uid'), 'tuser')
self.assertEqual(entry.getValue('cn'), 'Test User')
# Now delete
update = {
self.container_dn:
{'dn': self.container_dn,
'deleteentry': None,
},
self.user_dn:
{'dn': self.user_dn,
'deleteentry': 'deleteentry: reset: nada',
},
}
modified = self.updater.update_from_dict(update)
self.assertTrue(modified)
with self.assertRaises(errors.NotFound):
entries = self.ld.getList(self.container_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])
with self.assertRaises(errors.NotFound):
entries = self.ld.getList(self.user_dn, ldap.SCOPE_BASE, 'objectclass=*', ['*'])

File diff suppressed because it is too large Load Diff

View File

@ -1,149 +0,0 @@
# encoding: utf-8
# Authors:
# Pavel Zuna <pzuna@redhat.com>
#
# Copyright (C) 2009 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Test the `ipalib.encoder` module.
"""
import string
from tests.util import ClassChecker, assert_equal
from ipalib.encoder import Encoder, EncoderSettings, encode_args, decode_retval
_encoder_settings = EncoderSettings()
_test_str_d = u'ěščřžýáíé'
_test_str_e = u'ěščřžýáíé'.encode(_encoder_settings.encode_to)
class test_Encoder(ClassChecker):
"""
Test the `ipalib.encoder.Encoder` class.
"""
_cls = Encoder
def test_encode(self):
"""
Test the `ipalib.encoder.Encoder.encode` method.
"""
o = self.cls()
encode_to = o.encoder_settings.encode_to
o.encoder_settings.encode_postprocessor = lambda x: x
# strings
assert_equal(o.encode('ahoj'), 'ahoj'.encode(encode_to))
assert_equal(o.encode(_test_str_d), _test_str_e)
# bool, float, int, long
assert_equal(o.encode(True), 'TRUE'.encode(encode_to))
assert_equal(o.encode(1.01), str(1.01).encode(encode_to))
assert_equal(o.encode(1000), str(1000).encode(encode_to))
assert_equal(o.encode(long(1)), str(long(1)).encode(encode_to))
# lists
expected = [_test_str_e, '1']
assert_equal(o.encode([_test_str_d, 1]), expected)
expected = ['1', ['1', '2', '3']]
assert_equal(o.encode([1, [1, 2, 3]]), expected)
# tuples
expected = (_test_str_e, '1')
assert_equal(o.encode((_test_str_d, 1)), expected)
expected = ('1', ('1', '2', '3'))
assert_equal(o.encode((1, (1, 2, 3))), expected)
# dicts: only values, no postprocessing
o.encoder_settings.encode_dict_keys = False
o.encoder_settings.encode_dict_keys_postprocess = False
o.encoder_settings.encode_dict_vals = True
o.encoder_settings.encode_dict_vals_postprocess = False
expected = {_test_str_d: _test_str_e}
assert_equal(o.encode({_test_str_d: _test_str_d}), expected)
# dicts: only keys, no postprocessing
o.encoder_settings.encode_dict_keys = True
o.encoder_settings.encode_dict_vals = False
expected = {_test_str_e: _test_str_d}
assert_equal(o.encode({_test_str_d: _test_str_d}), expected)
# dicts: both keys and values, no postprocessing
o.encoder_settings.encode_dict_vals = True
expected = {_test_str_e: _test_str_e}
assert_equal(o.encode({_test_str_d: _test_str_d}), expected)
# dicts: both keys and values, postprocessing on keys only
o.encoder_settings.encode_dict_keys = True
o.encoder_settings.encode_dict_keys_postprocess = True
o.encoder_settings.encode_postprocessor = string.upper
expected = {_test_str_e.upper(): _test_str_e}
assert_equal(o.encode({u'ěščřžýáíé': u'ěščřžýáíé'}), expected)
# None
o.encoder_settings.encode_postprocessor = lambda x: x
o.encoder_settings.encode_none = False
assert_equal(o.encode(None), None)
o.encoder_settings.encode_none = True
assert_equal(o.encode(None), str(None).encode(encode_to))
def test_decode(self):
"""
Test the `ipalib.encoder.Encoder.decode` method.
"""
o = self.cls()
decode_from = o.encoder_settings.decode_from
o.encoder_settings.decode_postprocessor = lambda x: x
# strings
assert_equal(o.decode('ahoj'), 'ahoj'.decode(decode_from))
assert_equal(o.decode(_test_str_e), _test_str_d)
# bool, float, int, long
assert_equal(o.decode('True'), str(True).decode(decode_from))
assert_equal(o.decode('1.01'), str(1.01).decode(decode_from))
assert_equal(o.decode('1000'), str(1000).decode(decode_from))
assert_equal(o.decode('1'), str(long(1)).decode(decode_from))
# lists
expected = [_test_str_d, '1']
assert_equal(o.decode([_test_str_e, '1']), expected)
expected = [u'1', [u'1', u'2', u'3']]
assert_equal(o.decode(['1', ['1', '2', '3']]), expected)
# tuples
expected = (_test_str_d, 1)
assert_equal(o.decode((_test_str_e, 1)), expected)
expected = (u'1', (u'1', u'2', u'3'))
assert_equal(o.decode(('1', ('1', '2', '3'))), expected)
# dicts: only values, no postprocessing
o.encoder_settings.decode_dict_keys = False
o.encoder_settings.decode_dict_keys_postprocess = False
o.encoder_settings.decode_dict_vals = True
o.encoder_settings.decode_dict_vals_postprocess = False
expected = {_test_str_e: _test_str_d}
assert_equal(o.decode({_test_str_e: _test_str_e}), expected)
# dicts: only keys, no postprocessing
o.encoder_settings.decode_dict_keys = True
o.encoder_settings.decode_dict_vals = False
expected = {_test_str_d: _test_str_e}
assert_equal(o.decode({_test_str_e: _test_str_e}), expected)
# dicts: both keys and values, no postprocessing
o.encoder_settings.decode_dict_vals = True
expected = {_test_str_d: _test_str_d}
assert_equal(o.decode({_test_str_e: _test_str_e}), expected)
# dicts: both keys and values, postprocessing on keys only
o.encoder_settings.decode_dict_keys = True
o.encoder_settings.decode_dict_keys_postprocess = True
o.encoder_settings.decode_postprocessor = string.upper
expected = {_test_str_d.upper(): _test_str_d}
assert_equal(o.decode({_test_str_e: _test_str_e}), expected)
# TODO: dict decoding using a table
# None
o.encoder_settings.decode_postprocessor = lambda x: x
o.encoder_settings.decode_none = False
assert_equal(o.decode(None), None)
o.encoder_settings.decode_none = True
assert_equal(o.decode(None), str(None).decode(decode_from))

View File

@ -32,7 +32,7 @@ from ipalib.constants import NAME_REGEX, NAME_ERROR
import base64
from ipalib import x509
from nss.error import NSPRError
from ipalib.dn import *
from ipapython.dn import DN
# certutil -

File diff suppressed because it is too large Load Diff

View File

@ -23,7 +23,7 @@ from httptest import Unauthorized_HTTP_test
from tests.test_xmlrpc.xmlrpc_test import XMLRPC_test
from tests.util import assert_equal, assert_not_equal
from ipalib import api, errors
from ipalib.dn import DN
from ipapython.dn import DN
import ldap
testuser = u'tuser'
@ -57,9 +57,7 @@ class test_changepw(XMLRPC_test, Unauthorized_HTTP_test):
)
def _checkpw(self, user, password):
dn = str(DN(('uid', user),
api.env.container_user,
api.env.basedn))
dn = str(DN(('uid', user), api.env.container_user, api.env.basedn))
conn = ldap.initialize(api.env.ldap_uri)
try:
conn.simple_bind_s(dn, password)

View File

@ -33,7 +33,7 @@ from ipalib.plugins.host import host
import nss.nss as nss
from ipalib import api, x509, create_api, errors
from ipapython import ipautil
from ipalib.dn import *
from ipapython.dn import DN
class test_ldap(object):
"""
@ -45,8 +45,8 @@ class test_ldap(object):
self.ldapuri = 'ldap://%s' % ipautil.format_netloc(api.env.host)
self.ccache = '/tmp/krb5cc_%d' % os.getuid()
nss.nss_init_nodb()
self.dn = str(DN(('krbprincipalname','ldap/%s@%s' % (api.env.host, api.env.realm)),
('cn','services'),('cn','accounts'),api.env.basedn))
self.dn = DN(('krbprincipalname','ldap/%s@%s' % (api.env.host, api.env.realm)),
('cn','services'),('cn','accounts'),api.env.basedn)
def tearDown(self):
if self.conn and self.conn.isconnected():
@ -90,7 +90,7 @@ class test_ldap(object):
else:
raise nose.SkipTest("No directory manager password in %s" % pwfile)
self.conn = ldap2(shared_instance=False, ldap_uri=self.ldapuri)
self.conn.connect(bind_dn='cn=directory manager', bind_pw=dm_password)
self.conn.connect(bind_dn=DN(('cn', 'directory manager')), bind_pw=dm_password)
(dn, entry_attrs) = self.conn.get_entry(self.dn, ['usercertificate'])
cert = entry_attrs.get('usercertificate')
cert = cert[0]
@ -120,7 +120,7 @@ class test_ldap(object):
fp.close()
else:
raise nose.SkipTest("No directory manager password in %s" % pwfile)
myapi.Backend.ldap2.connect(bind_dn="cn=Directory Manager", bind_pw=dm_password)
myapi.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')), bind_pw=dm_password)
result = myapi.Command['service_show']('ldap/%s@%s' % (api.env.host, api.env.realm,))
entry_attrs = result['result']
@ -145,4 +145,3 @@ class test_ldap(object):
cert = cert[0]
serial = unicode(x509.get_serial_number(cert, x509.DER))
assert serial is not None

View File

@ -21,29 +21,17 @@
Test --setattr and --addattr and other attribute-specific issues
"""
from ipalib import api, errors, x509
from ipalib import api, errors
from tests.test_xmlrpc import objectclasses
from xmlrpc_test import (Declarative, fuzzy_digits, fuzzy_uuid, fuzzy_date,
fuzzy_hex, fuzzy_hash, fuzzy_issuer)
from ipalib.dn import *
import base64
from xmlrpc_test import Declarative, fuzzy_digits, fuzzy_uuid
from ipapython.dn import DN
user1 = u'tuser1'
fqdn1 = u'testhost1.%s' % api.env.domain
# We can use the same cert we generated for the service tests
fd = open('tests/test_xmlrpc/service.crt', 'r')
servercert = fd.readlines()
servercert = u''.join(servercert)
servercert = x509.strip_header(servercert)
servercert = servercert.replace('\n', '')
fd.close()
user1=u'tuser1'
class test_attr(Declarative):
cleanup_commands = [
('user_del', [user1], {}),
('host_del', [fqdn1], {}),
]
tests = [
@ -72,16 +60,13 @@ class test_attr(Declarative):
cn=[u'Test User1'],
initials=[u'TU'],
ipauniqueid=[fuzzy_uuid],
krbpwdpolicyreference=lambda x: [DN(i) for i in x] == \
[DN(('cn','global_policy'),('cn',api.env.realm),
('cn','kerberos'),api.env.basedn)],
mepmanagedentry=lambda x: [DN(i) for i in x] == \
[DN(('cn',user1),('cn','groups'),('cn','accounts'),
api.env.basedn)],
krbpwdpolicyreference=[DN(('cn','global_policy'),('cn',api.env.realm),
('cn','kerberos'),api.env.basedn)],
mepmanagedentry=[DN(('cn',user1),('cn','groups'),('cn','accounts'),
api.env.basedn)],
memberof_group=[u'ipausers'],
dn=lambda x: DN(x) == \
DN(('uid','tuser1'),('cn','users'),('cn','accounts'),
api.env.basedn),
dn=DN(('uid','tuser1'),('cn','users'),('cn','accounts'),
api.env.basedn),
has_keytab=False,
has_password=False,
),
@ -563,71 +548,4 @@ class test_attr(Declarative):
desc='Server is unwilling to perform', info=''),
),
dict(
desc='Try to create %r with description and --addattr description' % fqdn1,
command=('host_add', [fqdn1],
dict(
description=u'Test host 1',
addattr=u'description=Test host 2',
force=True,
),
),
expected=errors.OnlyOneValueAllowed(attr='description'),
),
dict(
desc='Create %r with a certificate' % fqdn1,
command=('host_add', [fqdn1],
dict(
usercertificate=servercert,
force=True,
),
),
expected=dict(
value=fqdn1,
summary=u'Added host "%s"' % fqdn1,
result=dict(
dn=lambda x: DN(x) == DN(('fqdn',fqdn1),('cn','computers'),
('cn','accounts'),api.env.basedn),
fqdn=[fqdn1],
krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
objectclass=objectclasses.host,
ipauniqueid=[fuzzy_uuid],
managedby_host=[fqdn1],
usercertificate=[base64.b64decode(servercert)],
valid_not_before=fuzzy_date,
valid_not_after=fuzzy_date,
subject=lambda x: DN(x) == \
DN(('CN',api.env.host),x509.subject_base()),
serial_number=fuzzy_digits,
serial_number_hex=fuzzy_hex,
md5_fingerprint=fuzzy_hash,
sha1_fingerprint=fuzzy_hash,
issuer=fuzzy_issuer,
has_keytab=False,
has_password=False,
),
),
),
dict(
desc='Remove %r certificate using --delattr' % fqdn1,
command=('host_mod', [fqdn1],
dict(
delattr=u'usercertificate=%s' % servercert,
),
),
expected=dict(
value=fqdn1,
summary=u'Modified host "%s"' % fqdn1,
result=dict(
fqdn=[fqdn1],
krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
managedby_host=[fqdn1],
has_keytab=False,
has_password=False,
),
),
),
]

View File

@ -22,6 +22,7 @@ Test the `ipalib/plugins/automember.py` module.
"""
from ipalib import api, errors
from ipapython.dn import DN
from tests.test_xmlrpc import objectclasses
from xmlrpc_test import Declarative, fuzzy_digits, fuzzy_uuid
@ -132,7 +133,7 @@ class test_automember(Declarative):
gidnumber=[fuzzy_digits],
objectclass=objectclasses.group + [u'posixgroup'],
ipauniqueid=[fuzzy_uuid],
dn=u'cn=%s,cn=groups,cn=accounts,%s' % (group1, api.env.basedn),
dn=DN(('cn', group1), ('cn', 'groups'), ('cn', 'accounts'), api.env.basedn),
),
),
),
@ -151,8 +152,8 @@ class test_automember(Declarative):
description=[u'Test desc'],
objectclass=objectclasses.hostgroup,
ipauniqueid=[fuzzy_uuid],
mepmanagedentry=['cn=%s,cn=ng,cn=alt,%s' % (hostgroup1, api.env.basedn)],
dn=u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup1, api.env.basedn),
mepmanagedentry=[DN(('cn', hostgroup1), ('cn', 'ng'), ('cn', 'alt'), api.env.basedn)],
dn=DN(('cn', hostgroup1), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn),
),
),
),
@ -171,8 +172,8 @@ class test_automember(Declarative):
description=[u'Test desc'],
objectclass=objectclasses.hostgroup,
ipauniqueid=[fuzzy_uuid],
mepmanagedentry=['cn=%s,cn=ng,cn=alt,%s' % (hostgroup2, api.env.basedn)],
dn=u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup2, api.env.basedn),
mepmanagedentry=[DN(('cn', hostgroup2), ('cn', 'ng'), ('cn', 'alt'), api.env.basedn)],
dn=DN(('cn', hostgroup2), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn),
),
),
),
@ -191,8 +192,8 @@ class test_automember(Declarative):
description=[u'Test desc'],
objectclass=objectclasses.hostgroup,
ipauniqueid=[fuzzy_uuid],
mepmanagedentry=['cn=%s,cn=ng,cn=alt,%s' % (hostgroup3, api.env.basedn)],
dn=u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup3, api.env.basedn),
mepmanagedentry=[DN(('cn', hostgroup3), ('cn', 'ng'), ('cn', 'alt'), api.env.basedn)],
dn=DN(('cn', hostgroup3), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn),
),
),
),
@ -211,8 +212,8 @@ class test_automember(Declarative):
description=[u'Test desc'],
objectclass=objectclasses.hostgroup,
ipauniqueid=[fuzzy_uuid],
mepmanagedentry=['cn=%s,cn=ng,cn=alt,%s' % (hostgroup4, api.env.basedn)],
dn=u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup4, api.env.basedn),
mepmanagedentry=[DN(('cn', hostgroup4), ('cn', 'ng'), ('cn', 'alt'), api.env.basedn)],
dn=DN(('cn', hostgroup4), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn),
),
),
),
@ -232,7 +233,7 @@ class test_automember(Declarative):
gidnumber=[fuzzy_digits],
objectclass=objectclasses.group + [u'posixgroup'],
ipauniqueid=[fuzzy_uuid],
dn=u'cn=%s,cn=groups,cn=accounts,%s' % (defaultgroup1, api.env.basedn),
dn=DN(('cn', defaultgroup1), ('cn', 'groups'), ('cn', 'accounts'), api.env.basedn),
),
),
),
@ -251,8 +252,8 @@ class test_automember(Declarative):
description=[u'Default test desc'],
objectclass=objectclasses.hostgroup,
ipauniqueid=[fuzzy_uuid],
mepmanagedentry=['cn=%s,cn=ng,cn=alt,%s' % (defaulthostgroup1, api.env.basedn)],
dn=u'cn=%s,cn=hostgroups,cn=accounts,%s' % (defaulthostgroup1, api.env.basedn),
mepmanagedentry=[DN(('cn', defaulthostgroup1), ('cn', 'ng'), ('cn', 'alt'), api.env.basedn)],
dn=DN(('cn', defaulthostgroup1), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn),
),
),
),
@ -269,9 +270,9 @@ class test_automember(Declarative):
result=dict(
cn=[group1],
description=[u'Test desc'],
automembertargetgroup=[u'cn=%s,cn=groups,cn=accounts,%s' % (group1, api.env.basedn)],
automembertargetgroup=[DN(('cn', group1), ('cn', 'groups'), ('cn', 'accounts'), api.env.basedn)],
objectclass=objectclasses.automember,
dn=u'cn=%s,cn=group,cn=automember,cn=etc,%s' % (group1, api.env.basedn),
dn=DN(('cn', group1), ('cn', 'group'), ('cn', 'automember'), ('cn', 'etc'), api.env.basedn),
),
),
),
@ -299,7 +300,7 @@ class test_automember(Declarative):
cn=[group1],
description=[u'Test desc'],
automemberinclusiveregex=[u'manager=%s' % group_include_regex],
automembertargetgroup=[u'cn=%s,cn=groups,cn=accounts,%s' % (group1, api.env.basedn)],
automembertargetgroup=[DN(('cn', group1), ('cn', 'groups'), ('cn', 'accounts'), api.env.basedn)],
),
),
),
@ -318,9 +319,9 @@ class test_automember(Declarative):
result=dict(
cn=[hostgroup1],
description=[u'Test desc'],
automembertargetgroup=[u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup1, api.env.basedn)],
automembertargetgroup=[DN(('cn', hostgroup1), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn)],
objectclass=objectclasses.automember,
dn=u'cn=%s,cn=hostgroup,cn=automember,cn=etc,%s' % (hostgroup1, api.env.basedn),
dn=DN(('cn', hostgroup1), ('cn', 'hostgroup'), ('cn', 'automember'), ('cn', 'etc'), api.env.basedn),
),
),
),
@ -348,7 +349,7 @@ class test_automember(Declarative):
cn=[hostgroup1],
description=[u'Test desc'],
automemberinclusiveregex=[u'fqdn=%s' % hostgroup_include_regex],
automembertargetgroup=[u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup1, api.env.basedn)],
automembertargetgroup=[DN(('cn', hostgroup1), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn)],
),
),
),
@ -401,7 +402,7 @@ class test_automember(Declarative):
result=dict(
cn=[hostgroup1],
description=[u'Test desc'],
automembertargetgroup=[u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup1, api.env.basedn)],
automembertargetgroup=[DN(('cn', hostgroup1), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn)],
automemberinclusiveregex=[u'fqdn=%s' % hostgroup_include_regex,
u'fqdn=%s' % hostgroup_include_regex3,
u'fqdn=%s' % hostgroup_include_regex2,
@ -428,9 +429,9 @@ class test_automember(Declarative):
result=dict(
cn=[hostgroup2],
description=[u'Test desc'],
automembertargetgroup=[u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup2, api.env.basedn)],
automembertargetgroup=[DN(('cn', hostgroup2), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn)],
objectclass=objectclasses.automember,
dn=u'cn=%s,cn=hostgroup,cn=automember,cn=etc,%s' % (hostgroup2, api.env.basedn),
dn=DN(('cn', hostgroup2), ('cn', 'hostgroup'), ('cn', 'automember'), ('cn', 'etc'), api.env.basedn),
),
),
),
@ -458,7 +459,7 @@ class test_automember(Declarative):
cn=[hostgroup2],
description=[u'Test desc'],
automemberinclusiveregex=[u'fqdn=%s' % hostgroup_exclude_regex],
automembertargetgroup=[u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup2, api.env.basedn)],
automembertargetgroup=[DN(('cn', hostgroup2), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn)],
),
),
),
@ -477,9 +478,9 @@ class test_automember(Declarative):
result=dict(
cn=[hostgroup3],
description=[u'Test desc'],
automembertargetgroup=[u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup3, api.env.basedn)],
automembertargetgroup=[DN(('cn', hostgroup3), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn)],
objectclass=objectclasses.automember,
dn=u'cn=%s,cn=hostgroup,cn=automember,cn=etc,%s' % (hostgroup3, api.env.basedn),
dn=DN(('cn', hostgroup3), ('cn', 'hostgroup'), ('cn', 'automember'), ('cn', 'etc'), api.env.basedn),
),
),
),
@ -507,7 +508,7 @@ class test_automember(Declarative):
cn=[hostgroup3],
description=[u'Test desc'],
automemberinclusiveregex=[u'fqdn=%s' % hostgroup_exclude_regex2],
automembertargetgroup=[u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup3, api.env.basedn)],
automembertargetgroup=[DN(('cn', hostgroup3), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn)],
),
),
),
@ -526,9 +527,9 @@ class test_automember(Declarative):
result=dict(
cn=[hostgroup4],
description=[u'Test desc'],
automembertargetgroup=[u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup4, api.env.basedn)],
automembertargetgroup=[DN(('cn', hostgroup4), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn)],
objectclass=objectclasses.automember,
dn=u'cn=%s,cn=hostgroup,cn=automember,cn=etc,%s' % (hostgroup4, api.env.basedn),
dn=DN(('cn', hostgroup4), ('cn', 'hostgroup'), ('cn', 'automember'), ('cn', 'etc'), api.env.basedn),
),
),
),
@ -556,7 +557,7 @@ class test_automember(Declarative):
cn=[hostgroup4],
description=[u'Test desc'],
automemberinclusiveregex=[u'fqdn=%s' % hostgroup_exclude_regex3],
automembertargetgroup=[u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup4, api.env.basedn)],
automembertargetgroup=[DN(('cn', hostgroup4), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn)],
),
),
),
@ -574,8 +575,8 @@ class test_automember(Declarative):
cn=[group1],
description=[u'Test desc'],
automemberinclusiveregex=[u'manager=%s' % group_include_regex],
automembertargetgroup=[u'cn=%s,cn=groups,cn=accounts,%s' % (group1, api.env.basedn)],
dn=u'cn=%s,cn=group,cn=automember,cn=etc,%s' % (group1, api.env.basedn),
automembertargetgroup=[DN(('cn', group1), ('cn', 'groups'), ('cn', 'accounts'), api.env.basedn)],
dn=DN(('cn', group1), ('cn', 'group'), ('cn', 'automember'), ('cn', 'etc'), api.env.basedn),
),
summary=None,
),
@ -596,8 +597,8 @@ class test_automember(Declarative):
cn=[group1],
description=[u'Test desc'],
automemberinclusiveregex=[u'manager=%s' % group_include_regex],
automembertargetgroup=[u'cn=%s,cn=groups,cn=accounts,%s' % (group1, api.env.basedn)],
dn=u'cn=%s,cn=group,cn=automember,cn=etc,%s' % (group1, api.env.basedn),
automembertargetgroup=[DN(('cn', group1), ('cn', 'groups'), ('cn', 'accounts'), api.env.basedn)],
dn=DN(('cn', group1), ('cn', 'group'), ('cn', 'automember'), ('cn', 'etc'), api.env.basedn),
),
],
summary=u'1 rules matched',
@ -618,7 +619,7 @@ class test_automember(Declarative):
cn=[group1],
description=[u'New desc 1'],
automemberinclusiveregex=[u'manager=%s' % group_include_regex],
automembertargetgroup=[u'cn=%s,cn=groups,cn=accounts,%s' % (group1, api.env.basedn)],
automembertargetgroup=[DN(('cn', group1), ('cn', 'groups'), ('cn', 'accounts'), api.env.basedn)],
),
summary=u'Modified automember rule "%s"' % group1,
value=group1,
@ -637,7 +638,7 @@ class test_automember(Declarative):
result=dict(
cn=[hostgroup1],
description=[u'Test desc'],
automembertargetgroup=[u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup1, api.env.basedn)],
automembertargetgroup=[DN(('cn', hostgroup1), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn)],
automemberinclusiveregex=[u'fqdn=%s' % hostgroup_include_regex,
u'fqdn=%s' % hostgroup_include_regex3,
u'fqdn=%s' % hostgroup_include_regex2,
@ -646,7 +647,7 @@ class test_automember(Declarative):
u'fqdn=%s' % hostgroup_exclude_regex3,
u'fqdn=%s' % hostgroup_exclude_regex,
],
dn=u'cn=%s,cn=hostgroup,cn=automember,cn=etc,%s' % (hostgroup1, api.env.basedn),
dn=DN(('cn', hostgroup1), ('cn', 'hostgroup'), ('cn', 'automember'), ('cn', 'etc'), api.env.basedn),
),
summary=None,
),
@ -666,7 +667,7 @@ class test_automember(Declarative):
dict(
cn=[hostgroup1],
description=[u'Test desc'],
automembertargetgroup=[u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup1, api.env.basedn)],
automembertargetgroup=[DN(('cn', hostgroup1), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn)],
automemberinclusiveregex=[u'fqdn=%s' % hostgroup_include_regex,
u'fqdn=%s' % hostgroup_include_regex3,
u'fqdn=%s' % hostgroup_include_regex2,
@ -675,7 +676,7 @@ class test_automember(Declarative):
u'fqdn=%s' % hostgroup_exclude_regex3,
u'fqdn=%s' % hostgroup_exclude_regex,
],
dn=u'cn=%s,cn=hostgroup,cn=automember,cn=etc,%s' % (hostgroup1, api.env.basedn),
dn=DN(('cn', hostgroup1), ('cn', 'hostgroup'), ('cn', 'automember'), ('cn', 'etc'), api.env.basedn),
),
],
summary=u'1 rules matched',
@ -695,7 +696,7 @@ class test_automember(Declarative):
result=dict(
cn=[hostgroup1],
description=[u'New desc 1'],
automembertargetgroup=[u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup1, api.env.basedn)],
automembertargetgroup=[DN(('cn', hostgroup1), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn)],
automemberinclusiveregex=[u'fqdn=%s' % hostgroup_include_regex,
u'fqdn=%s' % hostgroup_include_regex3,
u'fqdn=%s' % hostgroup_include_regex2,
@ -722,7 +723,7 @@ class test_automember(Declarative):
expected=dict(
result=dict(
cn=[u'Group'],
automemberdefaultgroup=[u'cn=%s,cn=groups,cn=accounts,%s' % (defaultgroup1, api.env.basedn)],
automemberdefaultgroup=[DN(('cn', defaultgroup1), ('cn', 'groups'), ('cn', 'accounts'), api.env.basedn)],
),
value=u'group',
summary=u'Set default (fallback) group for automember "group"',
@ -737,9 +738,9 @@ class test_automember(Declarative):
),
expected=dict(
result=dict(
dn=u'cn=group,cn=automember,cn=etc,%s' % (api.env.basedn),
dn=DN(('cn', 'group'), ('cn', 'automember'), ('cn', 'etc'), api.env.basedn),
cn=[u'Group'],
automemberdefaultgroup=[u'cn=%s,cn=groups,cn=accounts,%s' % (defaultgroup1, api.env.basedn)],
automemberdefaultgroup=[DN(('cn', defaultgroup1), ('cn', 'groups'), ('cn', 'accounts'), api.env.basedn)],
),
value=u'group',
summary=None,
@ -758,7 +759,7 @@ class test_automember(Declarative):
expected=dict(
result=dict(
cn=[u'Hostgroup'],
automemberdefaultgroup=[u'cn=%s,cn=hostgroups,cn=accounts,%s' % (defaulthostgroup1, api.env.basedn)],
automemberdefaultgroup=[DN(('cn', defaulthostgroup1), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn)],
),
value=u'hostgroup',
summary=u'Set default (fallback) group for automember "hostgroup"',
@ -775,9 +776,9 @@ class test_automember(Declarative):
),
expected=dict(
result=dict(
dn=u'cn=hostgroup,cn=automember,cn=etc,%s' % (api.env.basedn),
dn=DN(('cn', 'hostgroup'), ('cn', 'automember'), ('cn', 'etc'), api.env.basedn),
cn=[u'Hostgroup'],
automemberdefaultgroup=[u'cn=%s,cn=hostgroups,cn=accounts,%s' % (defaulthostgroup1, api.env.basedn)],
automemberdefaultgroup=[DN(('cn', defaulthostgroup1), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn)],
),
value=u'hostgroup',
summary=None,
@ -810,10 +811,13 @@ class test_automember(Declarative):
cn=[u'Michael Scott'],
initials=[u'MS'],
ipauniqueid=[fuzzy_uuid],
krbpwdpolicyreference=[u'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn)],
mepmanagedentry=[u'cn=%s,cn=groups,cn=accounts,%s' % (manager1, api.env.basedn)],
krbpwdpolicyreference=[DN(('cn', 'global_policy'), ('cn', api.env.realm), ('cn', 'kerberos'),
api.env.basedn)],
mepmanagedentry=[DN(('cn', manager1), ('cn', 'groups'), ('cn', 'accounts'),
api.env.basedn)],
memberof_group=[u'defaultgroup1', u'ipausers'],
dn=u'uid=mscott,cn=users,cn=accounts,' + api.env.basedn,
dn=DN(('uid', 'mscott'), ('cn', 'users'), ('cn', 'accounts'),
api.env.basedn),
),
),
),
@ -840,15 +844,18 @@ class test_automember(Declarative):
uid=[user1],
uidnumber=[fuzzy_digits],
gidnumber=[fuzzy_digits],
manager=[u'uid=mscott,cn=users,cn=accounts,%s' % api.env.basedn],
manager=[DN(('uid', 'mscott'), ('cn', 'users'), ('cn', 'accounts'), api.env.basedn)],
displayname=[u'Test User1'],
cn=[u'Test User1'],
initials=[u'TU'],
ipauniqueid=[fuzzy_uuid],
krbpwdpolicyreference=[u'cn=global_policy,cn=%s,cn=kerberos,%s' % (api.env.realm, api.env.basedn)],
mepmanagedentry=[u'cn=%s,cn=groups,cn=accounts,%s' % (user1, api.env.basedn)],
krbpwdpolicyreference=[DN(('cn', 'global_policy'), ('cn', api.env.realm), ('cn', 'kerberos'),
api.env.basedn)],
mepmanagedentry=[DN(('cn', user1), ('cn', 'groups'), ('cn', 'accounts'),
api.env.basedn)],
memberof_group=[u'group1', u'ipausers'],
dn=u'uid=tuser1,cn=users,cn=accounts,' + api.env.basedn,
dn=DN(('uid', 'tuser1'), ('cn', 'users'), ('cn', 'accounts'),
api.env.basedn),
),
),
),
@ -867,7 +874,7 @@ class test_automember(Declarative):
value=fqdn1,
summary=u'Added host "%s"' % fqdn1,
result=dict(
dn=u'fqdn=%s,cn=computers,cn=accounts,%s' % (fqdn1, api.env.basedn),
dn=DN(('fqdn', fqdn1), ('cn', 'computers'), ('cn', 'accounts'), api.env.basedn),
fqdn=[fqdn1],
description=[u'Test host 1'],
l=[u'Undisclosed location 1'],
@ -895,7 +902,7 @@ class test_automember(Declarative):
value=fqdn2,
summary=u'Added host "%s"' % fqdn2,
result=dict(
dn=u'fqdn=%s,cn=computers,cn=accounts,%s' % (fqdn2, api.env.basedn),
dn=DN(('fqdn', fqdn2), ('cn', 'computers'), ('cn', 'accounts'), api.env.basedn),
fqdn=[fqdn2],
description=[u'Test host 2'],
l=[u'Undisclosed location 1'],
@ -923,7 +930,7 @@ class test_automember(Declarative):
value=fqdn3,
summary=u'Added host "%s"' % fqdn3,
result=dict(
dn=u'fqdn=%s,cn=computers,cn=accounts,%s' % (fqdn3, api.env.basedn),
dn=DN(('fqdn', fqdn3), ('cn', 'computers'), ('cn', 'accounts'), api.env.basedn),
fqdn=[fqdn3],
description=[u'Test host 3'],
l=[u'Undisclosed location 1'],
@ -951,7 +958,7 @@ class test_automember(Declarative):
value=fqdn4,
summary=u'Added host "%s"' % fqdn4,
result=dict(
dn=u'fqdn=%s,cn=computers,cn=accounts,%s' % (fqdn4, api.env.basedn),
dn=DN(('fqdn', fqdn4), ('cn', 'computers'), ('cn', 'accounts'), api.env.basedn),
fqdn=[fqdn4],
description=[u'Test host 4'],
l=[u'Undisclosed location 1'],
@ -979,7 +986,7 @@ class test_automember(Declarative):
value=fqdn5,
summary=u'Added host "%s"' % fqdn5,
result=dict(
dn=u'fqdn=%s,cn=computers,cn=accounts,%s' % (fqdn5, api.env.basedn),
dn=DN(('fqdn', fqdn5), ('cn', 'computers'), ('cn', 'accounts'), api.env.basedn),
fqdn=[fqdn5],
description=[u'Test host 5'],
l=[u'Undisclosed location 1'],
@ -1001,7 +1008,7 @@ class test_automember(Declarative):
value=hostgroup1,
summary=None,
result={
'dn': u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup1, api.env.basedn),
'dn': DN(('cn', hostgroup1), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn),
'member_host': [u'%s' % fqdn1],
'cn': [hostgroup1],
'description': [u'Test desc'],
@ -1017,7 +1024,7 @@ class test_automember(Declarative):
value=defaulthostgroup1,
summary=None,
result={
'dn': u'cn=%s,cn=hostgroups,cn=accounts,%s' % (defaulthostgroup1, api.env.basedn),
'dn': DN(('cn', defaulthostgroup1), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn),
'member_host': [u'%s' % fqdn2],
'cn': [defaulthostgroup1],
'description': [u'Default test desc'],
@ -1033,7 +1040,7 @@ class test_automember(Declarative):
value=hostgroup2,
summary=None,
result={
'dn': u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup2, api.env.basedn),
'dn': DN(('cn', hostgroup2), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn),
'member_host': [u'%s' % fqdn3],
'cn': [hostgroup2],
'description': [u'Test desc'],
@ -1049,7 +1056,7 @@ class test_automember(Declarative):
value=hostgroup3,
summary=None,
result={
'dn': u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup3, api.env.basedn),
'dn': DN(('cn', hostgroup3), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn),
'member_host': [u'%s' % fqdn4],
'cn': [hostgroup3],
'description': [u'Test desc'],
@ -1065,7 +1072,7 @@ class test_automember(Declarative):
value=hostgroup4,
summary=None,
result={
'dn': u'cn=%s,cn=hostgroups,cn=accounts,%s' % (hostgroup4, api.env.basedn),
'dn': DN(('cn', hostgroup4), ('cn', 'hostgroups'), ('cn', 'accounts'), api.env.basedn),
'member_host': [u'%s' % fqdn5],
'cn': [hostgroup4],
'description': [u'Test desc'],

View File

@ -28,7 +28,7 @@ import shutil
from ipalib import api
from ipalib import errors
from ipalib.dn import DN
from ipapython.dn import DN
from nose.tools import raises, assert_raises # pylint: disable=E0611
from xmlrpc_test import XMLRPC_test, assert_attr_equal
@ -238,40 +238,36 @@ class test_automount(AutomountTest):
result=dict(
keys={'auto.direct': ()},
orphanmaps=(dict(
dn=lambda dn: DN(dn) == DN(
('automountmapname', self.mapname),
('cn', self.locname),
('cn', 'automount'), api.env.basedn),
dn=DN(('automountmapname', self.mapname),
('cn', self.locname),
('cn', 'automount'), api.env.basedn),
description=(u'description of map',),
automountmapname=(u'testmap',)),),
orphankeys=[(
dict(
dn=lambda dn: DN(dn) == DN(
('description', self.keyname2),
('automountmapname', 'testmap'),
('cn', self.locname),
('cn', 'automount'), api.env.basedn),
dn=DN(('description', self.keyname2),
('automountmapname', 'testmap'),
('cn', self.locname),
('cn', 'automount'), api.env.basedn),
automountkey=(self.keyname2,),
description=(self.keyname2,),
automountinformation=(u'ro',),
),
dict(
dn=lambda dn: DN(dn) == DN(
('description', self.keyname_rename),
('automountmapname', 'testmap'),
('cn', self.locname),
('cn', 'automount'), api.env.basedn),
dn=DN(('description', self.keyname_rename),
('automountmapname', 'testmap'),
('cn', self.locname),
('cn', 'automount'), api.env.basedn),
automountkey=(self.keyname_rename,),
description=(self.keyname_rename,),
automountinformation=(u'rw',),
))],
maps=(
dict(
dn=lambda dn: DN(dn) == DN(
('description', '/- auto.direct'),
('automountmapname', 'auto.master'),
('cn', self.locname),
('cn', 'automount'), api.env.basedn),
dn=DN(('description', '/- auto.direct'),
('automountmapname', 'auto.master'),
('cn', self.locname),
('cn', 'automount'), api.env.basedn),
automountkey=(u'/-',),
description=(u'/- auto.direct',),
automountinformation=(u'auto.direct',)

Some files were not shown because too many files have changed in this diff Show More