From 653dd024a630af095277f5884add9246da399eb9 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 20 Mar 2009 16:07:49 +1100 Subject: Add minschema like tool to extract and dump the full schema from AD --- source4/scripting/bin/fullschema | 191 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 source4/scripting/bin/fullschema (limited to 'source4/scripting/bin/fullschema') diff --git a/source4/scripting/bin/fullschema b/source4/scripting/bin/fullschema new file mode 100644 index 0000000000..02e90f6973 --- /dev/null +++ b/source4/scripting/bin/fullschema @@ -0,0 +1,191 @@ +#!/usr/bin/python +# +# work out the minimal schema for a set of objectclasses +# + +import base64 +import optparse +import os +import sys + +# Find right directory when running from source tree +sys.path.insert(0, "bin/python") + +import samba +from samba import getopt as options, Ldb +from ldb import SCOPE_SUBTREE, SCOPE_BASE, LdbError +import sys + +parser = optparse.OptionParser("fullschema ") +sambaopts = options.SambaOptions(parser) +parser.add_option_group(sambaopts) +credopts = options.CredentialsOptions(parser) +parser.add_option_group(credopts) +parser.add_option_group(options.VersionOptions(parser)) +parser.add_option("--verbose", help="Be verbose", action="store_true") +parser.add_option("--dump-classes", action="store_true") +parser.add_option("--dump-attributes", action="store_true") + +opts, args = parser.parse_args() +opts.dump_all = True + +if opts.dump_classes: + opts.dump_all = False +if opts.dump_attributes: + opts.dump_all = False +if opts.dump_all: + opts.dump_classes = True + opts.dump_attributes = True + +if len(args) != 1: + parser.print_usage() + sys.exit(1) + +url = args[0] + +lp_ctx = sambaopts.get_loadparm() + +creds = credopts.get_credentials(lp_ctx) +ldb = Ldb(url, credentials=creds, lp=lp_ctx, options=["modules:paged_searches"]) + +objectclasses = {} +attributes = {} + +# the attributes we need for objectclasses +class_attrs = ["objectClass", + "cn", + "subClassOf", + "governsID", + "possSuperiors", + "possibleInferiors", + "mayContain", + "mustContain", + "auxiliaryClass", + "rDNAttID", + "showInAdvancedViewOnly", + "adminDisplayName", + "adminDescription", + "objectClassCategory", + "lDAPDisplayName", + "schemaIDGUID", + "systemOnly", + "systemPossSuperiors", + "systemMayContain", + "systemMustContain", + "systemAuxiliaryClass", + "defaultSecurityDescriptor", + "systemFlags", + "defaultHidingValue", + "defaultObjectCategory", + + # this attributes are not used by w2k3 + "schemaFlagsEx", + "msDs-IntId", + "msDs-Schema-Extensions", + "classDisplayName", + "isDefunct"] + +attrib_attrs = ["objectClass", + "cn", + "attributeID", + "attributeSyntax", + "isSingleValued", + "rangeLower", + "rangeUpper", + "mAPIID", + "linkID", + "showInAdvancedViewOnly", + "adminDisplayName", + "oMObjectClass", + "adminDescription", + "oMSyntax", + "searchFlags", + "extendedCharsAllowed", + "lDAPDisplayName", + "schemaIDGUID", + "attributeSecurityGUID", + "systemOnly", + "systemFlags", + "isMemberOfPartialAttributeSet", + + # this attributes are not used by w2k3 + "schemaFlagsEx", + "msDs-IntId", + "msDs-Schema-Extensions", + "classDisplayName", + "isEphemeral", + "isDefunct"] + +# +# notes: +# +# objectClassCategory +# 1: structural +# 2: abstract +# 3: auxiliary + +class Objectclass(dict): + + def __init__(self, ldb, name): + """create an objectclass object""" + self.name = name + + +class Attribute(dict): + + def __init__(self, ldb, name): + """create an attribute object""" + self.name = name + self["cn"] = get_object_cn(ldb, name) + + + +def fix_dn(dn): + """fix a string DN to use ${SCHEMADN}""" + return dn.replace(rootDse["schemaNamingContext"][0], "${SCHEMADN}") + + +def write_ldif_one(o, attrs): + """dump an object as ldif""" + print "dn: CN=%s,${SCHEMADN}" % o["cn"] + for a in attrs: + if not o.has_key(a): + continue + # special case for oMObjectClass, which is a binary object + v = o[a] + for j in v: + value = fix_dn(j) + if a != "cn": + if a == "oMObjectClass": + print "%s:: %s" % (a, base64.b64encode(value)) + elif a.endswith("GUID"): + print "%s: %s" % (a, ldb.schema_format_value(a, value)) + else: + print "%s: %s" % (a, value) + print "" + + +# get the rootDSE +res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["schemaNamingContext"]) +rootDse = res[0] + +if opts.dump_attributes: + res = ldb.search(expression="objectClass=attributeSchema", + base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE,attrs=attrib_attrs) + + for msg in res: + o = Objectclass(ldb, msg["ldapDisplayName"]) + for a in msg: + o[a] = msg[a] + write_ldif_one(o, attrib_attrs) + +if opts.dump_classes: + res = ldb.search(expression="objectClass=classSchema", + base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE,attrs=class_attrs) + + for msg in res: + o = Objectclass(ldb, msg["ldapDisplayName"]) + for a in msg: + o[a] = msg[a] + write_ldif_one(o, class_attrs) + -- cgit From f696bb81f8499443eee9815e7adf8dbb6810506a Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 20 Mar 2009 16:18:40 +1100 Subject: s4: Remove autogenerated attributes from minschema and fullschema output These attributes will be generated by Samba on import, and do not need to be in the schema file. Andrew Bartlett --- source4/scripting/bin/fullschema | 14 -------------- 1 file changed, 14 deletions(-) (limited to 'source4/scripting/bin/fullschema') diff --git a/source4/scripting/bin/fullschema b/source4/scripting/bin/fullschema index 02e90f6973..d3bf398e65 100644 --- a/source4/scripting/bin/fullschema +++ b/source4/scripting/bin/fullschema @@ -22,7 +22,6 @@ parser.add_option_group(sambaopts) credopts = options.CredentialsOptions(parser) parser.add_option_group(credopts) parser.add_option_group(options.VersionOptions(parser)) -parser.add_option("--verbose", help="Be verbose", action="store_true") parser.add_option("--dump-classes", action="store_true") parser.add_option("--dump-attributes", action="store_true") @@ -48,9 +47,6 @@ lp_ctx = sambaopts.get_loadparm() creds = credopts.get_credentials(lp_ctx) ldb = Ldb(url, credentials=creds, lp=lp_ctx, options=["modules:paged_searches"]) -objectclasses = {} -attributes = {} - # the attributes we need for objectclasses class_attrs = ["objectClass", "cn", @@ -62,7 +58,6 @@ class_attrs = ["objectClass", "mustContain", "auxiliaryClass", "rDNAttID", - "showInAdvancedViewOnly", "adminDisplayName", "adminDescription", "objectClassCategory", @@ -94,7 +89,6 @@ attrib_attrs = ["objectClass", "rangeUpper", "mAPIID", "linkID", - "showInAdvancedViewOnly", "adminDisplayName", "oMObjectClass", "adminDescription", @@ -116,14 +110,6 @@ attrib_attrs = ["objectClass", "isEphemeral", "isDefunct"] -# -# notes: -# -# objectClassCategory -# 1: structural -# 2: abstract -# 3: auxiliary - class Objectclass(dict): def __init__(self, ldb, name): -- cgit From 37f130fd89d02e77bf55cbd8da731d87bb4ab1e8 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 20 Mar 2009 16:47:34 +1100 Subject: s4:fullschema Use server-side sort to make the output deterministic --- source4/scripting/bin/fullschema | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source4/scripting/bin/fullschema') diff --git a/source4/scripting/bin/fullschema b/source4/scripting/bin/fullschema index d3bf398e65..41c45f30c8 100644 --- a/source4/scripting/bin/fullschema +++ b/source4/scripting/bin/fullschema @@ -157,7 +157,8 @@ rootDse = res[0] if opts.dump_attributes: res = ldb.search(expression="objectClass=attributeSchema", - base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE,attrs=attrib_attrs) + base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE,attrs=attrib_attrs, + controls=["server_sort:1:0:cn"]) for msg in res: o = Objectclass(ldb, msg["ldapDisplayName"]) @@ -167,7 +168,8 @@ if opts.dump_attributes: if opts.dump_classes: res = ldb.search(expression="objectClass=classSchema", - base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE,attrs=class_attrs) + base=rootDse["schemaNamingContext"][0], scope=SCOPE_SUBTREE,attrs=class_attrs, + controls=["server_sort:1:0:cn"]) for msg in res: o = Objectclass(ldb, msg["ldapDisplayName"]) -- cgit