initial release
This commit is contained in:
commit
2c30289acf
|
@ -0,0 +1,5 @@
|
|||
recursive-include src/ldaptools/schemas *.ldif
|
||||
recursive-include tests *.py
|
||||
include tox.ini
|
||||
include VERSION
|
||||
include README.rst
|
|
@ -0,0 +1,57 @@
|
|||
ldaptools
|
||||
=========
|
||||
|
||||
Helper modules to work with LDAP directories and test LDAP tools against OpenLDAP.
|
||||
|
||||
- `ldaptools.ldif_utils`: simple parser for LDIF files
|
||||
- `ldaptools.ldap_source`: generate a stream of LDAP entries from an LDAP URL
|
||||
- `ldaptools.synchronize`: synchronization class to synchronize a source of LDAP records with a target
|
||||
- `ldaptools.paged`: an LDAPObject implementating paged search requests
|
||||
- `ldaptools.ldapsync`: a command line client to the Synchronize class
|
||||
|
||||
ldapsync
|
||||
========
|
||||
|
||||
usage: ldapsync [-h] --object-class-pivot OBJECT_CLASS_PIVOT
|
||||
[--attributes-file ATTRIBUTES_FILE] [--attributes ATTRIBUTES]
|
||||
--source-uri SOURCE_URI --source-base-dn SOURCE_BASE_DN
|
||||
[--source-bind-dn SOURCE_BIND_DN]
|
||||
[--source-bind-password SOURCE_BIND_PASSWORD] --target-uri
|
||||
TARGET_URI --target-base-dn TARGET_BASE_DN
|
||||
[--target-bind-dn TARGET_BIND_DN]
|
||||
[--target-bind-password TARGET_BIND_PASSWORD] [--fake]
|
||||
[--verbose]
|
||||
|
||||
Synchronize an LDIF file or a source LDAP directory to another directory Base
|
||||
DN of the source is remapped to another DN in the target directory
|
||||
|
||||
optional arguments:
|
||||
-h, --help show this help message and exit
|
||||
--object-class-pivot OBJECT_CLASS_PIVOT
|
||||
an objectClass and an attribute name which is the
|
||||
unique identifier for this class
|
||||
--attributes-file ATTRIBUTES_FILE
|
||||
a file containing the list of attributes to
|
||||
synchronize
|
||||
--attributes ATTRIBUTES
|
||||
a list of attribute names separated by spaces
|
||||
--source-uri SOURCE_URI
|
||||
URL of an LDAP directory (ldapi://, ldap:// or
|
||||
ldaps://) or path of and LDIF file
|
||||
--source-base-dn SOURCE_BASE_DN
|
||||
base DN of the source
|
||||
--source-bind-dn SOURCE_BIND_DN
|
||||
bind DN for a source LDAP directory
|
||||
--source-bind-password SOURCE_BIND_PASSWORD
|
||||
bind password for a source LDAP directory
|
||||
--target-uri TARGET_URI
|
||||
URL of the target LDAP directory
|
||||
--target-base-dn TARGET_BASE_DN
|
||||
base DN of the target LDAP directory
|
||||
--target-bind-dn TARGET_BIND_DN
|
||||
bind DN for a target LDAP directory
|
||||
--target-bind-password TARGET_BIND_PASSWORD
|
||||
bind password for a target LDAP directory
|
||||
--fake compute synchronization actions but do not apply
|
||||
--verbose print all actions to stdout
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
python-ldaptools (1.0-1) wheezy; urgency=low
|
||||
|
||||
* Initial package, targetting wheezy.
|
||||
|
||||
-- Benjamin Dauvergne <bdauvergne@entrouvert.com> Mon, 11 Feb 2016 20:59:28 +0200
|
|
@ -0,0 +1 @@
|
|||
ldaptools.egg-info/*
|
|
@ -0,0 +1 @@
|
|||
7
|
|
@ -0,0 +1,14 @@
|
|||
Source: python-ldaptools
|
||||
Section: python
|
||||
Priority: optional
|
||||
Maintainer: Benjamin Dauvergne <bdauvergne@entrouvert.com>
|
||||
Build-Depends: python-setuptools (>= 0.6b3), python-all (>= 2.6), debhelper (>= 7.4.3)
|
||||
Standards-Version: 3.9.1
|
||||
X-Python-Version: >= 2.7
|
||||
Homepage: http://dev.entrouvert.org/projects/ldaptools/
|
||||
|
||||
Package: python-ldaptools
|
||||
Architecture: all
|
||||
Depends: ${python:Depends}
|
||||
XB-Python-Version: ${python:Versions}
|
||||
Description: helper library for python-ldap and openldap
|
|
@ -0,0 +1,25 @@
|
|||
This package was debianized by Benjamin Dauvergne <bdauvergne@entrouvert.com> on
|
||||
Mon, 11 Feb 2016 21:00:09 +0200
|
||||
|
||||
Upstream Author: Benjamin Dauvergne <bdauvergne@entrouvert.com>
|
||||
|
||||
Copyright (c) 2011 Entr'ouvert;
|
||||
|
||||
License is GNU GPL v3.
|
||||
|
||||
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, write to the Free Software Foundation, Inc., 59 Temple
|
||||
Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
On Debian GNU/Linux systems, the complete text of the GNU General Public
|
||||
License can be found in `/usr/share/common-licenses/GPL'.
|
|
@ -0,0 +1,6 @@
|
|||
#!/usr/bin/make -f
|
||||
|
||||
%:
|
||||
dh $@ --with python2
|
||||
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
#! /usr/bin/env python
|
||||
#
|
||||
'''
|
||||
Setup script for Authentic 2
|
||||
'''
|
||||
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
from setuptools import setup, find_packages
|
||||
from setuptools.command.sdist import sdist
|
||||
|
||||
|
||||
class eo_sdist(sdist):
|
||||
def run(self):
|
||||
print "creating VERSION file"
|
||||
if os.path.exists('VERSION'):
|
||||
os.remove('VERSION')
|
||||
version = get_version()
|
||||
version_file = open('VERSION', 'w')
|
||||
version_file.write(version)
|
||||
version_file.close()
|
||||
sdist.run(self)
|
||||
print "removing VERSION file"
|
||||
if os.path.exists('VERSION'):
|
||||
os.remove('VERSION')
|
||||
|
||||
|
||||
def get_version():
|
||||
'''Use the VERSION, if absent generates a version with git describe, if not
|
||||
tag exists, take 0.0.0- and add the length of the commit log.
|
||||
'''
|
||||
if os.path.exists('VERSION'):
|
||||
with open('VERSION', 'r') as v:
|
||||
return v.read()
|
||||
if os.path.exists('.git'):
|
||||
p = subprocess.Popen(['git', 'describe', '--dirty', '--match=v*'], stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
result = p.communicate()[0]
|
||||
if p.returncode == 0:
|
||||
result = result.split()[0][1:]
|
||||
else:
|
||||
result = '0.0.0-%s' % len(subprocess.check_output(
|
||||
['git', 'rev-list', 'HEAD']).splitlines())
|
||||
return result.replace('-', '.').replace('.g', '+g')
|
||||
return '0.0.0'
|
||||
|
||||
|
||||
setup(name="ldaptools",
|
||||
version=get_version(),
|
||||
license="AGPLv3+",
|
||||
description="ldaptools",
|
||||
url="http://dev.entrouvert.org/projects/ldaptools/",
|
||||
author="Entr'ouvert",
|
||||
author_email="authentic@listes.entrouvert.com",
|
||||
maintainer="Benjamin Dauvergne",
|
||||
maintainer_email="bdauvergne@entrouvert.com",
|
||||
packages=find_packages('src'),
|
||||
package_dir={'': 'src'},
|
||||
include_package_data=True,
|
||||
install_requires=['python-ldap'],
|
||||
entry_points={
|
||||
'console_scripts': ['ldapsync=ldaptools.ldapsync.cmd:main'],
|
||||
},
|
||||
zip_safe=False,
|
||||
cmdclass={'sdist': eo_sdist})
|
|
@ -0,0 +1,12 @@
|
|||
|
||||
|
||||
class CommandError(Exception):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.err_code = kwargs.pop('err_code', None)
|
||||
super(CommandError, self).__init__(*args, **kwargs)
|
||||
|
||||
|
||||
class ConfigError(CommandError):
|
||||
def __init__(self, *args, **kwargs):
|
||||
kwargs['err_code'] = 1
|
||||
super(ConfigError, self).__init__(*args, **kwargs)
|
|
@ -0,0 +1,32 @@
|
|||
import ldap
|
||||
|
||||
from ldaptools.utils import idict, istr
|
||||
|
||||
|
||||
class LDAPSource(object):
|
||||
entries = None
|
||||
conn = None
|
||||
base_dn = None
|
||||
filterstr = '(objectclass=*)'
|
||||
attributes = None
|
||||
|
||||
def __init__(self, conn, base_dn=None, filterstr=None, attributes=None):
|
||||
assert conn
|
||||
self.conn = conn or self.conn
|
||||
self.filterstr = filterstr or self.filterstr
|
||||
self.attributes = attributes or self.attributes
|
||||
self.base_dn = base_dn or self.base_dn
|
||||
|
||||
def search(self):
|
||||
for dn, entry in self.conn.paged_search_ext_s(self.base_dn, ldap.SCOPE_SUBTREE,
|
||||
filterstr=self.filterstr,
|
||||
attrlist=self.attributes):
|
||||
if not dn:
|
||||
continue
|
||||
entry = idict(entry)
|
||||
if 'objectclass' in entry:
|
||||
entry['objectclass'] = [istr(v) for v in entry['objectclass']]
|
||||
yield dn, entry
|
||||
|
||||
def __iter__(self):
|
||||
return self.search()
|
|
@ -0,0 +1,142 @@
|
|||
import argparse
|
||||
import sys
|
||||
|
||||
import ldap.sasl
|
||||
|
||||
from ldaptools import ldif_utils, paged, ldap_source
|
||||
from ldaptools.synchronize import Synchronize
|
||||
|
||||
|
||||
def source_uri(value):
|
||||
for prefix in ['ldapi://', 'ldap://', 'ldaps://']:
|
||||
if value.startswith(prefix):
|
||||
return value
|
||||
raise argparse.ArgumentTypeError('%r is not an LDAP url' % value)
|
||||
|
||||
|
||||
def or_type(f1, f2):
|
||||
def f(value):
|
||||
try:
|
||||
return f1(value)
|
||||
except argparse.ArgumentTypeError, e1:
|
||||
try:
|
||||
return f2(value)
|
||||
except argparse.ArgumentTypeError, e2:
|
||||
raise argparse.ArgumentTypeError('%s and %s' % (e1.args[0], e2.args[0]))
|
||||
return f
|
||||
|
||||
|
||||
def object_class_pivot(value):
|
||||
value = filter(None, map(str.strip, map(str.lower, value.split())))
|
||||
if len(value) != 2:
|
||||
raise argparse.ArgumentTypeError('%r is not a pair of an objectClass and an attribute name')
|
||||
return value
|
||||
|
||||
|
||||
def main(args=None):
|
||||
parser = argparse.ArgumentParser(description='''\
|
||||
Synchronize an LDIF file or a source LDAP directory to another directory
|
||||
|
||||
Base DN of the source is remapped to another DN in the target directory''')
|
||||
parser.add_argument('--object-class-pivot',
|
||||
required=True,
|
||||
type=object_class_pivot,
|
||||
action='append',
|
||||
help='an objectClass and an attribute name which is the unique identifier '
|
||||
'for this class')
|
||||
parser.add_argument('--attributes-file',
|
||||
type=argparse.FileType('r'),
|
||||
help='a file containing the list of attributes to synchronize')
|
||||
parser.add_argument('--attributes',
|
||||
help='a list of attribute names separated by spaces')
|
||||
parser.add_argument('--source-uri',
|
||||
required=True,
|
||||
type=or_type(source_uri, argparse.FileType('r')),
|
||||
help='URL of an LDAP directory (ldapi://, ldap:// or ldaps://) or path of '
|
||||
'and LDIF file')
|
||||
parser.add_argument('--source-base-dn',
|
||||
required=True,
|
||||
help='base DN of the source')
|
||||
parser.add_argument('--source-bind-dn',
|
||||
help='bind DN for a source LDAP directory')
|
||||
parser.add_argument('--source-bind-password',
|
||||
help='bind password for a source LDAP directory')
|
||||
|
||||
parser.add_argument('--target-uri',
|
||||
type=source_uri,
|
||||
required=True,
|
||||
help='URL of the target LDAP directory')
|
||||
parser.add_argument('--target-base-dn',
|
||||
required=True,
|
||||
help='base DN of the target LDAP directory')
|
||||
parser.add_argument('--target-bind-dn',
|
||||
help='bind DN for a target LDAP directory')
|
||||
parser.add_argument('--target-bind-password',
|
||||
help='bind password for a target LDAP directory')
|
||||
parser.add_argument('--fake',
|
||||
action='store_true',
|
||||
help='compute synchronization actions but do not apply')
|
||||
parser.add_argument('--verbose',
|
||||
action='store_true',
|
||||
help='print all actions to stdout')
|
||||
|
||||
options = parser.parse_args(args=args)
|
||||
|
||||
attributes = set()
|
||||
|
||||
if options.attributes_file:
|
||||
attributes.update([attribute.strip().lower() for attribute in options.attributes_file])
|
||||
if options.attributes:
|
||||
for attribute in options.attributes.split():
|
||||
attribute = attribute.strip().lower()
|
||||
if attribute:
|
||||
attributes.add(attribute)
|
||||
attributes = list(attributes)
|
||||
if not attributes:
|
||||
parser.print_help()
|
||||
print 'Yout must give at least one attribute to synchronize'
|
||||
|
||||
if options.verbose:
|
||||
print 'Synchronizing ',
|
||||
if hasattr(options.source_uri, 'read'):
|
||||
if options.verbose:
|
||||
print options.source_uri.name,
|
||||
source = ldif_utils.ListLDIFParser(options.source_uri)
|
||||
source.parse()
|
||||
else:
|
||||
if options.verbose:
|
||||
print options.source_uri,
|
||||
conn = paged.PagedLDAPObject(options.source_uri)
|
||||
if options.source_uri.startswith('ldapi://'):
|
||||
conn.sasl_interactive_bind_s("", ldap.sasl.external())
|
||||
elif options.source_bind_dn and options.source_bind_password:
|
||||
conn.simple_bind_s(options.source_bind_dn, options.source_bind_password)
|
||||
|
||||
source = ldap_source.LDAPSource(conn, base_dn=options.source_base_dn, attributes=attributes)
|
||||
|
||||
if options.verbose:
|
||||
print 'to', options.target_uri
|
||||
target_conn = paged.PagedLDAPObject(options.target_uri)
|
||||
if options.target_uri.startswith('ldapi://'):
|
||||
target_conn.sasl_interactive_bind_s("", ldap.sasl.external())
|
||||
elif options.target_bind_dn and options.target_bind_dn:
|
||||
target_conn.simple_bind_s(options.target_bind_dn, options.target_bind_password)
|
||||
synchronize = Synchronize(source, options.source_base_dn,
|
||||
target_conn, options.target_base_dn,
|
||||
pivot_attributes=options.object_class_pivot,
|
||||
attributes=attributes)
|
||||
|
||||
synchronize.build_actions()
|
||||
if options.verbose:
|
||||
for action in synchronize.actions:
|
||||
print action
|
||||
if not synchronize.actions:
|
||||
print 'Nothing to do.'
|
||||
if not options.fake:
|
||||
synchronize.apply_actions()
|
||||
failed_actions = [action for action in synchronize.actions if action.errors]
|
||||
if failed_actions:
|
||||
print >>sys.stderr, 'Some actions failed:'
|
||||
for action in failed_actions:
|
||||
print >>sys.stderr, action, action.erors
|
||||
raise SystemExit(1)
|
|
@ -0,0 +1,21 @@
|
|||
import ldap
|
||||
import ldif
|
||||
|
||||
from ldaptools.utils import idict
|
||||
|
||||
|
||||
class ListLDIFParser(ldif.LDIFParser):
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.entries = []
|
||||
ldif.LDIFParser.__init__(self, *args, **kwargs)
|
||||
|
||||
def handle(self, dn, entry):
|
||||
self.entries.append((dn, entry))
|
||||
|
||||
def add(self, conn):
|
||||
for dn, entry in self.entries:
|
||||
conn.add_s(dn, ldap.modlist.addModlist(entry))
|
||||
|
||||
def __iter__(self):
|
||||
for dn, attributes in self.entries:
|
||||
yield dn, idict(attributes)
|
|
@ -0,0 +1,73 @@
|
|||
import ldap
|
||||
from ldap.ldapobject import ReconnectLDAPObject
|
||||
from ldap.controls import SimplePagedResultsControl
|
||||
|
||||
|
||||
class PagedResultsSearchObject:
|
||||
page_size = 500
|
||||
|
||||
def paged_search_ext_s(self, base, scope, filterstr='(objectClass=*)', attrlist=None,
|
||||
attrsonly=0, serverctrls=None, clientctrls=None, timeout=-1,
|
||||
sizelimit=0):
|
||||
"""
|
||||
Behaves exactly like LDAPObject.search_ext_s() but internally uses the
|
||||
simple paged results control to retrieve search results in chunks.
|
||||
|
||||
This is non-sense for really large results sets which you would like
|
||||
to process one-by-one
|
||||
"""
|
||||
|
||||
while True: # loop for reconnecting if necessary
|
||||
req_ctrl = SimplePagedResultsControl(True, size=self.page_size, cookie='')
|
||||
try:
|
||||
# Send first search request
|
||||
msgid = self.search_ext(
|
||||
base,
|
||||
scope,
|
||||
filterstr=filterstr,
|
||||
attrlist=attrlist,
|
||||
attrsonly=attrsonly,
|
||||
serverctrls=(serverctrls or [])+[req_ctrl],
|
||||
clientctrls=clientctrls,
|
||||
timeout=timeout,
|
||||
sizelimit=sizelimit
|
||||
)
|
||||
|
||||
all_results = []
|
||||
|
||||
while True:
|
||||
rtype, rdata, rmsgid, rctrls = self.result3(msgid)
|
||||
for result in rdata:
|
||||
yield result
|
||||
all_results.extend(rdata)
|
||||
# Extract the simple paged results response control
|
||||
pctrls = [
|
||||
c
|
||||
for c in rctrls
|
||||
if c.controlType == SimplePagedResultsControl.controlType
|
||||
]
|
||||
if pctrls:
|
||||
if pctrls[0].cookie:
|
||||
# Copy cookie from response control to request control
|
||||
req_ctrl.cookie = pctrls[0].cookie
|
||||
msgid = self.search_ext(
|
||||
base,
|
||||
scope,
|
||||
filterstr=filterstr,
|
||||
attrlist=attrlist,
|
||||
attrsonly=attrsonly,
|
||||
serverctrls=(serverctrls or [])+[req_ctrl],
|
||||
clientctrls=clientctrls,
|
||||
timeout=timeout,
|
||||
sizelimit=sizelimit
|
||||
)
|
||||
else:
|
||||
break # no more pages available
|
||||
except ldap.SERVER_DOWN:
|
||||
self.reconnect(self._uri)
|
||||
else:
|
||||
break
|
||||
|
||||
|
||||
class PagedLDAPObject(ReconnectLDAPObject, PagedResultsSearchObject):
|
||||
pass
|
|
@ -0,0 +1,600 @@
|
|||
# OpenLDAP Core schema
|
||||
# $OpenLDAP: pkg/ldap/servers/slapd/schema/core.ldif,v 1.1.2.5 2007/01/02 21:44:09 kurt Exp $
|
||||
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
##
|
||||
## Copyright 1998-2007 The OpenLDAP Foundation.
|
||||
## All rights reserved.
|
||||
##
|
||||
## Redistribution and use in source and binary forms, with or without
|
||||
## modification, are permitted only as authorized by the OpenLDAP
|
||||
## Public License.
|
||||
##
|
||||
## A copy of this license is available in the file LICENSE in the
|
||||
## top-level directory of the distribution or, alternatively, at
|
||||
## <http://www.OpenLDAP.org/license.html>.
|
||||
#
|
||||
|
||||
# The version of this file as distributed by the OpenLDAP Foundation
|
||||
# contains text claiming copyright by the Internet Society and including
|
||||
# the IETF RFC license, which does not meet Debian's Free Software
|
||||
# Guidelines. However, apart from short and obvious comments, the text of
|
||||
# this file is purely a functional interface specification, which is not
|
||||
# subject to that license and is not copyrightable under US law.
|
||||
#
|
||||
# The license statement is retained below so as not to remove credit, but
|
||||
# as best as we can determine, it is not applicable to the contents of
|
||||
# this file.
|
||||
|
||||
## Portions Copyright (C) The Internet Society (1997-2003).
|
||||
## All Rights Reserved.
|
||||
##
|
||||
## This document and translations of it may be copied and furnished to
|
||||
## others, and derivative works that comment on or otherwise explain it
|
||||
## or assist in its implementation may be prepared, copied, published
|
||||
## and distributed, in whole or in part, without restriction of any
|
||||
## kind, provided that the above copyright notice and this paragraph are
|
||||
## included on all such copies and derivative works. However, this
|
||||
## document itself may not be modified in any way, such as by removing
|
||||
## the copyright notice or references to the Internet Society or other
|
||||
## Internet organizations, except as needed for the purpose of
|
||||
## developing Internet standards in which case the procedures for
|
||||
## copyrights defined in the Internet Standards process must be
|
||||
## followed, or as required to translate it into languages other than
|
||||
## English.
|
||||
##
|
||||
## The limited permissions granted above are perpetual and will not be
|
||||
## revoked by the Internet Society or its successors or assigns.
|
||||
##
|
||||
## This document and the information contained herein is provided on an
|
||||
## "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
|
||||
## TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
|
||||
## BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
|
||||
## HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
|
||||
## MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
#
|
||||
#
|
||||
# Includes LDAPv3 schema items from:
|
||||
# RFC 2252/2256 (LDAPv3)
|
||||
#
|
||||
# Select standard track schema items:
|
||||
# RFC 1274 (uid/dc)
|
||||
# RFC 2079 (URI)
|
||||
# RFC 2247 (dc/dcObject)
|
||||
# RFC 2587 (PKI)
|
||||
# RFC 2589 (Dynamic Directory Services)
|
||||
#
|
||||
# Select informational schema items:
|
||||
# RFC 2377 (uidObject)
|
||||
#
|
||||
#
|
||||
# Standard attribute types from RFC 2256
|
||||
#
|
||||
dn: cn=core,cn=schema,cn=config
|
||||
objectClass: olcSchemaConfig
|
||||
cn: core
|
||||
#
|
||||
# system schema
|
||||
#olcAttributeTypes: ( 2.5.4.0 NAME 'objectClass'
|
||||
# DESC 'RFC2256: object classes of the entity'
|
||||
# EQUALITY objectIdentifierMatch
|
||||
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )
|
||||
#
|
||||
# system schema
|
||||
#olcAttributeTypes: ( 2.5.4.1 NAME ( 'aliasedObjectName' 'aliasedEntryName' )
|
||||
# DESC 'RFC2256: name of aliased object'
|
||||
# EQUALITY distinguishedNameMatch
|
||||
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.2 NAME 'knowledgeInformation'
|
||||
DESC 'RFC2256: knowledge information'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
|
||||
#
|
||||
# system schema
|
||||
#olcAttributeTypes: ( 2.5.4.3 NAME ( 'cn' 'commonName' )
|
||||
# DESC 'RFC2256: common name(s) for which the entity is known by'
|
||||
# SUP name )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.4 NAME ( 'sn' 'surname' )
|
||||
DESC 'RFC2256: last (family) name(s) for which the entity is known by'
|
||||
SUP name )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.5 NAME 'serialNumber'
|
||||
DESC 'RFC2256: serial number of the entity'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{64} )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.6 NAME ( 'c' 'countryName' )
|
||||
DESC 'RFC2256: ISO-3166 country 2-letter code'
|
||||
SUP name SINGLE-VALUE )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.7 NAME ( 'l' 'localityName' )
|
||||
DESC 'RFC2256: locality which this object resides in'
|
||||
SUP name )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.8 NAME ( 'st' 'stateOrProvinceName' )
|
||||
DESC 'RFC2256: state or province which this object resides in'
|
||||
SUP name )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.9 NAME ( 'street' 'streetAddress' )
|
||||
DESC 'RFC2256: street address of this object'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.10 NAME ( 'o' 'organizationName' )
|
||||
DESC 'RFC2256: organization this object belongs to'
|
||||
SUP name )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.11 NAME ( 'ou' 'organizationalUnitName' )
|
||||
DESC 'RFC2256: organizational unit this object belongs to'
|
||||
SUP name )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.12 NAME 'title'
|
||||
DESC 'RFC2256: title associated with the entity'
|
||||
SUP name )
|
||||
#
|
||||
# system schema
|
||||
#olcAttributeTypes: ( 2.5.4.13 NAME 'description'
|
||||
# DESC 'RFC2256: descriptive information'
|
||||
# EQUALITY caseIgnoreMatch
|
||||
# SUBSTR caseIgnoreSubstringsMatch
|
||||
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{1024} )
|
||||
#
|
||||
# Deprecated by enhancedSearchGuide
|
||||
olcAttributeTypes: ( 2.5.4.14 NAME 'searchGuide'
|
||||
DESC 'RFC2256: search guide, deprecated by enhancedSearchGuide'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.25 )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.15 NAME 'businessCategory'
|
||||
DESC 'RFC2256: business category'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.16 NAME 'postalAddress'
|
||||
DESC 'RFC2256: postal address'
|
||||
EQUALITY caseIgnoreListMatch
|
||||
SUBSTR caseIgnoreListSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.17 NAME 'postalCode'
|
||||
DESC 'RFC2256: postal code'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{40} )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.18 NAME 'postOfficeBox'
|
||||
DESC 'RFC2256: Post Office Box'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{40} )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.19 NAME 'physicalDeliveryOfficeName'
|
||||
DESC 'RFC2256: Physical Delivery Office Name'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128} )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.20 NAME 'telephoneNumber'
|
||||
DESC 'RFC2256: Telephone Number'
|
||||
EQUALITY telephoneNumberMatch
|
||||
SUBSTR telephoneNumberSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.50{32} )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.21 NAME 'telexNumber'
|
||||
DESC 'RFC2256: Telex Number'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.52 )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.22 NAME 'teletexTerminalIdentifier'
|
||||
DESC 'RFC2256: Teletex Terminal Identifier'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.51 )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.23 NAME ( 'facsimileTelephoneNumber' 'fax' )
|
||||
DESC 'RFC2256: Facsimile (Fax) Telephone Number'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.22 )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.24 NAME 'x121Address'
|
||||
DESC 'RFC2256: X.121 Address'
|
||||
EQUALITY numericStringMatch
|
||||
SUBSTR numericStringSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{15} )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.25 NAME 'internationaliSDNNumber'
|
||||
DESC 'RFC2256: international ISDN number'
|
||||
EQUALITY numericStringMatch
|
||||
SUBSTR numericStringSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{16} )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.26 NAME 'registeredAddress'
|
||||
DESC 'RFC2256: registered postal address'
|
||||
SUP postalAddress
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.27 NAME 'destinationIndicator'
|
||||
DESC 'RFC2256: destination indicator'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{128} )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.28 NAME 'preferredDeliveryMethod'
|
||||
DESC 'RFC2256: preferred delivery method'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.14
|
||||
SINGLE-VALUE )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.29 NAME 'presentationAddress'
|
||||
DESC 'RFC2256: presentation address'
|
||||
EQUALITY presentationAddressMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.43
|
||||
SINGLE-VALUE )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.30 NAME 'supportedApplicationContext'
|
||||
DESC 'RFC2256: supported application context'
|
||||
EQUALITY objectIdentifierMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.38 )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.31 NAME 'member'
|
||||
DESC 'RFC2256: member of a group'
|
||||
SUP distinguishedName )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.32 NAME 'owner'
|
||||
DESC 'RFC2256: owner (of the object)'
|
||||
SUP distinguishedName )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.33 NAME 'roleOccupant'
|
||||
DESC 'RFC2256: occupant of role'
|
||||
SUP distinguishedName )
|
||||
#
|
||||
# system schema
|
||||
#olcAttributeTypes: ( 2.5.4.34 NAME 'seeAlso'
|
||||
# DESC 'RFC2256: DN of related object'
|
||||
# SUP distinguishedName )
|
||||
#
|
||||
# system schema
|
||||
#olcAttributeTypes: ( 2.5.4.35 NAME 'userPassword'
|
||||
# DESC 'RFC2256/2307: password of user'
|
||||
# EQUALITY octetStringMatch
|
||||
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )
|
||||
#
|
||||
# Must be transferred using ;binary
|
||||
# with certificateExactMatch rule (per X.509)
|
||||
olcAttributeTypes: ( 2.5.4.36 NAME 'userCertificate'
|
||||
DESC 'RFC2256: X.509 user certificate, use ;binary'
|
||||
EQUALITY certificateExactMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )
|
||||
#
|
||||
# Must be transferred using ;binary
|
||||
# with certificateExactMatch rule (per X.509)
|
||||
olcAttributeTypes: ( 2.5.4.37 NAME 'cACertificate'
|
||||
DESC 'RFC2256: X.509 CA certificate, use ;binary'
|
||||
EQUALITY certificateExactMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.8 )
|
||||
#
|
||||
# Must be transferred using ;binary
|
||||
olcAttributeTypes: ( 2.5.4.38 NAME 'authorityRevocationList'
|
||||
DESC 'RFC2256: X.509 authority revocation list, use ;binary'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
|
||||
#
|
||||
# Must be transferred using ;binary
|
||||
olcAttributeTypes: ( 2.5.4.39 NAME 'certificateRevocationList'
|
||||
DESC 'RFC2256: X.509 certificate revocation list, use ;binary'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
|
||||
#
|
||||
# Must be stored and requested in the binary form
|
||||
olcAttributeTypes: ( 2.5.4.40 NAME 'crossCertificatePair'
|
||||
DESC 'RFC2256: X.509 cross certificate pair, use ;binary'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.10 )
|
||||
#
|
||||
# 2.5.4.41 is defined above as it's used for subtyping
|
||||
#olcAttributeTypes: ( 2.5.4.41 NAME 'name'
|
||||
# EQUALITY caseIgnoreMatch
|
||||
# SUBSTR caseIgnoreSubstringsMatch
|
||||
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.42 NAME ( 'givenName' 'gn' )
|
||||
DESC 'RFC2256: first name(s) for which the entity is known by'
|
||||
SUP name )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.43 NAME 'initials'
|
||||
DESC 'RFC2256: initials of some or all of names, but not the surname(s).'
|
||||
SUP name )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.44 NAME 'generationQualifier'
|
||||
DESC 'RFC2256: name qualifier indicating a generation'
|
||||
SUP name )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.45 NAME 'x500UniqueIdentifier'
|
||||
DESC 'RFC2256: X.500 unique identifier'
|
||||
EQUALITY bitStringMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.6 )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.46 NAME 'dnQualifier'
|
||||
DESC 'RFC2256: DN qualifier'
|
||||
EQUALITY caseIgnoreMatch
|
||||
ORDERING caseIgnoreOrderingMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44 )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.47 NAME 'enhancedSearchGuide'
|
||||
DESC 'RFC2256: enhanced search guide'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.21 )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.48 NAME 'protocolInformation'
|
||||
DESC 'RFC2256: protocol information'
|
||||
EQUALITY protocolInformationMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.42 )
|
||||
#
|
||||
# 2.5.4.49 is defined above as it's used for subtyping
|
||||
#olcAttributeTypes: ( 2.5.4.49 NAME 'distinguishedName'
|
||||
# EQUALITY distinguishedNameMatch
|
||||
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.50 NAME 'uniqueMember'
|
||||
DESC 'RFC2256: unique member of a group'
|
||||
EQUALITY uniqueMemberMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.34 )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.51 NAME 'houseIdentifier'
|
||||
DESC 'RFC2256: house identifier'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{32768} )
|
||||
#
|
||||
# Must be transferred using ;binary
|
||||
olcAttributeTypes: ( 2.5.4.52 NAME 'supportedAlgorithms'
|
||||
DESC 'RFC2256: supported algorithms'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.49 )
|
||||
#
|
||||
# Must be transferred using ;binary
|
||||
olcAttributeTypes: ( 2.5.4.53 NAME 'deltaRevocationList'
|
||||
DESC 'RFC2256: delta revocation list; use ;binary'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.9 )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.54 NAME 'dmdName'
|
||||
DESC 'RFC2256: name of DMD'
|
||||
SUP name )
|
||||
#
|
||||
olcAttributeTypes: ( 2.5.4.65 NAME 'pseudonym'
|
||||
DESC 'X.520(4th): pseudonym for the object'
|
||||
SUP name )
|
||||
#
|
||||
# Standard object classes from RFC2256
|
||||
#
|
||||
# system schema
|
||||
#olcObjectClasses: ( 2.5.6.1 NAME 'alias'
|
||||
# DESC 'RFC2256: an alias'
|
||||
# SUP top STRUCTURAL
|
||||
# MUST aliasedObjectName )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.2 NAME 'country'
|
||||
DESC 'RFC2256: a country'
|
||||
SUP top STRUCTURAL
|
||||
MUST c
|
||||
MAY ( searchGuide $ description ) )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.3 NAME 'locality'
|
||||
DESC 'RFC2256: a locality'
|
||||
SUP top STRUCTURAL
|
||||
MAY ( street $ seeAlso $ searchGuide $ st $ l $ description ) )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.4 NAME 'organization'
|
||||
DESC 'RFC2256: an organization'
|
||||
SUP top STRUCTURAL
|
||||
MUST o
|
||||
MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
|
||||
x121Address $ registeredAddress $ destinationIndicator $
|
||||
preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
|
||||
telephoneNumber $ internationaliSDNNumber $
|
||||
facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $
|
||||
postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.5 NAME 'organizationalUnit'
|
||||
DESC 'RFC2256: an organizational unit'
|
||||
SUP top STRUCTURAL
|
||||
MUST ou
|
||||
MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
|
||||
x121Address $ registeredAddress $ destinationIndicator $
|
||||
preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
|
||||
telephoneNumber $ internationaliSDNNumber $
|
||||
facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $
|
||||
postalAddress $ physicalDeliveryOfficeName $ st $ l $ description ) )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.6 NAME 'person'
|
||||
DESC 'RFC2256: a person'
|
||||
SUP top STRUCTURAL
|
||||
MUST ( sn $ cn )
|
||||
MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.7 NAME 'organizationalPerson'
|
||||
DESC 'RFC2256: an organizational person'
|
||||
SUP person STRUCTURAL
|
||||
MAY ( title $ x121Address $ registeredAddress $ destinationIndicator $
|
||||
preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
|
||||
telephoneNumber $ internationaliSDNNumber $
|
||||
facsimileTelephoneNumber $ street $ postOfficeBox $ postalCode $
|
||||
postalAddress $ physicalDeliveryOfficeName $ ou $ st $ l ) )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.8 NAME 'organizationalRole'
|
||||
DESC 'RFC2256: an organizational role'
|
||||
SUP top STRUCTURAL
|
||||
MUST cn
|
||||
MAY ( x121Address $ registeredAddress $ destinationIndicator $
|
||||
preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
|
||||
telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $
|
||||
seeAlso $ roleOccupant $ preferredDeliveryMethod $ street $
|
||||
postOfficeBox $ postalCode $ postalAddress $
|
||||
physicalDeliveryOfficeName $ ou $ st $ l $ description ) )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.9 NAME 'groupOfNames'
|
||||
DESC 'RFC2256: a group of names (DNs)'
|
||||
SUP top STRUCTURAL
|
||||
MUST ( member $ cn )
|
||||
MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.10 NAME 'residentialPerson'
|
||||
DESC 'RFC2256: an residential person'
|
||||
SUP person STRUCTURAL
|
||||
MUST l
|
||||
MAY ( businessCategory $ x121Address $ registeredAddress $
|
||||
destinationIndicator $ preferredDeliveryMethod $ telexNumber $
|
||||
teletexTerminalIdentifier $ telephoneNumber $ internationaliSDNNumber $
|
||||
facsimileTelephoneNumber $ preferredDeliveryMethod $ street $
|
||||
postOfficeBox $ postalCode $ postalAddress $
|
||||
physicalDeliveryOfficeName $ st $ l ) )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.11 NAME 'applicationProcess'
|
||||
DESC 'RFC2256: an application process'
|
||||
SUP top STRUCTURAL
|
||||
MUST cn
|
||||
MAY ( seeAlso $ ou $ l $ description ) )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.12 NAME 'applicationEntity'
|
||||
DESC 'RFC2256: an application entity'
|
||||
SUP top STRUCTURAL
|
||||
MUST ( presentationAddress $ cn )
|
||||
MAY ( supportedApplicationContext $ seeAlso $ ou $ o $ l $
|
||||
description ) )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.13 NAME 'dSA'
|
||||
DESC 'RFC2256: a directory system agent (a server)'
|
||||
SUP applicationEntity STRUCTURAL
|
||||
MAY knowledgeInformation )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.14 NAME 'device'
|
||||
DESC 'RFC2256: a device'
|
||||
SUP top STRUCTURAL
|
||||
MUST cn
|
||||
MAY ( serialNumber $ seeAlso $ owner $ ou $ o $ l $ description ) )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.15 NAME 'strongAuthenticationUser'
|
||||
DESC 'RFC2256: a strong authentication user'
|
||||
SUP top AUXILIARY
|
||||
MUST userCertificate )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.16 NAME 'certificationAuthority'
|
||||
DESC 'RFC2256: a certificate authority'
|
||||
SUP top AUXILIARY
|
||||
MUST ( authorityRevocationList $ certificateRevocationList $
|
||||
cACertificate ) MAY crossCertificatePair )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.17 NAME 'groupOfUniqueNames'
|
||||
DESC 'RFC2256: a group of unique names (DN and Unique Identifier)'
|
||||
SUP top STRUCTURAL
|
||||
MUST ( uniqueMember $ cn )
|
||||
MAY ( businessCategory $ seeAlso $ owner $ ou $ o $ description ) )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.18 NAME 'userSecurityInformation'
|
||||
DESC 'RFC2256: a user security information'
|
||||
SUP top AUXILIARY
|
||||
MAY ( supportedAlgorithms ) )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.16.2 NAME 'certificationAuthority-V2'
|
||||
SUP certificationAuthority
|
||||
AUXILIARY MAY ( deltaRevocationList ) )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.19 NAME 'cRLDistributionPoint'
|
||||
SUP top STRUCTURAL
|
||||
MUST ( cn )
|
||||
MAY ( certificateRevocationList $ authorityRevocationList $
|
||||
deltaRevocationList ) )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.20 NAME 'dmd'
|
||||
SUP top STRUCTURAL
|
||||
MUST ( dmdName )
|
||||
MAY ( userPassword $ searchGuide $ seeAlso $ businessCategory $
|
||||
x121Address $ registeredAddress $ destinationIndicator $
|
||||
preferredDeliveryMethod $ telexNumber $ teletexTerminalIdentifier $
|
||||
telephoneNumber $ internationaliSDNNumber $ facsimileTelephoneNumber $
|
||||
street $ postOfficeBox $ postalCode $ postalAddress $
|
||||
physicalDeliveryOfficeName $ st $ l $ description ) )
|
||||
#
|
||||
#
|
||||
# Object Classes from RFC 2587
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.21 NAME 'pkiUser'
|
||||
DESC 'RFC2587: a PKI user'
|
||||
SUP top AUXILIARY
|
||||
MAY userCertificate )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.22 NAME 'pkiCA'
|
||||
DESC 'RFC2587: PKI certificate authority'
|
||||
SUP top AUXILIARY
|
||||
MAY ( authorityRevocationList $ certificateRevocationList $
|
||||
cACertificate $ crossCertificatePair ) )
|
||||
#
|
||||
olcObjectClasses: ( 2.5.6.23 NAME 'deltaCRL'
|
||||
DESC 'RFC2587: PKI user'
|
||||
SUP top AUXILIARY
|
||||
MAY deltaRevocationList )
|
||||
#
|
||||
#
|
||||
# Standard Track URI label schema from RFC 2079
|
||||
# system schema
|
||||
#olcAttributeTypes: ( 1.3.6.1.4.1.250.1.57 NAME 'labeledURI'
|
||||
# DESC 'RFC2079: Uniform Resource Identifier with optional label'
|
||||
# EQUALITY caseExactMatch
|
||||
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
|
||||
#
|
||||
olcObjectClasses: ( 1.3.6.1.4.1.250.3.15 NAME 'labeledURIObject'
|
||||
DESC 'RFC2079: object that contains the URI attribute type'
|
||||
MAY ( labeledURI )
|
||||
SUP top AUXILIARY )
|
||||
#
|
||||
#
|
||||
# Derived from RFC 1274, but with new "short names"
|
||||
#
|
||||
#olcAttributeTypes: ( 0.9.2342.19200300.100.1.1
|
||||
# NAME ( 'uid' 'userid' )
|
||||
# DESC 'RFC1274: user identifier'
|
||||
# EQUALITY caseIgnoreMatch
|
||||
# SUBSTR caseIgnoreSubstringsMatch
|
||||
# SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
|
||||
#
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.3
|
||||
NAME ( 'mail' 'rfc822Mailbox' )
|
||||
DESC 'RFC1274: RFC822 Mailbox'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
|
||||
#
|
||||
olcObjectClasses: ( 0.9.2342.19200300.100.4.19 NAME 'simpleSecurityObject'
|
||||
DESC 'RFC1274: simple security object'
|
||||
SUP top AUXILIARY
|
||||
MUST userPassword )
|
||||
#
|
||||
# RFC 1274 + RFC 2247
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.25
|
||||
NAME ( 'dc' 'domainComponent' )
|
||||
DESC 'RFC1274/2247: domain component'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
|
||||
#
|
||||
# RFC 2247
|
||||
olcObjectClasses: ( 1.3.6.1.4.1.1466.344 NAME 'dcObject'
|
||||
DESC 'RFC2247: domain component object'
|
||||
SUP top AUXILIARY MUST dc )
|
||||
#
|
||||
# RFC 2377
|
||||
olcObjectClasses: ( 1.3.6.1.1.3.1 NAME 'uidObject'
|
||||
DESC 'RFC2377: uid object'
|
||||
SUP top AUXILIARY MUST uid )
|
||||
#
|
||||
# From COSINE Pilot
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.37
|
||||
NAME 'associatedDomain'
|
||||
DESC 'RFC1274: domain associated with object'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
|
||||
#
|
||||
# RFC 2459 -- deprecated in favor of 'mail' (in cosine.schema)
|
||||
olcAttributeTypes: ( 1.2.840.113549.1.9.1
|
||||
NAME ( 'email' 'emailAddress' 'pkcs9email' )
|
||||
DESC 'RFC3280: legacy attribute for email addresses in DNs'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} )
|
||||
#
|
|
@ -0,0 +1,200 @@
|
|||
# RFC1274: Cosine and Internet X.500 schema
|
||||
# $OpenLDAP$
|
||||
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
##
|
||||
## Copyright 1998-2012 The OpenLDAP Foundation.
|
||||
## All rights reserved.
|
||||
##
|
||||
## Redistribution and use in source and binary forms, with or without
|
||||
## modification, are permitted only as authorized by the OpenLDAP
|
||||
## Public License.
|
||||
##
|
||||
## A copy of this license is available in the file LICENSE in the
|
||||
## top-level directory of the distribution or, alternatively, at
|
||||
## <http://www.OpenLDAP.org/license.html>.
|
||||
#
|
||||
# RFC1274: Cosine and Internet X.500 schema
|
||||
#
|
||||
# This file contains LDAPv3 schema derived from X.500 COSINE "pilot"
|
||||
# schema. As this schema was defined for X.500(89), some
|
||||
# oddities were introduced in the mapping to LDAPv3. The
|
||||
# mappings were based upon: draft-ietf-asid-ldapv3-attributes-03.txt
|
||||
# (a work in progress)
|
||||
#
|
||||
# Note: It seems that the pilot schema evolved beyond what was
|
||||
# described in RFC1274. However, this document attempts to describes
|
||||
# RFC1274 as published.
|
||||
#
|
||||
# Depends on core.ldif
|
||||
#
|
||||
# This file was automatically generated from cosine.schema; see that
|
||||
# file for complete background.
|
||||
#
|
||||
dn: cn=cosine,cn=schema,cn=config
|
||||
objectClass: olcSchemaConfig
|
||||
cn: cosine
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.2 NAME 'textEncodedORAddress'
|
||||
EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.
|
||||
1466.115.121.1.15{256} )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.4 NAME 'info' DESC 'RFC1274: g
|
||||
eneral information' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{2048} )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.5 NAME ( 'drink' 'favouriteDri
|
||||
nk' ) DESC 'RFC1274: favorite drink' EQUALITY caseIgnoreMatch SUBSTR caseIgno
|
||||
reSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.6 NAME 'roomNumber' DESC 'RFC1
|
||||
274: room number' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch S
|
||||
YNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.7 NAME 'photo' DESC 'RFC1274:
|
||||
photo (G3 fax)' SYNTAX 1.3.6.1.4.1.1466.115.121.1.23{25000} )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.8 NAME 'userClass' DESC 'RFC12
|
||||
74: category of user' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMat
|
||||
ch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.9 NAME 'host' DESC 'RFC1274: h
|
||||
ost computer' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTA
|
||||
X 1.3.6.1.4.1.1466.115.121.1.15{256} )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.10 NAME 'manager' DESC 'RFC127
|
||||
4: DN of manager' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115
|
||||
.121.1.12 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.11 NAME 'documentIdentifier' D
|
||||
ESC 'RFC1274: unique identifier of document' EQUALITY caseIgnoreMatch SUBSTR
|
||||
caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.12 NAME 'documentTitle' DESC '
|
||||
RFC1274: title of document' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstri
|
||||
ngsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.13 NAME 'documentVersion' DES
|
||||
C 'RFC1274: version of document' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSu
|
||||
bstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.14 NAME 'documentAuthor' DESC
|
||||
'RFC1274: DN of author of document' EQUALITY distinguishedNameMatch SYNTAX 1
|
||||
.3.6.1.4.1.1466.115.121.1.12 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.15 NAME 'documentLocation' DE
|
||||
SC 'RFC1274: location of document original' EQUALITY caseIgnoreMatch SUBSTR c
|
||||
aseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.20 NAME ( 'homePhone' 'homeTe
|
||||
lephoneNumber' ) DESC 'RFC1274: home telephone number' EQUALITY telephoneNumb
|
||||
erMatch SUBSTR telephoneNumberSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121
|
||||
.1.50 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.21 NAME 'secretary' DESC 'RFC
|
||||
1274: DN of secretary' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.146
|
||||
6.115.121.1.12 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.22 NAME 'otherMailbox' SYNTAX
|
||||
1.3.6.1.4.1.1466.115.121.1.39 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.26 NAME 'aRecord' EQUALITY ca
|
||||
seIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.27 NAME 'mDRecord' EQUALITY c
|
||||
aseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.28 NAME 'mXRecord' EQUALITY c
|
||||
aseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.29 NAME 'nSRecord' EQUALITY c
|
||||
aseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.30 NAME 'sOARecord' EQUALITY
|
||||
caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.31 NAME 'cNAMERecord' EQUALIT
|
||||
Y caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.38 NAME 'associatedName' DESC
|
||||
'RFC1274: DN of entry associated with domain' EQUALITY distinguishedNameMatc
|
||||
h SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.39 NAME 'homePostalAddress' D
|
||||
ESC 'RFC1274: home postal address' EQUALITY caseIgnoreListMatch SUBSTR caseIg
|
||||
noreListSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.41 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.40 NAME 'personalTitle' DESC
|
||||
'RFC1274: personal title' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstring
|
||||
sMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.41 NAME ( 'mobile' 'mobileTel
|
||||
ephoneNumber' ) DESC 'RFC1274: mobile telephone number' EQUALITY telephoneNum
|
||||
berMatch SUBSTR telephoneNumberSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.12
|
||||
1.1.50 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.42 NAME ( 'pager' 'pagerTelep
|
||||
honeNumber' ) DESC 'RFC1274: pager telephone number' EQUALITY telephoneNumber
|
||||
Match SUBSTR telephoneNumberSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1
|
||||
.50 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.43 NAME ( 'co' 'friendlyCount
|
||||
ryName' ) DESC 'RFC1274: friendly country name' EQUALITY caseIgnoreMatch SUBS
|
||||
TR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.44 NAME 'uniqueIdentifier' DE
|
||||
SC 'RFC1274: unique identifer' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.1.14
|
||||
66.115.121.1.15{256} )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.45 NAME 'organizationalStatus
|
||||
' DESC 'RFC1274: organizational status' EQUALITY caseIgnoreMatch SUBSTR caseI
|
||||
gnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.46 NAME 'janetMailbox' DESC '
|
||||
RFC1274: Janet mailbox' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5Subst
|
||||
ringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256} )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.47 NAME 'mailPreferenceOption
|
||||
' DESC 'RFC1274: mail preference option' SYNTAX 1.3.6.1.4.1.1466.115.121.1.27
|
||||
)
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.48 NAME 'buildingName' DESC '
|
||||
RFC1274: name of building' EQUALITY caseIgnoreMatch SUBSTR caseIgnoreSubstrin
|
||||
gsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256} )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.49 NAME 'dSAQuality' DESC 'RF
|
||||
C1274: DSA Quality' SYNTAX 1.3.6.1.4.1.1466.115.121.1.19 SINGLE-VALUE )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.50 NAME 'singleLevelQuality'
|
||||
DESC 'RFC1274: Single Level Quality' SYNTAX 1.3.6.1.4.1.1466.115.121.1.13 SIN
|
||||
GLE-VALUE )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.51 NAME 'subtreeMinimumQualit
|
||||
y' DESC 'RFC1274: Subtree Mininum Quality' SYNTAX 1.3.6.1.4.1.1466.115.121.1.
|
||||
13 SINGLE-VALUE )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.52 NAME 'subtreeMaximumQualit
|
||||
y' DESC 'RFC1274: Subtree Maximun Quality' SYNTAX 1.3.6.1.4.1.1466.115.121.1.
|
||||
13 SINGLE-VALUE )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.53 NAME 'personalSignature' D
|
||||
ESC 'RFC1274: Personal Signature (G3 fax)' SYNTAX 1.3.6.1.4.1.1466.115.121.1.
|
||||
23 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.54 NAME 'dITRedirect' DESC 'R
|
||||
FC1274: DIT Redirect' EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466
|
||||
.115.121.1.12 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.55 NAME 'audio' DESC 'RFC1274
|
||||
: audio (u-law)' SYNTAX 1.3.6.1.4.1.1466.115.121.1.4{25000} )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.56 NAME 'documentPublisher' D
|
||||
ESC 'RFC1274: publisher of document' EQUALITY caseIgnoreMatch SUBSTR caseIgno
|
||||
reSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
|
||||
olcObjectClasses: ( 0.9.2342.19200300.100.4.4 NAME ( 'pilotPerson' 'newPilo
|
||||
tPerson' ) SUP person STRUCTURAL MAY ( userid $ textEncodedORAddress $ rfc822
|
||||
Mailbox $ favouriteDrink $ roomNumber $ userClass $ homeTelephoneNumber $ hom
|
||||
ePostalAddress $ secretary $ personalTitle $ preferredDeliveryMethod $ busine
|
||||
ssCategory $ janetMailbox $ otherMailbox $ mobileTelephoneNumber $ pagerTelep
|
||||
honeNumber $ organizationalStatus $ mailPreferenceOption $ personalSignature
|
||||
) )
|
||||
olcObjectClasses: ( 0.9.2342.19200300.100.4.5 NAME 'account' SUP top STRUCT
|
||||
URAL MUST userid MAY ( description $ seeAlso $ localityName $ organizationNam
|
||||
e $ organizationalUnitName $ host ) )
|
||||
olcObjectClasses: ( 0.9.2342.19200300.100.4.6 NAME 'document' SUP top STRUC
|
||||
TURAL MUST documentIdentifier MAY ( commonName $ description $ seeAlso $ loca
|
||||
lityName $ organizationName $ organizationalUnitName $ documentTitle $ docume
|
||||
ntVersion $ documentAuthor $ documentLocation $ documentPublisher ) )
|
||||
olcObjectClasses: ( 0.9.2342.19200300.100.4.7 NAME 'room' SUP top STRUCTURA
|
||||
L MUST commonName MAY ( roomNumber $ description $ seeAlso $ telephoneNumber
|
||||
) )
|
||||
olcObjectClasses: ( 0.9.2342.19200300.100.4.9 NAME 'documentSeries' SUP top
|
||||
STRUCTURAL MUST commonName MAY ( description $ seeAlso $ telephonenumber $ l
|
||||
ocalityName $ organizationName $ organizationalUnitName ) )
|
||||
olcObjectClasses: ( 0.9.2342.19200300.100.4.13 NAME 'domain' SUP top STRUCT
|
||||
URAL MUST domainComponent MAY ( associatedName $ organizationName $ descripti
|
||||
on $ businessCategory $ seeAlso $ searchGuide $ userPassword $ localityName $
|
||||
stateOrProvinceName $ streetAddress $ physicalDeliveryOfficeName $ postalAdd
|
||||
ress $ postalCode $ postOfficeBox $ streetAddress $ facsimileTelephoneNumber
|
||||
$ internationalISDNNumber $ telephoneNumber $ teletexTerminalIdentifier $ tel
|
||||
exNumber $ preferredDeliveryMethod $ destinationIndicator $ registeredAddress
|
||||
$ x121Address ) )
|
||||
olcObjectClasses: ( 0.9.2342.19200300.100.4.14 NAME 'RFC822localPart' SUP d
|
||||
omain STRUCTURAL MAY ( commonName $ surname $ description $ seeAlso $ telepho
|
||||
neNumber $ physicalDeliveryOfficeName $ postalAddress $ postalCode $ postOffi
|
||||
ceBox $ streetAddress $ facsimileTelephoneNumber $ internationalISDNNumber $
|
||||
telephoneNumber $ teletexTerminalIdentifier $ telexNumber $ preferredDelivery
|
||||
Method $ destinationIndicator $ registeredAddress $ x121Address ) )
|
||||
olcObjectClasses: ( 0.9.2342.19200300.100.4.15 NAME 'dNSDomain' SUP domain
|
||||
STRUCTURAL MAY ( ARecord $ MDRecord $ MXRecord $ NSRecord $ SOARecord $ CNAME
|
||||
Record ) )
|
||||
olcObjectClasses: ( 0.9.2342.19200300.100.4.17 NAME 'domainRelatedObject' D
|
||||
ESC 'RFC1274: an object related to an domain' SUP top AUXILIARY MUST associat
|
||||
edDomain )
|
||||
olcObjectClasses: ( 0.9.2342.19200300.100.4.18 NAME 'friendlyCountry' SUP c
|
||||
ountry STRUCTURAL MUST friendlyCountryName )
|
||||
olcObjectClasses: ( 0.9.2342.19200300.100.4.20 NAME 'pilotOrganization' SU
|
||||
P ( organization $ organizationalUnit ) STRUCTURAL MAY buildingName )
|
||||
olcObjectClasses: ( 0.9.2342.19200300.100.4.21 NAME 'pilotDSA' SUP dsa STR
|
||||
UCTURAL MAY dSAQuality )
|
||||
olcObjectClasses: ( 0.9.2342.19200300.100.4.22 NAME 'qualityLabelledData'
|
||||
SUP top AUXILIARY MUST dsaQuality MAY ( subtreeMinimumQuality $ subtreeMaximu
|
||||
mQuality ) )
|
|
@ -0,0 +1,21 @@
|
|||
dn: cn=eduorg-200210,cn=schema,cn=config
|
||||
objectClass: olcSchemaConfig
|
||||
cn: eduorg-200210
|
||||
olcAttributeTypes: {0}( 1.3.6.1.4.1.5923.1.2.1.2 NAME 'eduOrgHomePageURI' DESC
|
||||
'eduOrg per Internet2 and EDUCAUSE' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4
|
||||
.1.1466.115.121.1.15 )
|
||||
olcAttributeTypes: {1}( 1.3.6.1.4.1.5923.1.2.1.3 NAME 'eduOrgIdentityAuthNPoli
|
||||
cyURI' DESC 'eduOrg per Internet2 and EDUCAUSE' EQUALITY caseExactMatch SYNTA
|
||||
X 1.3.6.1.4.1.1466.115.121.1.15 )
|
||||
olcAttributeTypes: {2}( 1.3.6.1.4.1.5923.1.2.1.4 NAME 'eduOrgLegalName' DESC '
|
||||
eduOrg per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SYNTAX 1.3.6.1.4.
|
||||
1.1466.115.121.1.15 )
|
||||
olcAttributeTypes: {3}( 1.3.6.1.4.1.5923.1.2.1.5 NAME 'eduOrgSuperiorURI' DESC
|
||||
'eduOrg per Internet2 and EDUCAUSE' EQUALITY caseExactMatch SYNTAX 1.3.6.1.4
|
||||
.1.1466.115.121.1.15 )
|
||||
olcAttributeTypes: {4}( 1.3.6.1.4.1.5923.1.2.1.6 NAME 'eduOrgWhitePagesURI' DE
|
||||
SC 'eduOrg per Internet2 and EDUCAUSE' EQUALITY caseExactMatch SYNTAX 1.3.6.1
|
||||
.4.1.1466.115.121.1.15 )
|
||||
olcObjectClasses: {0}( 1.3.6.1.4.1.5923.1.2.2 NAME 'eduOrg' AUXILIARY MAY ( cn
|
||||
$ eduOrgHomePageURI $ eduOrgIdentityAuthNPolicyURI $ eduOrgLegalName $ eduOr
|
||||
gSuperiorURI $ eduOrgWhitePagesURI ) )
|
|
@ -0,0 +1,47 @@
|
|||
# This LDIF file can be used to add to add the eduPerson schema to
|
||||
# an OpenLDAP server > 2.4 that uses the new configuration format.
|
||||
# Put this file to /etc/ldap/schema/ and then execute the following
|
||||
# comand to add this schema:
|
||||
# ldapadd -Y EXTERNAL -H ldapi:/// -f /etc/ldap/schema/eduperson.ldif
|
||||
dn: cn=eduperson,cn=schema,cn=config
|
||||
objectClass: olcSchemaConfig
|
||||
cn: eduperson
|
||||
olcAttributeTypes: {0}( 1.3.6.1.4.1.5923.1.1.1.1 NAME 'eduPersonAffiliation' D
|
||||
ESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SUBSTR ca
|
||||
seIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
|
||||
olcAttributeTypes: {1}( 1.3.6.1.4.1.5923.1.1.1.2 NAME 'eduPersonNickname' DESC
|
||||
'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SUBSTR caseI
|
||||
gnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
|
||||
olcAttributeTypes: {2}( 1.3.6.1.4.1.5923.1.1.1.3 NAME 'eduPersonOrgDN' DESC 'e
|
||||
duPerson per Internet2 and EDUCAUSE' EQUALITY distinguishedNameMatch SYNTAX 1
|
||||
.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )
|
||||
olcAttributeTypes: {3}( 1.3.6.1.4.1.5923.1.1.1.4 NAME 'eduPersonOrgUnitDN' DES
|
||||
C 'eduPerson per Internet2 and EDUCAUSE' EQUALITY distinguishedNameMatch SYNT
|
||||
AX 1.3.6.1.4.1.1466.115.121.1.12 )
|
||||
olcAttributeTypes: {4}( 1.3.6.1.4.1.5923.1.1.1.5 NAME 'eduPersonPrimaryAffilia
|
||||
tion' DESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SU
|
||||
BSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VA
|
||||
LUE )
|
||||
olcAttributeTypes: {5}( 1.3.6.1.4.1.5923.1.1.1.6 NAME 'eduPersonPrincipalName'
|
||||
DESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SUBSTR
|
||||
caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE )
|
||||
olcAttributeTypes: {6}( 1.3.6.1.4.1.5923.1.1.1.7 NAME 'eduPersonEntitlement' D
|
||||
ESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseExactMatch SYNTAX 1.3
|
||||
.6.1.4.1.1466.115.121.1.15 )
|
||||
olcAttributeTypes: {7}( 1.3.6.1.4.1.5923.1.1.1.8 NAME 'eduPersonPrimaryOrgUnit
|
||||
DN' DESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY distinguishedNameMat
|
||||
ch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 SINGLE-VALUE )
|
||||
olcAttributeTypes: {8}( 1.3.6.1.4.1.5923.1.1.1.9 NAME 'eduPersonScopedAffiliat
|
||||
ion' DESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SYN
|
||||
TAX 1.3.6.1.4.1.1466.115.121.1.15 )
|
||||
olcAttributeTypes: {9}( 1.3.6.1.4.1.5923.1.1.1.10 NAME 'eduPersonTargetedID' D
|
||||
ESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SYNTAX 1.
|
||||
3.6.1.4.1.1466.115.121.1.15 )
|
||||
olcAttributeTypes: {10}( 1.3.6.1.4.1.5923.1.1.1.11 NAME 'eduPersonAssurance' D
|
||||
ESC 'eduPerson per Internet2 and EDUCAUSE' EQUALITY caseIgnoreMatch SYNTAX 1.
|
||||
3.6.1.4.1.1466.115.121.1.15 )
|
||||
olcObjectClasses: {0}( 1.3.6.1.4.1.5923.1.1.2 NAME 'eduPerson' DESC 'eduPerson
|
||||
per Internet2 and EDUCAUSE' AUXILIARY MAY ( eduPersonAffiliation $ eduPerson
|
||||
Nickname $ eduPersonOrgDN $ eduPersonOrgUnitDN $ eduPersonPrimaryAffiliation
|
||||
$ eduPersonPrincipalName $ eduPersonEntitlement $ eduPersonPrimaryOrgUnitDN $
|
||||
eduPersonScopedAffiliation $ eduPersonTargetedID $ eduPersonAssurance ) )
|
|
@ -0,0 +1,69 @@
|
|||
# InetOrgPerson (RFC2798)
|
||||
# $OpenLDAP$
|
||||
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
##
|
||||
## Copyright 1998-2012 The OpenLDAP Foundation.
|
||||
## All rights reserved.
|
||||
##
|
||||
## Redistribution and use in source and binary forms, with or without
|
||||
## modification, are permitted only as authorized by the OpenLDAP
|
||||
## Public License.
|
||||
##
|
||||
## A copy of this license is available in the file LICENSE in the
|
||||
## top-level directory of the distribution or, alternatively, at
|
||||
## <http://www.OpenLDAP.org/license.html>.
|
||||
#
|
||||
# InetOrgPerson (RFC2798)
|
||||
#
|
||||
# Depends upon
|
||||
# Definition of an X.500 Attribute Type and an Object Class to Hold
|
||||
# Uniform Resource Identifiers (URIs) [RFC2079]
|
||||
# (core.ldif)
|
||||
#
|
||||
# A Summary of the X.500(96) User Schema for use with LDAPv3 [RFC2256]
|
||||
# (core.ldif)
|
||||
#
|
||||
# The COSINE and Internet X.500 Schema [RFC1274] (cosine.ldif)
|
||||
#
|
||||
# This file was automatically generated from inetorgperson.schema; see
|
||||
# that file for complete references.
|
||||
#
|
||||
dn: cn=inetorgperson,cn=schema,cn=config
|
||||
objectClass: olcSchemaConfig
|
||||
cn: inetorgperson
|
||||
olcAttributeTypes: ( 2.16.840.1.113730.3.1.1 NAME 'carLicense' DESC 'RFC279
|
||||
8: vehicle license or registration plate' EQUALITY caseIgnoreMatch SUBSTR cas
|
||||
eIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
|
||||
olcAttributeTypes: ( 2.16.840.1.113730.3.1.2 NAME 'departmentNumber' DESC '
|
||||
RFC2798: identifies a department within an organization' EQUALITY caseIgnoreM
|
||||
atch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
|
||||
olcAttributeTypes: ( 2.16.840.1.113730.3.1.241 NAME 'displayName' DESC 'RFC
|
||||
2798: preferred name to be used when displaying entries' EQUALITY caseIgnoreM
|
||||
atch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SI
|
||||
NGLE-VALUE )
|
||||
olcAttributeTypes: ( 2.16.840.1.113730.3.1.3 NAME 'employeeNumber' DESC 'RF
|
||||
C2798: numerically identifies an employee within an organization' EQUALITY ca
|
||||
seIgnoreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.12
|
||||
1.1.15 SINGLE-VALUE )
|
||||
olcAttributeTypes: ( 2.16.840.1.113730.3.1.4 NAME 'employeeType' DESC 'RFC2
|
||||
798: type of employment for a person' EQUALITY caseIgnoreMatch SUBSTR caseIgn
|
||||
oreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 )
|
||||
olcAttributeTypes: ( 0.9.2342.19200300.100.1.60 NAME 'jpegPhoto' DESC 'RFC2
|
||||
798: a JPEG image' SYNTAX 1.3.6.1.4.1.1466.115.121.1.28 )
|
||||
olcAttributeTypes: ( 2.16.840.1.113730.3.1.39 NAME 'preferredLanguage' DESC
|
||||
'RFC2798: preferred written or spoken language for a person' EQUALITY caseIg
|
||||
noreMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.
|
||||
15 SINGLE-VALUE )
|
||||
olcAttributeTypes: ( 2.16.840.1.113730.3.1.40 NAME 'userSMIMECertificate' D
|
||||
ESC 'RFC2798: PKCS#7 SignedData used to support S/MIME' SYNTAX 1.3.6.1.4.1.14
|
||||
66.115.121.1.5 )
|
||||
olcAttributeTypes: ( 2.16.840.1.113730.3.1.216 NAME 'userPKCS12' DESC 'RFC2
|
||||
798: personal identity information, a PKCS #12 PFX' SYNTAX 1.3.6.1.4.1.1466.1
|
||||
15.121.1.5 )
|
||||
olcObjectClasses: ( 2.16.840.1.113730.3.2.2 NAME 'inetOrgPerson' DESC 'RFC2
|
||||
798: Internet Organizational Person' SUP organizationalPerson STRUCTURAL MAY
|
||||
( audio $ businessCategory $ carLicense $ departmentNumber $ displayName $ em
|
||||
ployeeNumber $ employeeType $ givenName $ homePhone $ homePostalAddress $ ini
|
||||
tials $ jpegPhoto $ labeledURI $ mail $ manager $ mobile $ o $ pager $ photo
|
||||
$ roomNumber $ secretary $ uid $ userCertificate $ x500uniqueIdentifier $ pre
|
||||
ferredLanguage $ userSMIMECertificate $ userPKCS12 ) )
|
|
@ -0,0 +1,120 @@
|
|||
# NIS (RFC2307)
|
||||
# $OpenLDAP$
|
||||
## This work is part of OpenLDAP Software <http://www.openldap.org/>.
|
||||
##
|
||||
## Copyright 1998-2014 The OpenLDAP Foundation.
|
||||
## All rights reserved.
|
||||
##
|
||||
## Redistribution and use in source and binary forms, with or without
|
||||
## modification, are permitted only as authorized by the OpenLDAP
|
||||
## Public License.
|
||||
##
|
||||
## A copy of this license is available in the file LICENSE in the
|
||||
## top-level directory of the distribution or, alternatively, at
|
||||
## <http://www.OpenLDAP.org/license.html>.
|
||||
#
|
||||
# Definitions from RFC2307 (Experimental)
|
||||
# An Approach for Using LDAP as a Network Information Service
|
||||
#
|
||||
# Depends upon core.ldif and cosine.ldif
|
||||
#
|
||||
# This file was automatically generated from nis.schema; see that file
|
||||
# for complete references.
|
||||
#
|
||||
dn: cn=nis,cn=schema,cn=config
|
||||
objectClass: olcSchemaConfig
|
||||
cn: nis
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.2 NAME 'gecos' DESC 'The GECOS field; th
|
||||
e common name' EQUALITY caseIgnoreIA5Match SUBSTR caseIgnoreIA5SubstringsMatc
|
||||
h SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.3 NAME 'homeDirectory' DESC 'The absolut
|
||||
e path to the home directory' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1
|
||||
466.115.121.1.26 SINGLE-VALUE )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.4 NAME 'loginShell' DESC 'The path to th
|
||||
e login shell' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.2
|
||||
6 SINGLE-VALUE )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.5 NAME 'shadowLastChange' EQUALITY integ
|
||||
erMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.6 NAME 'shadowMin' EQUALITY integerMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.7 NAME 'shadowMax' EQUALITY integerMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.8 NAME 'shadowWarning' EQUALITY integerM
|
||||
atch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.9 NAME 'shadowInactive' EQUALITY integer
|
||||
Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.10 NAME 'shadowExpire' EQUALITY integerM
|
||||
atch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.11 NAME 'shadowFlag' EQUALITY integerMat
|
||||
ch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.12 NAME 'memberUid' EQUALITY caseExactI
|
||||
A5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.
|
||||
26 )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.13 NAME 'memberNisNetgroup' EQUALITY ca
|
||||
seExactIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.11
|
||||
5.121.1.26 )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.14 NAME 'nisNetgroupTriple' DESC 'Netgr
|
||||
oup triple' SYNTAX 1.3.6.1.1.1.0.0 )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.15 NAME 'ipServicePort' EQUALITY intege
|
||||
rMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.16 NAME 'ipServiceProtocol' SUP name )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.17 NAME 'ipProtocolNumber' EQUALITY int
|
||||
egerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.18 NAME 'oncRpcNumber' EQUALITY integer
|
||||
Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.19 NAME 'ipHostNumber' DESC 'IP address
|
||||
' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.20 NAME 'ipNetworkNumber' DESC 'IP netw
|
||||
ork' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} SI
|
||||
NGLE-VALUE )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.21 NAME 'ipNetmaskNumber' DESC 'IP netm
|
||||
ask' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} SI
|
||||
NGLE-VALUE )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.22 NAME 'macAddress' DESC 'MAC address'
|
||||
EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128} )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.23 NAME 'bootParameter' DESC 'rpc.bootp
|
||||
aramd parameter' SYNTAX 1.3.6.1.1.1.0.1 )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.24 NAME 'bootFile' DESC 'Boot image nam
|
||||
e' EQUALITY caseExactIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.26 NAME 'nisMapName' SUP name )
|
||||
olcAttributeTypes: ( 1.3.6.1.1.1.1.27 NAME 'nisMapEntry' EQUALITY caseExac
|
||||
tIA5Match SUBSTR caseExactIA5SubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.
|
||||
1.26{1024} SINGLE-VALUE )
|
||||
olcObjectClasses: ( 1.3.6.1.1.1.2.0 NAME 'posixAccount' DESC 'Abstraction o
|
||||
f an account with POSIX attributes' SUP top AUXILIARY MUST ( cn $ uid $ uidNu
|
||||
mber $ gidNumber $ homeDirectory ) MAY ( userPassword $ loginShell $ gecos $
|
||||
description ) )
|
||||
olcObjectClasses: ( 1.3.6.1.1.1.2.1 NAME 'shadowAccount' DESC 'Additional a
|
||||
ttributes for shadow passwords' SUP top AUXILIARY MUST uid MAY ( userPassword
|
||||
$ shadowLastChange $ shadowMin $ shadowMax $ shadowWarning $ shadowInactive
|
||||
$ shadowExpire $ shadowFlag $ description ) )
|
||||
olcObjectClasses: ( 1.3.6.1.1.1.2.2 NAME 'posixGroup' DESC 'Abstraction of
|
||||
a group of accounts' SUP top STRUCTURAL MUST ( cn $ gidNumber ) MAY ( userPas
|
||||
sword $ memberUid $ description ) )
|
||||
olcObjectClasses: ( 1.3.6.1.1.1.2.3 NAME 'ipService' DESC 'Abstraction an I
|
||||
nternet Protocol service' SUP top STRUCTURAL MUST ( cn $ ipServicePort $ ipSe
|
||||
rviceProtocol ) MAY description )
|
||||
olcObjectClasses: ( 1.3.6.1.1.1.2.4 NAME 'ipProtocol' DESC 'Abstraction of
|
||||
an IP protocol' SUP top STRUCTURAL MUST ( cn $ ipProtocolNumber $ description
|
||||
) MAY description )
|
||||
olcObjectClasses: ( 1.3.6.1.1.1.2.5 NAME 'oncRpc' DESC 'Abstraction of an O
|
||||
NC/RPC binding' SUP top STRUCTURAL MUST ( cn $ oncRpcNumber $ description ) M
|
||||
AY description )
|
||||
olcObjectClasses: ( 1.3.6.1.1.1.2.6 NAME 'ipHost' DESC 'Abstraction of a ho
|
||||
st, an IP device' SUP top AUXILIARY MUST ( cn $ ipHostNumber ) MAY ( l $ desc
|
||||
ription $ manager ) )
|
||||
olcObjectClasses: ( 1.3.6.1.1.1.2.7 NAME 'ipNetwork' DESC 'Abstraction of a
|
||||
n IP network' SUP top STRUCTURAL MUST ( cn $ ipNetworkNumber ) MAY ( ipNetmas
|
||||
kNumber $ l $ description $ manager ) )
|
||||
olcObjectClasses: ( 1.3.6.1.1.1.2.8 NAME 'nisNetgroup' DESC 'Abstraction of
|
||||
a netgroup' SUP top STRUCTURAL MUST cn MAY ( nisNetgroupTriple $ memberNisNe
|
||||
tgroup $ description ) )
|
||||
olcObjectClasses: ( 1.3.6.1.1.1.2.9 NAME 'nisMap' DESC 'A generic abstracti
|
||||
on of a NIS map' SUP top STRUCTURAL MUST nisMapName MAY description )
|
||||
olcObjectClasses: ( 1.3.6.1.1.1.2.10 NAME 'nisObject' DESC 'An entry in a
|
||||
NIS map' SUP top STRUCTURAL MUST ( cn $ nisMapEntry $ nisMapName ) MAY descri
|
||||
ption )
|
||||
olcObjectClasses: ( 1.3.6.1.1.1.2.11 NAME 'ieee802Device' DESC 'A device w
|
||||
ith a MAC address' SUP top AUXILIARY MAY macAddress )
|
||||
olcObjectClasses: ( 1.3.6.1.1.1.2.12 NAME 'bootableDevice' DESC 'A device
|
||||
with boot parameters' SUP top AUXILIARY MAY ( bootFile $ bootParameter ) )
|
|
@ -0,0 +1,486 @@
|
|||
#
|
||||
# 60supann.ldif - version 389 Directory Server du schéma SupAnn version 2009.6
|
||||
#
|
||||
# (cf original à http://www.cru.fr/_media/documentation/supann/supann_2009.schema.txt)
|
||||
#
|
||||
# Modifications :
|
||||
# 21 mai 10 (JML): supannRefId : suppression du SINGLE-VALUE mis par erreur
|
||||
# 23 fevr. 10 (JML): import du fichier OpenLDAP supann_2009.schema.txt pour 389 Directory Server
|
||||
# 03 nov. 14 (BDA): ajout mailForwardingAddress
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
dn: cn=supann,cn=schema,cn=config
|
||||
objectClass: olcSchemaConfig
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.1
|
||||
NAME 'supannListeRouge'
|
||||
DESC 'indique que l entree correspondante n est pas publique'
|
||||
EQUALITY booleanMatch
|
||||
SINGLE-VALUE
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.7
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.2
|
||||
NAME 'supannActivite'
|
||||
DESC 'activite ou metier de la personne'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.3
|
||||
NAME 'supannOrganisme'
|
||||
DESC 'code organisme d appartenance'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SINGLE-VALUE
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.4
|
||||
NAME 'supannCivilite'
|
||||
DESC 'civilite : M., Mme, Mlle'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SINGLE-VALUE
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{32}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.5
|
||||
NAME 'supannAffectation'
|
||||
DESC 'affectation'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.6
|
||||
NAME 'supannCodeEntite'
|
||||
DESC 'identifiant d entite'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SINGLE-VALUE
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.7
|
||||
NAME 'supannCodeEntiteParent'
|
||||
DESC 'identifiant d entite parente'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.8
|
||||
NAME 'supannEntiteAffectation'
|
||||
DESC 'identifiant d entite d affectation'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.9
|
||||
NAME 'supannCodeINE'
|
||||
DESC 'code INE'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.44{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.10
|
||||
NAME 'supannEtuId'
|
||||
DESC 'identifiant scolarite'
|
||||
EQUALITY caseExactMatch
|
||||
SUBSTR caseExactSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.11
|
||||
NAME 'supannEmpId'
|
||||
DESC 'identifiant personnel'
|
||||
EQUALITY caseExactMatch
|
||||
SUBSTR caseExactSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.12
|
||||
NAME 'supannAutreTelephone'
|
||||
SUP telephoneNumber
|
||||
DESC 'numeros de telephone secondaires'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.50
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.13
|
||||
NAME 'supannEntiteAffectationPrincipale'
|
||||
DESC 'identifiant d entite principale d affectation'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SINGLE-VALUE
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.14
|
||||
NAME 'supannEtablissement'
|
||||
DESC 'code d etablissement'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.15
|
||||
NAME 'supannMailPerso'
|
||||
DESC 'Mailbox RFC822 privee'
|
||||
EQUALITY caseIgnoreIA5Match
|
||||
SUBSTR caseIgnoreIA5SubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.16
|
||||
NAME 'supannTypeEntite'
|
||||
DESC 'type de structure ou entite'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.17
|
||||
NAME 'supannParrainDN'
|
||||
SUP distinguishedName
|
||||
DESC 'dn du responsable de cette entree'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.18
|
||||
NAME 'supannGroupeDateFin'
|
||||
DESC 'indique la date de fin de validite de l entree correspondante'
|
||||
EQUALITY generalizedTimeMatch
|
||||
ORDERING generalizedTimeOrderingMatch
|
||||
SINGLE-VALUE
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.24
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.19
|
||||
NAME 'supannGroupeAdminDN'
|
||||
SUP distinguishedName
|
||||
DESC 'dn des administrateurs du groupe concerne'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.20
|
||||
NAME 'supannAliasLogin'
|
||||
DESC 'login personalise'
|
||||
EQUALITY caseExactMatch
|
||||
SUBSTR caseExactSubstringsMatch
|
||||
SINGLE-VALUE
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.21
|
||||
NAME 'supannRole'
|
||||
DESC 'role'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.22
|
||||
NAME 'supannGroupeLecteurDN'
|
||||
SUP distinguishedName
|
||||
DESC 'dn des entites habilite a lire le contenu d un groupe'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.12
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.23
|
||||
NAME 'supannRoleGenerique'
|
||||
DESC 'role generique d une personne'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{256}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.24
|
||||
NAME 'supannRoleEntite'
|
||||
DESC 'role contextuel'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{512}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.25
|
||||
NAME 'supannEtuAnneeInscription'
|
||||
DESC 'annee inscription'
|
||||
EQUALITY numericStringMatch
|
||||
ORDERING numericStringOrderingMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.36{4}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.26
|
||||
NAME 'supannEtuCursusAnnee'
|
||||
DESC 'cursus et annee dans le diplome'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.27
|
||||
NAME 'supannEtuDiplome'
|
||||
DESC 'diplome'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.28
|
||||
NAME 'supannEtuElementPedagogique'
|
||||
DESC 'element pedagogique'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.29
|
||||
NAME 'supannEtuEtape'
|
||||
DESC 'etape'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: ( 1.3.6.1.4.1.7135.1.2.1.30
|
||||
NAME 'supannEtuInscription'
|
||||
DESC 'description d inscriptions'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{4096}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.31
|
||||
NAME 'supannEtuRegimeInscription'
|
||||
DESC 'regime d inscription'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.32
|
||||
NAME 'supannEtuSecteurDisciplinaire'
|
||||
DESC 'secteur disciplinaire'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.33
|
||||
NAME 'supannEtuTypeDiplome'
|
||||
DESC 'type de diplome'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.34
|
||||
NAME 'supannAutreMail'
|
||||
SUP mail
|
||||
DESC 'adresses mail non institutionnelles'
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.26{256}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.35
|
||||
NAME 'supannEmpCorps'
|
||||
DESC 'corps d appartenance d un agent'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.36
|
||||
NAME 'supannTypeEntiteAffectation'
|
||||
DESC 'type de structure ou entite d affectation'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SUBSTR caseIgnoreSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcAttributeTypes: (
|
||||
1.3.6.1.4.1.7135.1.2.1.37
|
||||
NAME 'supannRefId'
|
||||
DESC 'identifiant partage avec autre brique du SI'
|
||||
EQUALITY caseExactMatch
|
||||
SUBSTR caseExactSubstringsMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{128}
|
||||
)
|
||||
# repris du schema Netscape (enlever si conflit) :
|
||||
olcAttributeTypes: ( 2.16.840.1.113730.3.1.17
|
||||
NAME 'mailForwardingAddress'
|
||||
DESC 'coin'
|
||||
EQUALITY caseIgnoreMatch
|
||||
SYNTAX 1.3.6.1.4.1.1466.115.121.1.15
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcObjectClasses: (
|
||||
1.3.6.1.4.1.7135.1.2.2.1
|
||||
NAME 'supannPerson'
|
||||
SUP top AUXILIARY
|
||||
DESC 'classe d infos complementaires sur personnes supann'
|
||||
MAY ( supannOrganisme $ supannCivilite $ supannAutreTelephone $ supannAffectation $ supannEmpId $ supannCodeINE $ supannEtuId $ supannAliasLogin $ supannParrainDN $ supannActivite $ supannEntiteAffectation $ supannEntiteAffectationPrincipale $ supannMailPerso $ supannRole $ supannRoleEntite $ supannRoleGenerique $ supannEtuAnneeInscription $ supannEtuCursusAnnee $ supannEtuDiplome $ supannEtuElementPedagogique $ supannEtuEtape $ supannEtuInscription $ supannEtuRegimeInscription $ supannEtuSecteurDisciplinaire $ supannEtuTypeDiplome $ supannEtablissement $ supannListeRouge $ supannAutreMail $ mailForwardingAddress $ supannEmpCorps $ supannTypeEntiteAffectation $ supannRefId )
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcObjectClasses: (
|
||||
1.3.6.1.4.1.7135.1.2.2.2
|
||||
NAME 'supannOrg'
|
||||
SUP top AUXILIARY
|
||||
DESC 'classe d infos complementaires pour etablissement'
|
||||
MAY ( supannEtablissement )
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcObjectClasses: (
|
||||
1.3.6.1.4.1.7135.1.2.2.3
|
||||
NAME 'supannEntite'
|
||||
SUP top AUXILIARY
|
||||
DESC 'classe d infos complementaires pour entite'
|
||||
MUST ( supannCodeEntite )
|
||||
MAY ( supannTypeEntite $ supannCodeEntiteParent $ supannRefId )
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
#objectClasses: (
|
||||
# 1.3.6.1.4.1.7135.1.2.2.4
|
||||
# NAME 'entree disponible'
|
||||
# )
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
#objectClasses: (
|
||||
# 1.3.6.1.4.1.7135.1.2.2.5
|
||||
# NAME 'entree disponible'
|
||||
# )
|
||||
#
|
||||
################################################################################
|
||||
#
|
||||
olcObjectClasses: (
|
||||
1.3.6.1.4.1.7135.1.2.2.6
|
||||
NAME 'supannGroupe'
|
||||
SUP top AUXILIARY
|
||||
DESC 'attributs specifiques des groupes'
|
||||
MAY ( supannGroupeDateFin $ supannGroupeAdminDN $ supannGroupeLecteurDN $ supannRefId )
|
||||
)
|
||||
#
|
||||
################################################################################
|
||||
#
|
|
@ -0,0 +1,237 @@
|
|||
import time
|
||||
import tempfile
|
||||
import shutil
|
||||
import subprocess
|
||||
import os
|
||||
import ldap
|
||||
import ldap.modlist
|
||||
import ldap.sasl
|
||||
import StringIO
|
||||
import atexit
|
||||
|
||||
from ldaptools.ldif_utils import ListLDIFParser
|
||||
from ldaptools.paged import PagedLDAPObject
|
||||
|
||||
SLAPD_PATH = None
|
||||
SLAPADD_PATH = None
|
||||
SLAPD_PATHS = ['/bin', '/usr/bin', '/sbin', '/usr/sbin', '/usr/local/bin', '/usr/local/sbin']
|
||||
|
||||
|
||||
def has_slapd():
|
||||
global SLAPD_PATH, SLAPADD_PATH, PATHS
|
||||
if not SLAPD_PATH or not SLAPADD_PATH:
|
||||
for path in SLAPD_PATHS:
|
||||
slapd_path = os.path.join(path, 'slapd')
|
||||
if os.path.exists(slapd_path):
|
||||
SLAPD_PATH = slapd_path
|
||||
slapadd_path = os.path.join(path, 'slapadd')
|
||||
if os.path.exists(slapd_path):
|
||||
SLAPADD_PATH = slapadd_path
|
||||
return not (SLAPD_PATH is None or SLAPADD_PATH is None)
|
||||
|
||||
|
||||
class Slapd(object):
|
||||
'''Initiliaze an OpenLDAP server with just one database containing branch
|
||||
o=orga and loading the core schema. ACL are very permissive.
|
||||
'''
|
||||
root_bind_dn = 'uid=admin,cn=config'
|
||||
root_bind_password = 'admin'
|
||||
|
||||
config_ldif = '''dn: cn=config
|
||||
objectClass: olcGlobal
|
||||
cn: config
|
||||
olcToolThreads: 1
|
||||
olcLogLevel: stats
|
||||
olcLogFile: {slapd_dir}/log
|
||||
|
||||
dn: cn=module{{0}},cn=config
|
||||
objectClass: olcModuleList
|
||||
cn: module{{0}}
|
||||
olcModulePath: /usr/lib/ldap
|
||||
olcModuleLoad: {{0}}back_hdb
|
||||
olcModuleLoad: {{1}}back_monitor
|
||||
olcModuleLoad: {{2}}back_mdb
|
||||
olcModuleLoad: {{3}}accesslog
|
||||
olcModuleLoad: {{4}}unique
|
||||
olcModuleLoad: {{5}}refint
|
||||
olcModuleLoad: {{6}}constraint
|
||||
olcModuleLoad: {{7}}syncprov
|
||||
|
||||
dn: cn=schema,cn=config
|
||||
objectClass: olcSchemaConfig
|
||||
cn: schema
|
||||
|
||||
dn: olcDatabase={{-1}}frontend,cn=config
|
||||
objectClass: olcDatabaseConfig
|
||||
objectClass: olcFrontendConfig
|
||||
olcDatabase: {{-1}}frontend
|
||||
olcAccess: {{0}}to *
|
||||
by dn.exact=gidNumber={gid}+uidNumber={uid},cn=peercred,cn=external,cn=auth manage
|
||||
by * break
|
||||
olcAccess: {{1}}to dn.exact="" by * read
|
||||
olcAccess: {{2}}to dn.base="cn=Subschema" by * read
|
||||
olcSizeLimit: unlimited
|
||||
olcTimeLimit: unlimited
|
||||
|
||||
dn: olcDatabase={{0}}config,cn=config
|
||||
objectClass: olcDatabaseConfig
|
||||
olcDatabase: {{0}}config
|
||||
olcRootDN: uid=admin,cn=config
|
||||
olcRootPW: admin
|
||||
olcAccess: {{0}}to *
|
||||
by dn.exact=gidNumber={gid}+uidNumber={uid},cn=peercred,cn=external,cn=auth manage
|
||||
by * break
|
||||
'''
|
||||
process = None
|
||||
schemas = ['core', 'cosine', 'inetorgperson', 'nis', 'eduorg-200210-openldap', 'eduperson',
|
||||
'supann-2009']
|
||||
schemas_ldif = [open(os.path.join(os.path.dirname(__file__),
|
||||
'schemas', '%s.ldif' % schema)).read() for schema in schemas]
|
||||
checkpoints = None
|
||||
data_dirs = None
|
||||
|
||||
def create_process(self, args):
|
||||
return subprocess.Popen(args, stdin=subprocess.PIPE, env=os.environ, stdout=subprocess.PIPE,
|
||||
stderr=subprocess.PIPE)
|
||||
|
||||
def __init__(self, ldap_url=None):
|
||||
assert has_slapd()
|
||||
self.checkpoints = []
|
||||
self.data_dirs = []
|
||||
self.slapd_dir = tempfile.mkdtemp(prefix='a2-provision-slapd')
|
||||
self.config_dir = os.path.join(self.slapd_dir, 'slapd.d')
|
||||
os.mkdir(self.config_dir)
|
||||
self.socket = os.path.join(self.slapd_dir, 'socket')
|
||||
if not ldap_url:
|
||||
ldap_url = 'ldapi://%s' % self.socket.replace('/', '%2F')
|
||||
self.ldap_url = ldap_url
|
||||
self.slapadd(self.config_ldif, context={'slapd_dir': self.slapd_dir, 'gid': os.getgid(),
|
||||
'uid': os.getuid()})
|
||||
for schema_ldif in self.schemas_ldif:
|
||||
self.slapadd(schema_ldif)
|
||||
self.start()
|
||||
self.add_db('o=orga')
|
||||
ldif = '''dn: o=orga
|
||||
objectClass: organization
|
||||
o: orga'''
|
||||
self.add_ldif(ldif)
|
||||
|
||||
def add_db(self, suffix):
|
||||
path = os.path.join(self.slapd_dir, suffix)
|
||||
os.mkdir(path)
|
||||
ldif = '''dn: olcDatabase=mdb,cn=config
|
||||
objectClass: olcDatabaseConfig
|
||||
objectClass: olcMdbConfig
|
||||
olcDatabase: mdb
|
||||
olcSuffix: {suffix}
|
||||
olcDbDirectory: {path}
|
||||
olcReadOnly: FALSE
|
||||
# Index
|
||||
olcAccess: {{0}}to * by manage'''
|
||||
self.add_ldif(ldif, context={'suffix': suffix, 'path': path})
|
||||
self.data_dirs.append(path)
|
||||
|
||||
def slapadd(self, ldif, context=None):
|
||||
assert not self.process
|
||||
|
||||
if context:
|
||||
ldif = ldif.format(**context)
|
||||
slapadd = self.create_process([SLAPADD_PATH, '-v', '-n0', '-F', self.config_dir])
|
||||
stdout, stderr = slapadd.communicate(input=ldif)
|
||||
assert slapadd.returncode == 0, 'slapadd failed: %s' % stderr
|
||||
|
||||
def start(self):
|
||||
'''Launch slapd'''
|
||||
assert not self.process
|
||||
|
||||
cmd = [SLAPD_PATH,
|
||||
'-d768', # put slapd in foreground
|
||||
'-F' + self.config_dir,
|
||||
'-h', self.ldap_url]
|
||||
self.process = self.create_process(cmd)
|
||||
atexit.register(self.clean)
|
||||
|
||||
while True:
|
||||
try:
|
||||
conn = self.get_connection()
|
||||
conn.whoami_s()
|
||||
except ldap.SERVER_DOWN:
|
||||
time.sleep(0.1)
|
||||
else:
|
||||
break
|
||||
|
||||
def stop(self):
|
||||
'''Send SIGTERM to slapd'''
|
||||
assert self.process
|
||||
|
||||
process = self.process
|
||||
self.process = None
|
||||
process.kill()
|
||||
|
||||
def checkpoint(self):
|
||||
'''Stop slapd and save current data state'''
|
||||
assert not self.process
|
||||
|
||||
self.checkpoints.append(
|
||||
os.path.join(self.slapd_dir, 'checkpoint-%d' % len(self.checkpoints)))
|
||||
for data_dir in self.data_dirs:
|
||||
dirname = os.path.basename(data_dir)
|
||||
target = os.path.join(self.checkpoints[-1], dirname)
|
||||
shutil.copytree(data_dir, target)
|
||||
|
||||
def restore(self):
|
||||
'''Stop slapd and restore last data state'''
|
||||
assert not self.process
|
||||
assert self.checkpoints, 'no checkpoint exists'
|
||||
for data_dir in self.data_dirs:
|
||||
dirname = os.path.basename(data_dir)
|
||||
shutil.rmtree(data_dir)
|
||||
shutil.copytree(os.path.join(self.checkpoints[-1], dirname), data_dir)
|
||||
shutil.rmtree(self.checkpoints[-1])
|
||||
self.checkpoints.pop()
|
||||
|
||||
# Clean behind us
|
||||
def __del__(self):
|
||||
self.clean()
|
||||
|
||||
def clean(self):
|
||||
'''Remove directory'''
|
||||
if self.slapd_dir:
|
||||
if os.path.exists(self.slapd_dir):
|
||||
shutil.rmtree(self.slapd_dir, ignore_errors=True)
|
||||
self.slapd_dir = None
|
||||
if self.process:
|
||||
self.stop()
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, type, value, tb):
|
||||
self.clean()
|
||||
|
||||
def add_ldif(self, ldif, context=None):
|
||||
assert self.process
|
||||
|
||||
if context:
|
||||
ldif = ldif.format(**context)
|
||||
parser = ListLDIFParser(StringIO.StringIO(ldif))
|
||||
parser.parse()
|
||||
conn = self.get_connection_admin()
|
||||
parser.add(conn)
|
||||
|
||||
def get_connection(self):
|
||||
assert self.process
|
||||
|
||||
return PagedLDAPObject(self.ldap_url)
|
||||
|
||||
def get_connection_admin(self):
|
||||
conn = self.get_connection()
|
||||
conn.simple_bind_s(self.root_bind_dn, self.root_bind_password)
|
||||
return conn
|
||||
|
||||
def get_connection_external(self):
|
||||
assert self.ldap_url.startswith('ldapi://')
|
||||
|
||||
conn = self.get_connection()
|
||||
conn.sasl_interactive_bind_s("", ldap.sasl.external())
|
||||
return conn
|
|
@ -0,0 +1,260 @@
|
|||
import logging
|
||||
import functools
|
||||
from itertools import groupby
|
||||
|
||||
import ldap
|
||||
from ldap.filter import filter_format
|
||||
import ldap.modlist
|
||||
import ldap.dn
|
||||
|
||||
|
||||
from .utils import batch_generator, to_dict_of_set, idict, str2dn, istr
|
||||
|
||||
|
||||
@functools.total_ordering
|
||||
class Action(object):
|
||||
dn = None
|
||||
new_dn = None
|
||||
entry = None
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.__dict__.update(kwargs)
|
||||
self.msgids = []
|
||||
self.errors = []
|
||||
self.results = []
|
||||
|
||||
def __eq__(self, other):
|
||||
return (other.__class__ is self.__class__ and self.dn == other.dn and other.new_dn ==
|
||||
other.new_dn and to_dict_of_set(self.entry) == to_dict_of_set(other.entry))
|
||||
|
||||
# - first rename, sorted by dn depth
|
||||
# - then update and creations, sorted by depth
|
||||
# - the deletions sorted by reverse of depth
|
||||
def __lt__(self, other):
|
||||
if self.order == other.order:
|
||||
n = len(str2dn(self.dn))
|
||||
m = len(str2dn(other.dn))
|
||||
if self.order == 4: # Delete should be done from leaves to root
|
||||
return m < n
|
||||
else:
|
||||
return n < m # Other operations must be donne from root to leaves
|
||||
else:
|
||||
return self.order < other.order
|
||||
|
||||
def do(self, conn):
|
||||
pass
|
||||
|
||||
def collect_result(self, conn):
|
||||
for msgid in self.msgids:
|
||||
try:
|
||||
self.results.append(conn.result2(msgid))
|
||||
except ldap.LDAPError, e:
|
||||
self.errors.append(e)
|
||||
|
||||
def __str__(self):
|
||||
s = '<%s dn: %s' % (self.__class__.__name__, self.dn)
|
||||
if self.entry:
|
||||
s += ' entry: %s' % self.entry
|
||||
if self.new_dn:
|
||||
s += ' new_dn: %s' % self.new_dn
|
||||
return s
|
||||
|
||||
|
||||
class Create(Action):
|
||||
order = 3
|
||||
|
||||
def do(self, conn):
|
||||
self.msgids.append(conn.add(self.dn, ldap.modlist.addModlist(self.entry)))
|
||||
|
||||
|
||||
class Rename(Action):
|
||||
order = 1
|
||||
|
||||
def do(self, conn):
|
||||
old_dn = str2dn(self.dn)
|
||||
new_dn = str2dn(self.new_dn)
|
||||
new_rdn = ldap.dn.dn2str(new_dn[:1])
|
||||
newsuperior = None
|
||||
if old_dn[1:] != new_dn[1:]:
|
||||
newsuperior = ldap.dn.dn2str(new_dn[1:])
|
||||
self.msgids.append(conn.rename(self.dn, new_rdn, newsuperior=newsuperior, delold=0))
|
||||
|
||||
|
||||
class Update(Action):
|
||||
order = 2
|
||||
|
||||
def do(self, conn):
|
||||
modlist = []
|
||||
for key, values in self.entry.iteritems():
|
||||
modlist.append((ldap.MOD_REPLACE, key, values))
|
||||
self.msgids.append(conn.modify(self.dn, modlist))
|
||||
|
||||
|
||||
class Delete(Action):
|
||||
order = 4
|
||||
|
||||
def do(self, conn):
|
||||
self.msgids.append(conn.delete(self.dn))
|
||||
|
||||
|
||||
class Synchronize(object):
|
||||
'''Synchronize a source or records with an LDAP server'''
|
||||
BATCH_SIZE = 100
|
||||
|
||||
# an iterable yield pair of (dn, attributes)
|
||||
source = None
|
||||
# an LDAP connection as provided by python-ldap
|
||||
target_conn = None
|
||||
|
||||
# list or pairs, objectclass -> attribute
|
||||
pivot_attributes = []
|
||||
|
||||
# attributes
|
||||
attributes = []
|
||||
|
||||
# actions
|
||||
CREATE = 1
|
||||
UPDATE = 2
|
||||
RENAME = 3
|
||||
DELETE = 4
|
||||
|
||||
all_filter = '(objectclass=*)'
|
||||
|
||||
# actions
|
||||
actions = None
|
||||
|
||||
def __init__(self, source, source_dn, target_conn, target_dn, attributes=None, all_filter=None,
|
||||
pivot_attributes=None, logger=None):
|
||||
self.source = source
|
||||
self.source_dn = source_dn
|
||||
self.target_conn = target_conn
|
||||
self.target_dn = target_dn
|
||||
self.attributes = attributes or self.attributes
|
||||
self.all_filter = all_filter or self.all_filter
|
||||
self.pivot_attributes = pivot_attributes or self.pivot_attributes
|
||||
self.logger = logger or logging.getLogger(__name__)
|
||||
self.errors = []
|
||||
|
||||
def massage_dn(self, old_dn):
|
||||
return old_dn[:-len(self.source_dn)] + self.target_dn
|
||||
|
||||
def get_pivot_attribute(self, entry):
|
||||
'''Find a pivot attribute value for an LDAP entry'''
|
||||
for objc, attr in self.pivot_attributes:
|
||||
entry['objectclass'] = map(istr, entry['objectclass'])
|
||||
if objc in entry['objectclass']:
|
||||
try:
|
||||
value = entry[attr]
|
||||
except KeyError:
|
||||
raise Exception('entry missing pivot attribute %s: %s' % (attr, entry))
|
||||
break
|
||||
else:
|
||||
raise Exception('entry has unknown objectclasses %s' % entry['objectclass'])
|
||||
if len(value) != 1:
|
||||
raise Exception('entry pivot attribute %s must have only one value' % attr)
|
||||
return objc, attr, value[0]
|
||||
|
||||
def get_target_entries(self, filterstr=None, attributes=[]):
|
||||
'''Return all target entries'''
|
||||
l = self.target_conn.paged_search_ext_s(self.target_dn, ldap.SCOPE_SUBTREE,
|
||||
filterstr=filterstr or self.all_filter,
|
||||
attrlist=attributes)
|
||||
return ((dn, idict(entry)) for dn, entry in l if dn)
|
||||
|
||||
def build_actions_for_entries(self, entries):
|
||||
seen_dn = self.seen_dn
|
||||
renamed_dn = self.renamed_dn
|
||||
in_dns = []
|
||||
out_filters = []
|
||||
# Transform input entries into filters
|
||||
for dn, entry in entries:
|
||||
objectclass, attr, value = self.get_pivot_attribute(entry)
|
||||
in_dns.append(((attr, value), (dn, entry)))
|
||||
filter_tpl = '(&(objectclass=%%s)(%s=%%s))' % attr
|
||||
out_filters.append(
|
||||
filter_format(filter_tpl, (objectclass, value)))
|
||||
out_filter = '(|%s)' % ''.join(out_filters)
|
||||
# Get existing output entries
|
||||
out_dns = {}
|
||||
for dn, entry in self.get_target_entries(filterstr=out_filter, attributes=self.attributes):
|
||||
objectclass, attr, value = self.get_pivot_attribute(entry)
|
||||
out_dns[(attr, value)] = dn, entry
|
||||
for pivot, (source_dn, entry) in in_dns:
|
||||
target_dn = self.massage_dn(source_dn)
|
||||
seen_dn.add(target_dn)
|
||||
if pivot in out_dns:
|
||||
out_dn, out_entry = out_dns[pivot]
|
||||
# translate dn to dn after all previous renames
|
||||
out_ava = str2dn(out_dn)
|
||||
rename = True
|
||||
while rename:
|
||||
rename = False
|
||||
for i in range(len(out_ava) - 1, 0, -1):
|
||||
print 'looking for rewrite of', out_ava[i:]
|
||||
if out_ava[i:] in renamed_dn:
|
||||
# rewrite suffix if it has been renamed
|
||||
out_ava = out_ava[:i] + renamed_dn[out_ava[i:]]
|
||||
print 'found, renaming to', out_ava
|
||||
rename = True
|
||||
break
|
||||
new_out_dn = ldap.dn.dn2str(out_ava)
|
||||
if new_out_dn != target_dn:
|
||||
seen_dn.add(out_dn)
|
||||
self.rename(new_out_dn, target_dn)
|
||||
print 'rename', new_out_dn, target_dn
|
||||
renamed_dn[str2dn(new_out_dn)] = str2dn(target_dn)
|
||||
if to_dict_of_set(out_entry) != to_dict_of_set(entry):
|
||||
new_entry = {}
|
||||
for attribute in self.attributes:
|
||||
new_entry[attribute] = entry.get(attribute, [])
|
||||
self.update(target_dn, new_entry)
|
||||
else:
|
||||
self.create(target_dn, entry)
|
||||
|
||||
def build_actions(self):
|
||||
self.seen_dn = set()
|
||||
self.renamed_dn = {}
|
||||
self.actions = []
|
||||
# Order source entries by DN depth
|
||||
entries = list(self.source)
|
||||
entries.sort(key=lambda (dn, entry): len(str2dn(dn)))
|
||||
# First create, rename and update
|
||||
for batch in batch_generator(entries, self.BATCH_SIZE):
|
||||
self.build_actions_for_entries(batch)
|
||||
# Then delete
|
||||
for dn, entry in self.get_target_entries():
|
||||
if dn not in self.seen_dn:
|
||||
self.delete(dn)
|
||||
# Now sort actions by their special order
|
||||
self.actions.sort()
|
||||
|
||||
def create(self, dn, entry):
|
||||
self.actions.append(Create(dn=dn, entry=entry))
|
||||
|
||||
def rename(self, old_dn, new_dn):
|
||||
self.actions.append(Rename(dn=old_dn, new_dn=new_dn))
|
||||
|
||||
def update(self, dn, entry):
|
||||
self.actions.append(Update(dn=dn, entry=entry))
|
||||
|
||||
def delete(self, dn):
|
||||
self.actions.append(Delete(dn=dn))
|
||||
|
||||
def apply_actions(self):
|
||||
'''Apply actions, wait for result of different kind of actions
|
||||
separately, since openldap seem to reorder some of them'''
|
||||
|
||||
def action_key(action):
|
||||
return (action.__class__, str2dn(action.dn))
|
||||
for key, sequence in groupby(self.actions, action_key):
|
||||
for batch in batch_generator(sequence, self.BATCH_SIZE):
|
||||
for action in batch:
|
||||
action.do(self.target_conn)
|
||||
self.logger.debug('applying %s', action)
|
||||
self.logger.debug('waiting for completion of %d actions', len(batch))
|
||||
for action in batch:
|
||||
action.collect_result(self.target_conn)
|
||||
|
||||
def run(self):
|
||||
self.build_actions()
|
||||
self.apply_actions()
|
|
@ -0,0 +1,223 @@
|
|||
import ldap.dn
|
||||
|
||||
|
||||
# Copied from http://code.activestate.com/recipes/194371-case-insensitive-strings/
|
||||
class istr(str):
|
||||
"""Case insensitive strings class.
|
||||
Performs like str except comparisons are case insensitive."""
|
||||
|
||||
def __init__(self, strMe):
|
||||
str.__init__(self, strMe)
|
||||
self.__lowerCaseMe = strMe.lower()
|
||||
|
||||
def __repr__(self):
|
||||
return "iStr(%s)" % str.__repr__(self)
|
||||
|
||||
def __eq__(self, other):
|
||||
if not hasattr(other, 'lower'):
|
||||
return False
|
||||
return self.__lowerCaseMe == other.lower()
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.__lowerCaseMe < other.lower()
|
||||
|
||||
def __le__(self, other):
|
||||
return self.__lowerCaseMe <= other.lower()
|
||||
|
||||
def __gt__(self, other):
|
||||
return self.__lowerCaseMe > other.lower()
|
||||
|
||||
def __ne__(self, other):
|
||||
if not hasattr(other, 'lower'):
|
||||
return True
|
||||
return self.__lowerCaseMe != other.lower()
|
||||
|
||||
def __ge__(self, other):
|
||||
return self.__lowerCaseMe >= other.lower()
|
||||
|
||||
def __cmp__(self, other):
|
||||
return cmp(self.__lowerCaseMe, other.lower())
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.__lowerCaseMe)
|
||||
|
||||
def __contains__(self, other):
|
||||
return other.lower() in self.__lowerCaseMe
|
||||
|
||||
def count(self, other, *args):
|
||||
return str.count(self.__lowerCaseMe, other.lower(), *args)
|
||||
|
||||
def endswith(self, other, *args):
|
||||
return str.endswith(self.__lowerCaseMe, other.lower(), *args)
|
||||
|
||||
def find(self, other, *args):
|
||||
return str.find(self.__lowerCaseMe, other.lower(), *args)
|
||||
|
||||
def index(self, other, *args):
|
||||
return str.index(self.__lowerCaseMe, other.lower(), *args)
|
||||
|
||||
def lower(self): # Courtesy Duncan Booth
|
||||
return self.__lowerCaseMe
|
||||
|
||||
def rfind(self, other, *args):
|
||||
return str.rfind(self.__lowerCaseMe, other.lower(), *args)
|
||||
|
||||
def rindex(self, other, *args):
|
||||
return str.rindex(self.__lowerCaseMe, other.lower(), *args)
|
||||
|
||||
def startswith(self, other, *args):
|
||||
return str.startswith(self.__lowerCaseMe, other.lower(), *args)
|
||||
|
||||
|
||||
class idict(dict):
|
||||
"""A case insensitive dictionary that only permits strings as keys."""
|
||||
def __init__(self, indict={}):
|
||||
dict.__init__(self)
|
||||
self._keydict = {} # not self.__keydict because I want it to be easily accessible by subclasses
|
||||
for entry in indict:
|
||||
self[entry] = indict[entry] # not dict.__setitem__(self, entry, indict[entry]) becasue this causes errors (phantom entries) where indict has overlapping keys
|
||||
|
||||
def findkey(self, item):
|
||||
"""A caseless way of checking if a key exists or not.
|
||||
It returns None or the correct key."""
|
||||
if not isinstance(item, str):
|
||||
raise TypeError('Keywords for this object must be strings. You supplied %s' % type(item))
|
||||
key = item.lower()
|
||||
try:
|
||||
return self._keydict[key]
|
||||
except:
|
||||
return None
|
||||
|
||||
def changekey(self, item):
|
||||
"""For changing the casing of a key.
|
||||
If a key exists that is a caseless match for 'item' it will be changed to 'item'.
|
||||
This is useful when initially setting up default keys - but later might want to preserve an alternative casing.
|
||||
(e.g. if later read from a config file - and you might want to write back out with the user's casing preserved).
|
||||
"""
|
||||
key = self.findkey(item) # does the key exist
|
||||
if key is None:
|
||||
raise KeyError(item)
|
||||
temp = self[key]
|
||||
del self[key]
|
||||
self[item] = temp
|
||||
self._keydict[item.lower()] = item
|
||||
|
||||
def lowerkeys(self):
|
||||
"""Returns a lowercase list of all member keywords."""
|
||||
return self._keydict.keys()
|
||||
|
||||
def __setitem__(self, item, value): # setting a keyword
|
||||
"""To implement lowercase keys."""
|
||||
key = self.findkey(item) # if the key already exists
|
||||
if key is not None:
|
||||
dict.__delitem__(self, key)
|
||||
self._keydict[item.lower()] = item
|
||||
dict.__setitem__(self, item, value)
|
||||
|
||||
def __getitem__(self, item):
|
||||
"""To implement lowercase keys."""
|
||||
key = self.findkey(item) # does the key exist
|
||||
if key is None:
|
||||
raise KeyError(item)
|
||||
return dict.__getitem__(self, key)
|
||||
|
||||
def __delitem__(self, item): # deleting a keyword
|
||||
key = self.findkey(item) # does the key exist
|
||||
if key is None:
|
||||
raise KeyError(item)
|
||||
dict.__delitem__(self, key)
|
||||
del self._keydict[item.lower()]
|
||||
|
||||
def pop(self, item, default=None):
|
||||
"""Correctly emulates the pop method."""
|
||||
key = self.findkey(item) # does the key exist
|
||||
if key is None:
|
||||
if default is None:
|
||||
raise KeyError(item)
|
||||
else:
|
||||
return default
|
||||
del self._keydict[item.lower()]
|
||||
return dict.pop(self, key)
|
||||
|
||||
def popitem(self):
|
||||
"""Correctly emulates the popitem method."""
|
||||
popped = dict.popitem(self)
|
||||
del self._keydict[popped[0].lower()]
|
||||
return popped
|
||||
|
||||
def has_key(self, item):
|
||||
"""A case insensitive test for keys."""
|
||||
if not isinstance(item, str):
|
||||
return False # should never have a non-string key
|
||||
return item.lower() in self._keydict # does the key exist
|
||||
|
||||
def __contains__(self, item):
|
||||
"""A case insensitive __contains__."""
|
||||
if not isinstance(item, str):
|
||||
return False # should never have a non-string key
|
||||
return item.lower() in self._keydict # does the key exist
|
||||
|
||||
def setdefault(self, item, default=None):
|
||||
"""A case insensitive setdefault.
|
||||
If no default is supplied it sets the item to None"""
|
||||
key = self.findkey(item) # does the key exist
|
||||
if key is not None:
|
||||
return self[key]
|
||||
self.__setitem__(item, default)
|
||||
self._keydict[item.lower()] = item
|
||||
return default
|
||||
|
||||
def get(self, item, default=None):
|
||||
"""A case insensitive get."""
|
||||
key = self.findkey(item) # does the key exist
|
||||
if key is not None:
|
||||
return self[key]
|
||||
return default
|
||||
|
||||
def update(self, indict):
|
||||
"""A case insensitive update.
|
||||
If your dictionary has overlapping keys (e.g. 'FISH' and 'fish') then one will overwrite the other.
|
||||
The one that is kept is arbitrary."""
|
||||
for entry in indict:
|
||||
self[entry] = indict[entry] # this uses the new __setitem__ method
|
||||
|
||||
def copy(self):
|
||||
"""Create a new caselessDict object that is a copy of this one."""
|
||||
return idict(self)
|
||||
|
||||
def dict(self):
|
||||
"""Create a dictionary version of this caselessDict."""
|
||||
return dict.copy(self)
|
||||
|
||||
def clear(self):
|
||||
"""Clear this caselessDict."""
|
||||
self._keydict = {}
|
||||
dict.clear(self)
|
||||
|
||||
def __repr__(self):
|
||||
"""A caselessDict version of __repr__ """
|
||||
return 'caselessDict(' + dict.__repr__(self) + ')'
|
||||
|
||||
|
||||
def batch_generator(gen, *batch_size):
|
||||
batch = []
|
||||
for result in gen:
|
||||
batch.append(result)
|
||||
if len(batch) == batch_size[0]:
|
||||
yield batch
|
||||
batch = []
|
||||
if len(batch_size) > 1:
|
||||
batch_size = batch_size[1:]
|
||||
if len(batch):
|
||||
yield batch
|
||||
|
||||
|
||||
def to_dict_of_set(d):
|
||||
r = idict({k: set(v) for k, v in d.iteritems()})
|
||||
if 'objectclass' in r:
|
||||
r['objectclass'] = set(istr(v) for v in r['objectclass'])
|
||||
return r
|
||||
|
||||
|
||||
def str2dn(s):
|
||||
return tuple(map(tuple, ldap.dn.str2dn(s)))
|
|
@ -0,0 +1,75 @@
|
|||
import pytest
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
from ldaptools.slapd import Slapd
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def slapd(request):
|
||||
return Slapd(ldap_url=getattr(request, 'param', None))
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def slapd_tcp1(request):
|
||||
return Slapd(ldap_url='ldap://localhost:3389')
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def slapd_tcp2(request):
|
||||
return Slapd(ldap_url='ldap://localhost:4389')
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def ldif():
|
||||
return '''dn: dc=orga2
|
||||
o: orga
|
||||
dc: orga2
|
||||
objectClass: organization
|
||||
objectClass: dcObject
|
||||
|
||||
dn: uid=admin,dc=orga2
|
||||
objectClass: inetOrgPerson
|
||||
cn: John Doe
|
||||
uid: admin
|
||||
sn: John
|
||||
givenName: Doe
|
||||
mail: john.doe@entrouvert.com'''
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def attributes():
|
||||
return ['o', 'objectClass', 'uid', 'sn', 'givenName', 'mail', 'dc', 'cn']
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def pivot_attributes():
|
||||
return (
|
||||
('organization', 'o'),
|
||||
('inetOrgPerson', 'uid'),
|
||||
)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def ldif_path(request, ldif):
|
||||
handle, path = tempfile.mkstemp()
|
||||
with open(path, 'w') as f:
|
||||
f.write(ldif)
|
||||
f.flush()
|
||||
def finalize():
|
||||
os.unlink(path)
|
||||
request.addfinalizer(finalize)
|
||||
return path
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def attributes_path(request, attributes):
|
||||
handle, path = tempfile.mkstemp()
|
||||
with open(path, 'w') as f:
|
||||
for attribute in attributes:
|
||||
print >>f, ' %s ' % attribute
|
||||
f.flush()
|
||||
def finalize():
|
||||
os.unlink(path)
|
||||
request.addfinalizer(finalize)
|
||||
return path
|
|
@ -0,0 +1,70 @@
|
|||
import pytest
|
||||
import ldap
|
||||
|
||||
from ldaptools.ldapsync.cmd import main
|
||||
|
||||
|
||||
|
||||
def test_ldapsync_ldif_to_ldapi(slapd, ldif_path, attributes, pivot_attributes):
|
||||
args = [
|
||||
'--source-uri', ldif_path,
|
||||
'--source-base-dn', 'dc=orga2',
|
||||
'--target-uri', slapd.ldap_url,
|
||||
'--target-base-dn', 'o=orga',
|
||||
'--attributes', ' '.join(attributes),
|
||||
'--verbose',
|
||||
]
|
||||
for object_class, pivot_attribute in pivot_attributes:
|
||||
args += ['--object-class-pivot', '%s %s' % (object_class, pivot_attribute)]
|
||||
main(args)
|
||||
main(args)
|
||||
conn = slapd.get_connection()
|
||||
assert len(conn.search_s('o=orga', ldap.SCOPE_SUBTREE)) == 2
|
||||
assert set([dn for dn, entry in conn.search_s('o=orga', ldap.SCOPE_SUBTREE)]) == set(['o=orga',
|
||||
'uid=admin,o=orga'])
|
||||
|
||||
|
||||
def test_ldapsync_ldif_to_ldapi_attributes_file(slapd, ldif_path, attributes_path, pivot_attributes):
|
||||
args = [
|
||||
'--source-uri', ldif_path,
|
||||
'--source-base-dn', 'dc=orga2',
|
||||
'--target-uri', slapd.ldap_url,
|
||||
'--target-base-dn', 'o=orga',
|
||||
'--attributes-file', attributes_path,
|
||||
'--verbose',
|
||||
]
|
||||
for object_class, pivot_attribute in pivot_attributes:
|
||||
args += ['--object-class-pivot', '%s %s' % (object_class, pivot_attribute)]
|
||||
main(args)
|
||||
main(args)
|
||||
conn = slapd.get_connection()
|
||||
assert len(conn.search_s('o=orga', ldap.SCOPE_SUBTREE)) == 2
|
||||
assert set([dn for dn, entry in conn.search_s('o=orga', ldap.SCOPE_SUBTREE)]) == set(['o=orga',
|
||||
'uid=admin,o=orga'])
|
||||
|
||||
|
||||
def test_ldapsync_ldap_to_ldap(slapd_tcp1, slapd_tcp2, ldif, attributes, pivot_attributes):
|
||||
slapd_tcp1.add_db('dc=orga2')
|
||||
slapd_tcp1.add_ldif(ldif)
|
||||
|
||||
args = [
|
||||
'--source-uri', slapd_tcp1.ldap_url,
|
||||
'--source-bind-dn', slapd_tcp1.root_bind_dn,
|
||||
'--source-bind-password', slapd_tcp1.root_bind_password,
|
||||
'--source-base-dn', 'dc=orga2',
|
||||
|
||||
'--target-uri', slapd_tcp2.ldap_url,
|
||||
'--target-bind-dn', slapd_tcp2.root_bind_dn,
|
||||
'--target-bind-password', slapd_tcp2.root_bind_password,
|
||||
'--target-base-dn', 'o=orga',
|
||||
'--attributes', ' '.join(attributes),
|
||||
'--verbose',
|
||||
]
|
||||
for object_class, pivot_attribute in pivot_attributes:
|
||||
args += ['--object-class-pivot', '%s %s' % (object_class, pivot_attribute)]
|
||||
main(args)
|
||||
main(args)
|
||||
conn = slapd_tcp2.get_connection()
|
||||
assert len(conn.search_s('o=orga', ldap.SCOPE_SUBTREE)) == 2
|
||||
assert set([dn for dn, entry in conn.search_s('o=orga', ldap.SCOPE_SUBTREE)]) == set(['o=orga',
|
||||
'uid=admin,o=orga'])
|
|
@ -0,0 +1,11 @@
|
|||
import StringIO
|
||||
|
||||
from ldaptools.ldif_utils import ListLDIFParser
|
||||
|
||||
def test_ldifparser():
|
||||
parser = ListLDIFParser(StringIO.StringIO('''dn: o=orga
|
||||
objectClass: organization'''))
|
||||
parser.parse()
|
||||
assert len(list(parser)) == 1
|
||||
assert list(parser)[0][0] == 'o=orga'
|
||||
assert list(parser)[0][1] == {'objectClass': ['organization']}
|
|
@ -0,0 +1,27 @@
|
|||
import pytest
|
||||
|
||||
import ldap
|
||||
|
||||
|
||||
@pytest.mark.parametrize('slapd', [None, 'ldap://localhost:1389'], indirect=True)
|
||||
def test_checkpoint(slapd):
|
||||
conn = slapd.get_connection()
|
||||
conn.simple_bind_s('uid=admin,cn=config', 'admin')
|
||||
assert conn.whoami_s() == 'dn:uid=admin,cn=config'
|
||||
slapd.stop()
|
||||
slapd.checkpoint()
|
||||
slapd.start()
|
||||
slapd.add_ldif('''dn: uid=admin,o=orga
|
||||
objectclass: person
|
||||
objectclass: uidObject
|
||||
uid:in
|
||||
cn: n
|
||||
sn: n
|
||||
''')
|
||||
conn = slapd.get_connection()
|
||||
assert len(conn.search_s('o=orga', ldap.SCOPE_SUBTREE)) == 2
|
||||
slapd.stop()
|
||||
slapd.restore()
|
||||
slapd.start()
|
||||
conn = slapd.get_connection()
|
||||
assert len(conn.search_s('o=orga', ldap.SCOPE_SUBTREE)) == 1
|
|
@ -0,0 +1,211 @@
|
|||
import StringIO
|
||||
|
||||
import ldap
|
||||
|
||||
from ldaptools.synchronize import Synchronize, Delete, Rename, Update, Create
|
||||
from ldaptools.ldif_utils import ListLDIFParser
|
||||
from ldaptools.ldap_source import LDAPSource
|
||||
|
||||
|
||||
def test_synchronize_ldif(slapd):
|
||||
pivot_attributes = (
|
||||
('organization', 'o'),
|
||||
('inetOrgPerson', 'uid'),
|
||||
)
|
||||
attributes = ['o', 'objectClass', 'uid', 'sn', 'givenName', 'mail', 'dc', 'cn']
|
||||
conn = slapd.get_connection_admin()
|
||||
|
||||
def syn_ldif(ldif):
|
||||
parser = ListLDIFParser(StringIO.StringIO(ldif))
|
||||
parser.parse()
|
||||
synchronize = Synchronize(parser, 'o=orga', conn, 'o=orga',
|
||||
pivot_attributes=pivot_attributes,
|
||||
attributes=attributes)
|
||||
synchronize.run()
|
||||
return synchronize
|
||||
|
||||
ldif = '''dn: o=orga
|
||||
o: orga
|
||||
dc: coucou
|
||||
objectClass: organization
|
||||
objectClass: dcObject
|
||||
|
||||
dn: uid=admin,o=orga
|
||||
objectClass: inetOrgPerson
|
||||
cn: John Doe
|
||||
uid: admin
|
||||
sn: John
|
||||
givenName: Doe
|
||||
mail: john.doe@entrouvert.com'''
|
||||
|
||||
synchronize = syn_ldif(ldif)
|
||||
assert all(not action.errors for action in synchronize.actions)
|
||||
assert len(synchronize.actions) == 2
|
||||
assert len(conn.search_s('o=orga', ldap.SCOPE_SUBTREE)) == 2
|
||||
|
||||
# Rename
|
||||
slapd.add_ldif('''dn: ou=people,o=orga
|
||||
ou: people
|
||||
objectClass: organizationalUnit''')
|
||||
conn.rename_s('uid=admin,o=orga', 'cn=John Doe', newsuperior='ou=people,o=orga', delold=0)
|
||||
assert set([dn for dn, entry in conn.search_s('o=orga', ldap.SCOPE_SUBTREE)]) == set(['o=orga',
|
||||
'ou=people,o=orga',
|
||||
'cn=John Doe,ou=people,o=orga'])
|
||||
synchronize.run()
|
||||
|
||||
assert not any([action.errors for action in synchronize.actions])
|
||||
assert len(synchronize.actions) == 2
|
||||
assert isinstance(synchronize.actions[0], Rename)
|
||||
assert isinstance(synchronize.actions[1], Delete)
|
||||
assert len(conn.search_s('o=orga', ldap.SCOPE_SUBTREE)) == 2
|
||||
assert set([dn for dn, entry in conn.search_s('o=orga', ldap.SCOPE_SUBTREE)]) == set(['o=orga',
|
||||
'uid=admin,o=orga'])
|
||||
|
||||
# Delete one entry
|
||||
ldif = '''dn: o=orga
|
||||
o: orga
|
||||
dc: coucou
|
||||
objectClass: organization
|
||||
objectClass: dcobject
|
||||
'''
|
||||
synchronize = syn_ldif(ldif)
|
||||
assert all(not action.errors for action in synchronize.actions)
|
||||
assert len(synchronize.actions) == 1
|
||||
assert len(conn.search_s('o=orga', ldap.SCOPE_SUBTREE)) == 1
|
||||
|
||||
|
||||
def test_synchronize_ldap(slapd):
|
||||
pivot_attributes = (
|
||||
('organization', 'o'),
|
||||
('inetOrgPerson', 'uid'),
|
||||
)
|
||||
attributes = ['o', 'objectClass', 'uid', 'sn', 'givenName', 'mail', 'dc', 'cn']
|
||||
conn = slapd.get_connection_admin()
|
||||
|
||||
slapd.add_db('dc=orga2')
|
||||
ldif = '''dn: dc=orga2
|
||||
o: orga
|
||||
dc: orga2
|
||||
objectClass: organization
|
||||
objectClass: dcObject
|
||||
|
||||
dn: uid=admin,dc=orga2
|
||||
objectClass: inetOrgPerson
|
||||
cn: John Doe
|
||||
uid: admin
|
||||
sn: John
|
||||
givenName: Doe
|
||||
mail: john.doe@entrouvert.com'''
|
||||
slapd.add_ldif(ldif)
|
||||
|
||||
source = LDAPSource(conn, base_dn='dc=orga2', attributes=attributes)
|
||||
|
||||
|
||||
synchronize = Synchronize(source, 'dc=orga2', conn, 'o=orga',
|
||||
pivot_attributes=pivot_attributes,
|
||||
attributes=attributes)
|
||||
synchronize.run()
|
||||
|
||||
assert all(not action.errors for action in synchronize.actions)
|
||||
assert len(synchronize.actions) == 2
|
||||
assert isinstance(synchronize.actions[0], Update)
|
||||
assert isinstance(synchronize.actions[1], Create)
|
||||
assert len(conn.search_s('o=orga', ldap.SCOPE_SUBTREE)) == 2
|
||||
assert set([dn for dn, entry in conn.search_s('o=orga', ldap.SCOPE_SUBTREE)]) == set(['o=orga',
|
||||
'uid=admin,o=orga'])
|
||||
|
||||
# Rename
|
||||
slapd.add_ldif('''dn: ou=people,o=orga
|
||||
ou: people
|
||||
objectClass: organizationalUnit''')
|
||||
conn.rename_s('uid=admin,o=orga', 'cn=John Doe', newsuperior='ou=people,o=orga', delold=0)
|
||||
assert set([dn for dn, entry in conn.search_s('o=orga', ldap.SCOPE_SUBTREE)]) == set(['o=orga',
|
||||
'ou=people,o=orga',
|
||||
'cn=John Doe,ou=people,o=orga'])
|
||||
synchronize.run()
|
||||
|
||||
assert not any([action.errors for action in synchronize.actions])
|
||||
assert len(synchronize.actions) == 2
|
||||
assert isinstance(synchronize.actions[0], Rename)
|
||||
assert isinstance(synchronize.actions[1], Delete)
|
||||
assert len(conn.search_s('o=orga', ldap.SCOPE_SUBTREE)) == 2
|
||||
assert set([dn for dn, entry in conn.search_s('o=orga', ldap.SCOPE_SUBTREE)]) == set(['o=orga',
|
||||
'uid=admin,o=orga'])
|
||||
|
||||
# Delete one entry
|
||||
conn.delete_s('uid=admin,dc=orga2')
|
||||
synchronize.run()
|
||||
|
||||
assert all(not action.errors for action in synchronize.actions)
|
||||
assert len(synchronize.actions) == 1
|
||||
assert isinstance(synchronize.actions[0], Delete)
|
||||
assert len(conn.search_s('o=orga', ldap.SCOPE_SUBTREE)) == 1
|
||||
|
||||
def test_synchronize_deep_rename(slapd):
|
||||
pivot_attributes = (
|
||||
('organization', 'o'),
|
||||
('inetOrgPerson', 'uid'),
|
||||
('organizationalUnit', 'ou'),
|
||||
)
|
||||
attributes = ['o', 'objectClass', 'uid', 'sn', 'givenName', 'mail', 'dc',
|
||||
'cn', 'description', 'ou']
|
||||
conn = slapd.get_connection_admin()
|
||||
|
||||
def syn_ldif(ldif):
|
||||
parser = ListLDIFParser(StringIO.StringIO(ldif))
|
||||
parser.parse()
|
||||
synchronize = Synchronize(parser, 'o=orga', conn, 'o=orga',
|
||||
pivot_attributes=pivot_attributes,
|
||||
attributes=attributes)
|
||||
synchronize.run()
|
||||
return synchronize
|
||||
|
||||
ldif = '''dn: o=orga
|
||||
o: orga
|
||||
dc: coucou
|
||||
objectClass: organization
|
||||
objectClass: dcObject
|
||||
|
||||
dn: ou=people,o=orga
|
||||
objectClass: organizationalUnit
|
||||
ou: people
|
||||
description: coin
|
||||
|
||||
dn: uid=admin,ou=people,o=orga
|
||||
objectClass: inetOrgPerson
|
||||
cn: John Doe
|
||||
uid: admin
|
||||
sn: John
|
||||
givenName: Doe
|
||||
mail: john.doe@entrouvert.com'''
|
||||
|
||||
synchronize = syn_ldif(ldif)
|
||||
assert all(not action.errors for action in synchronize.actions)
|
||||
assert len(synchronize.actions) == 3
|
||||
assert len(conn.search_s('o=orga', ldap.SCOPE_SUBTREE)) == 3
|
||||
|
||||
# Rename
|
||||
ldif = '''dn: o=orga
|
||||
o: orga
|
||||
dc: coucou
|
||||
objectClass: organization
|
||||
objectClass: dcObject
|
||||
|
||||
dn: description=coin,o=orga
|
||||
objectClass: organizationalUnit
|
||||
ou: people
|
||||
description: coin
|
||||
|
||||
dn: cn=John Doe,description=coin,o=orga
|
||||
objectClass: inetOrgPerson
|
||||
cn: John Doe
|
||||
uid: admin
|
||||
sn: John
|
||||
givenName: Doe
|
||||
mail: john.doe@entrouvert.com'''
|
||||
|
||||
synchronize = syn_ldif(ldif)
|
||||
|
||||
assert all(not action.errors for action in synchronize.actions)
|
||||
assert len(synchronize.actions) == 2
|
||||
assert len(conn.search_s('o=orga', ldap.SCOPE_SUBTREE)) == 3
|
|
@ -0,0 +1,22 @@
|
|||
# Tox (http://tox.testrun.org/) is a tool for running tests
|
||||
# in multiple virtualenvs. This configuration file will run the
|
||||
# test suite on all supported python versions. To use it, "pip install tox"
|
||||
# and then run "tox" from this directory.
|
||||
|
||||
[tox]
|
||||
envlist = coverage, nocoverage
|
||||
|
||||
[testenv:coverage]
|
||||
usedevelop = true
|
||||
deps = pytest
|
||||
pytest-cov
|
||||
pytest-random
|
||||
commands =
|
||||
py.test --cov=ldaptools --cov-report xml {posargs}
|
||||
|
||||
[testenv:nocoverage]
|
||||
deps = pytest
|
||||
pytest-cov
|
||||
pytest-random
|
||||
commands =
|
||||
py.test {posargs}
|
Loading…
Reference in New Issue