Skip to content

Commit

Permalink
Add a compare-ldap-schemas tool
Browse files Browse the repository at this point in the history
Added a compare-ldap-schemas command-line tool that can be used to
identify differences between the schemas of two LDAP servers.
  • Loading branch information
dirmgr committed Jan 18, 2024
1 parent 5e09c0b commit 62aa718
Show file tree
Hide file tree
Showing 9 changed files with 11,854 additions and 6 deletions.
52 changes: 52 additions & 0 deletions dist-root/tools/compare-ldap-schemas
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#!/bin/sh

# Copyright 2008-2024 Ping Identity Corporation
# All Rights Reserved.
#
# -----
#
# Copyright 2008-2024 Ping Identity Corporation
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# -----
#
# Copyright (C) 2008-2024 Ping Identity Corporation
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License (GPLv2 only)
# as published by the Free Software Foundation.
#
# 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


# Get the current working directory and the tools directory.
CURRENT_DIR=`pwd`
cd "`dirname "${0}"`"
TOOLS_DIR=`pwd`
cd ${CURRENT_DIR}


# Invoke a number of common script utility functions.
. "${TOOLS_DIR}/.script-util.sh"


# Invoke the tool with the provided command-line arguments.
"${JAVA_CMD}" ${JAVA_ARGS} \
-cp "${TOOLS_DIR}/../unboundid-ldapsdk.jar:${CLASSPATH}" \
com.unboundid.ldap.sdk.unboundidds.tools.CompareLDAPSchemas "${@}"

46 changes: 46 additions & 0 deletions dist-root/tools/compare-ldap-schemas.bat
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
@echo off

rem Copyright 2008-2024 Ping Identity Corporation
rem All Rights Reserved.
rem
rem -----
rem
rem Copyright 2008-2024 Ping Identity Corporation
rem
rem Licensed under the Apache License, Version 2.0 (the "License");
rem you may not use this file except in compliance with the License.
rem You may obtain a copy of the License at
rem
rem http://www.apache.org/licenses/LICENSE-2.0
rem
rem Unless required by applicable law or agreed to in writing, software
rem distributed under the License is distributed on an "AS IS" BASIS,
rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
rem See the License for the specific language governing permissions and
rem limitations under the License.
rem
rem -----
rem
rem Copyright (C) 2008-2024 Ping Identity Corporation
rem This program is free software; you can redistribute it and/or modify
rem it under the terms of the GNU General Public License (GPLv2 only)
rem or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
rem as published by the Free Software Foundation.
rem
rem This program is distributed in the hope that it will be useful,
rem but WITHOUT ANY WARRANTY; without even the implied warranty of
rem MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
rem GNU General Public License for more details.
rem
rem You should have received a copy of the GNU General Public License


rem Get the directory containing this batch file.
set BATDIR=%~dp0

rem Invoke a number of common script utility functions.
call "%BATDIR%\.script-util.bat"

rem Invoke the tool with the provided command-line arguments.
"%JAVA_CMD%" %JAVA_ARGS% -cp "%BATDIR%\..\unboundid-ldapsdk.jar;%CLASSPATH%" com.unboundid.ldap.sdk.unboundidds.tools.CompareLDAPSchemas %*

6 changes: 6 additions & 0 deletions docs/release-notes.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ <h3>Version 7.0.0</h3>
<br><br>
</li>

<li>
Added a compare-ldap-schemas command-line tool that can be used to identify
differences between the schemas of two LDAP servers.
<br><br>
</li>

<li>
Added the ability to reuse automatically generated JAAS configuration files if
possible when attempting a SASL GSSAPI bind. Previously, if the caller didn't
Expand Down
163 changes: 163 additions & 0 deletions messages/unboundid-ldapsdk-tools.properties
Original file line number Diff line number Diff line change
Expand Up @@ -4427,4 +4427,167 @@ ERR_LDAP_DIFF_PROCESSOR_ERROR_GETTING_ENTRY_FROM_SOURCE=An error occurred \
while attempting to retrieve entry ''{0}'' from the source server: {1}
ERR_LDAP_DIFF_PROCESSOR_ERROR_GETTING_ENTRY_FROM_TARGET=An error occurred \
while attempting to retrieve entry ''{0}'' from the target server: {1}
INFO_COMPARE_SCHEMA_TOOL_DESC=This tool can be used to compare the schemas of \
two LDAP servers to identify schema elements that may be present in one but \
not the other, or elements that may be present in both servers but have \
differences between them.
INFO_COMPARE_SCHEMA_ARG_DESC_FIRST_SCHEMA_ENTRY_DN=The DN of the subschema \
subentry in the first server that contains the definitions to examine. If \
this is not specified, then the entry referenced by the subschemaSubentry \
attribute in the server''s root DSE will be used.
INFO_COMPARE_SCHEMA_ARG_DESC_SECOND_SCHEMA_ENTRY_DN=The DN of the subschema \
subentry in the second server that contains the definitions to examine. If \
this is not specified, then the entry referenced by the subschemaSubentry \
attribute in the server''s root DSE will be used.
INFO_COMPARE_SCHEMA_ARG_PLACEHOLDER_SCHEMA_ELEMENT_TYPE='{'elementType'}'
INFO_COMPARE_SCHEMA_ARG_DESC_SCHEMA_ELEMENT_TYPE=The types of schema elements \
to examine. Allowed values include {0}, {1}, {2}, {3}, {4}, {5}, {6}, and \
{7}. This may be provided multiple times to include multiple specific \
schema element types. If this argument is not provided, then all schema \
element types will be considered.
INFO_COMPARE_SCHEMA_ARG_DESC_GET_EXTENDED_SCHEMA_INFO=Use the extended \
schema info request control, which may be used to retrieve additional \
information about schema element definitions from a Ping Identity Directory \
Server.
INFO_COMPARE_SCHEMA_ARG_DESC_IGNORE_DESCRIPTIONS=Indicates that the tool \
should ignore differences in descriptions when comparing schema elements.
INFO_COMPARE_SCHEMA_ARG_DESC_IGNORE_EXTENSIONS=Indicates that the tool should \
ignore differences in extensions when comparing schema elements.
INFO_COMPARE_SCHEMA_ARG_PLACEHOLDER_PREFIX='{'prefix'}'
INFO_COMPARE_SCHEMA_ARG_DESC_INCLUDE_NAME_MATCHING_PREFIX=Indicates that the \
tool should only examine schema elements with names that match the \
specified prefix. This argument may be provided multiple times to specify \
multiple include prefixes. If no include or exclude prefixes are \
specified, then names will not be used when considering which elements to \
examine.
INFO_COMPARE_SCHEMA_ARG_DESC_EXCLUDE_NAME_MATCHING_PREFIX=Indicates that the \
tool should not examine schema elements with names that match the specified \
prefix. This argument may be provided multiple times to specify multiple \
exclude prefixes. If no include or exclude prefixes are specified, then \
names will not be used when considering which elements to examine.
INFO_COMPARE_SCHEMA_ARG_PLACEHOLDER_EXTENSION_VALUE='{'name=value'}'
INFO_COMPARE_SCHEMA_ARG_DESC_INCLUDE_EXTENSION_VALUE=Indicates that the tool \
should only examine schema elements with an extension that has the \
specified name and value. This argument may be provided multiple times to \
specify multiple include extension values. If no include or exclude \
extension values are specified, then extensions will not be used when \
considering which elements to examine.
INFO_COMPARE_SCHEMA_ARG_DESC_EXCLUDE_EXTENSION_VALUE=Indicates that the tool \
should no examine schema elements with an extension that has the specified \
name and value. This argument may be provided multiple times to specify \
multiple exclude extension values. If no include or exclude extension \
values are specified, then extensions will not be used when considering \
which elements to examine.
ERR_COMPARE_SCHEMA_INVALID_SCHEMA_ELEMENT_TYPE=Invalid value ''{0}'' \
specified for the --{1} argument. Allowed values include ''{2}'', ''{3}'', \
''{4}'', ''{5}'', ''{6}'', ''{7}'', ''{8}'', and ''{9}''.
INFO_COMPARE_SCHEMA_FIRST_SERVER_LABEL=first
INFO_COMPARE_SCHEMA_SECOND_SERVER_LABEL=second
ERR_COMPARE_SCHEMA_SUMMARY_UNPARSABLE_NO_DIFFERENCES=No differences were \
identified between the server schemas, but one or more unparsable schema \
elements were encountered.
ERR_COMPARE_SCHEMA_SUMMARY_UNPARSABLE_WITH_DIFFERENCE=One difference was \
identified between the server schemas, and one or more unparsable schema \
elements were encountered.
ERR_COMPARE_SCHEMA_SUMMARY_UNPARSABLE_WITH_DIFFERENCES={0} differences were \
identified between the server schemas, and one or more unparsable schema \
elements were encountered.
ERR_COMPARE_SCHEMA_SUMMARY_DIFFERENCE=One difference was identified between \
the server schemas.
ERR_COMPARE_SCHEMA_SUMMARY_DIFFERENCES={0} difference were identified between \
the server schemas.
INFO_COMPARE_SCHEMA_SUMMARY_NO_DIFFERENCES=No differences were identified \
between the server schemas.
ERR_COMPARE_SCHEMA_CANNOT_CONNECT=Unable to establish a connection to the {0} \
server: {1}
ERR_COMPARE_SCHEMA_CANNOT_GET_ROOT_DSE=Unable to retrieve the root DSE from \
the {0} server to determine the DN of the subschema subentry.
ERR_COMPARE_SCHEMA_CANNOT_GET_ROOT_DSE_SCHEMA_DN=The {0} server''s root DSE \
does not include the {1} attribute that is expected to specify the location \
of the subschema subentry.
ERR_COMPARE_SCHEMA_CANNOT_GET_SCHEMA_ENTRY=Unable to retrieve subschema \
subentry ''{0}'' from the {1} server to obtain its schema definitions.
ERR_COMPARE_SCHEMA_CANNOT_GET_SCHEMA=An error occurred while attempting to \
obtain the schema definitions from the {0} server: {1}
ERR_COMPARE_SCHEMA_EXTENSION_VALUE_NO_EQUALS=--{0} argument value ''{0}'' is \
not valid because it does not contain an equal sign to separate the \
extension name from its value.
ERR_COMPARE_SCHEMA_EXTENSION_VALUE_EMPTY_NAME=--{0} argument value ''{0}'' is \
not valid because it contains an empty extension name.
ERR_COMPARE_SCHEMA_EXTENSION_VALUE_EMPTY_VALUE=--{0} argument value ''{0}'' is \
not valid because it contains an empty extension value.
INFO_COMPARE_SCHEMA_ELEMENT_TYPE_ATTRIBUTE_SYNTAX=attribute syntax
INFO_COMPARE_SCHEMA_ELEMENT_TYPE_MATCHING_RULE=matching rule
INFO_COMPARE_SCHEMA_ELEMENT_TYPE_ATTRIBUTE_TYPE=attribute type
INFO_COMPARE_SCHEMA_ELEMENT_TYPE_OBJECT_CLASS=object class
INFO_COMPARE_SCHEMA_ELEMENT_TYPE_DIT_CONTENT_RULE=DIT content rule
INFO_COMPARE_SCHEMA_ELEMENT_TYPE_DIT_STRUCTURE_RULE=DIT structure rule
INFO_COMPARE_SCHEMA_ELEMENT_TYPE_NAME_FORM=name form
INFO_COMPARE_SCHEMA_ELEMENT_TYPE_MATCHING_RULE_USE=matching rule use
ERR_COMPARE_SCHEMA_UNPARSABLE_ELEMENT=The following {0} definition was found \
in the {1} server ({2}):
WARN_COMPARE_SCHEMA_MISSING_SYNTAX=The {0} server contains an attribute \
syntax definition that is missing from the {1} server:
INFO_COMPARE_SCHEMA_STRING_DESCRIPTOR_DESCRIPTION=description
WARN_COMPARE_SCHEMA_MISSING_MATCHING_RULE=The {0} server contains a matching \
rule definition that is missing from the {1} server:
INFO_COMPARE_SCHEMA_STRING_DESCRIPTOR_SYNTAX_OID=syntax OID
INFO_COMPARE_SCHEMA_BOOLEAN_FIELD_NAME_OBSOLETE=OBSOLETE
WARN_COMPARE_SCHEMA_MISSING_ATTRIBUTE_TYPE=The {0} server contains an \
attribute type definition that is missing from the {1} server:
INFO_COMPARE_SCHEMA_STRING_DESCRIPTOR_SUPERIOR_TYPE=superior type
INFO_COMPARE_SCHEMA_STRING_DESCRIPTOR_EQUALITY_MR=equality matching rule
INFO_COMPARE_SCHEMA_STRING_DESCRIPTOR_ORDERING_MR=ordering matching rule
INFO_COMPARE_SCHEMA_STRING_DESCRIPTOR_SUBSTRING_MR=substring matching rule
INFO_COMPARE_SCHEMA_BOOLEAN_FIELD_NAME_SINGLE_VALUE=SINGLE-VALUE
INFO_COMPARE_SCHEMA_BOOLEAN_FIELD_NAME_NO_USER_MOD=NO-USER-MODIFICATION
INFO_COMPARE_SCHEMA_STRING_DESCRIPTOR_USAGE=usage
INFO_COMPARE_SCHEMA_BOOLEAN_FIELD_NAME_COLLECTIVE=COLLECTIVE
WARN_COMPARE_SCHEMA_MISSING_OBJECT_CLASS=The {0} server contains an object \
class definition that is missing from the {1} server:
INFO_COMPARE_SCHEMA_STRING_DESCRIPTOR_REQUIRED_ATTRIBUTE=required attribute
INFO_COMPARE_SCHEMA_STRING_DESCRIPTOR_OPTIONAL_ATTRIBUTE=optional attribute
INFO_COMPARE_SCHEMA_STRING_DESCRIPTOR_OBJECT_CLASS_TYPE=object class type
WARN_COMPARE_SCHEMA_MISSING_DIT_CONTENT_RULE=The {0} server contains a DIT \
content rule definition that is missing from the {1} server:
INFO_COMPARE_SCHEMA_STRING_DESCRIPTOR_PROHIBITED_ATTRIBUTE=prohibited attribute
INFO_COMPARE_SCHEMA_STRING_DESCRIPTOR_AUXILIARY_CLASS=auxiliary object class
WARN_COMPARE_SCHEMA_MISSING_DIT_STRUCTURE_RULE=The {0} server contains a DIT \
structure rule definition that is missing from the {1} server:
INFO_COMPARE_SCHEMA_STRING_DESCRIPTOR_NAME_FORM=name form
INFO_COMPARE_SCHEMA_STRING_DESCRIPTOR_SUPERIOR_RULE_ID=superior rule ID
WARN_COMPARE_SCHEMA_MISSING_NAME_FORM=The {0} server contains a name form \
definition that is missing from the {1} server:
INFO_COMPARE_SCHEMA_STRING_DESCRIPTOR_STRUCTURAL_CLASS=structural object class
WARN_COMPARE_SCHEMA_MISSING_MATCHING_RULE_USE=The {0} server contains a \
matching rule use definition that is missing from the {1} server:
INFO_COMPARE_SCHEMA_STRING_DESCRIPTOR_APPLICABLE_ATTRIBUTE=applicable \
attribute type
WARN_COMPARE_SCHEMA_STRING_MISSING_FROM_SERVER=The {0} server contains {0} \
''{1}'' with {2} ''{3}'', but the corresponding definition from the {4} \
server does not contain any value for that field.
WARN_COMPARE_SCHEMA_STRING_DIFFERENT_BETWEEN_SERVERS=Both servers contain \
{0} ''{1}'' with {2} values, but the first server has a value of ''{3}'', \
while the second server has a value of ''{4}''.
WARN_COMPARE_SCHEMA_STRING_ARRAY_SINGLE_IN_ONLY_ONE_SERVER=The {0} server \
contains {1} ''{2}'' with {3} ''{4}'', but the corresponding definition \
from the {5} server does not have any values for that field.
WARN_COMPARE_SCHEMA_STRING_ARRAY_MULTIPLE_IN_ONLY_ONE_SERVER=The {0} server \
contains {1} ''{2}'' with {3} values {4}, but the corresponding \
definition from the {5} server does not have any values for that field.
WARN_COMPARE_SCHEMA_STRING_ARRAY_VALUE_MISSING_FROM_SERVER=Both servers \
contain {0} ''{1}'' with values for the ''{2}'' field, but the {3} server \
has value ''{4}'' that the {5} server does not have.
WARN_COMPARE_SCHEMA_BOOLEAN_DIFFERENCE=The {0} ''{1}'' definition is defined \
with ''{2}'' in the {3} server, but not in the {4} server.
WARN_COMPARE_SCHEMA_MISSING_EXTENSION=The {0} server contains {1} ''{2}'' \
with extension ''{3}'' that is not present in the corresponding definition \
from the {4} server.
WARN_COMPARE_SCHEMA_EXTENSION_DIFFERENCE=Both servers contain a {0} ''{1}'' \
definition with the ''{2}'' extension, but that extension has a different \
set of values in each server.
INFO_COMPARE_SCHEMA_STRING_DESCRIPTOR_NAME=name
INFO_COMPARE_LDAP_SCHEMAS_EXAMPLE=Compares the LDAP schemas for the two \
directory servers using the default settings, which will identify any \
differences between the schemas.

20 changes: 14 additions & 6 deletions src/com/unboundid/ldap/sdk/schema/Schema.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,14 @@
public final class Schema
implements Serializable
{
/**
* The filter that should be used to retrieve the subsechema subentry.
*/
@NotNull public static final Filter SUBSCHEMA_SUBENTRY_FILTER =
Filter.createEqualityFilter("objectClass", "subschema");



/**
* The name of the attribute used to hold the attribute syntax definitions.
*/
Expand Down Expand Up @@ -165,7 +173,7 @@ public final class Schema
* The set of request attributes that will be used when retrieving the server
* subschema subentry in order to retrieve all of the schema elements.
*/
@NotNull private static final String[] SCHEMA_REQUEST_ATTRS =
@NotNull public static final String[] SCHEMA_REQUEST_ATTRS =
{
"*",
ATTR_ATTRIBUTE_SYNTAX,
Expand Down Expand Up @@ -788,8 +796,10 @@ public Schema(@NotNull final Entry schemaEntry,
* Parses all schema elements contained in the provided entry. This method
* differs from the {@link #Schema(Entry)} constructor in that this method
* will throw an exception if it encounters any unparsable schema elements,
* while the constructor will silently ignore them. Alternately, the
* 'constructor that takes a bunch of maps can be used to
* while the constructor will silently ignore them. Alternatively, the
* constructor that takes a bunch of maps can be used to obtain information
* about any unparsable schema elements while still providing access to the
* parsed schema.
*
* @param schemaEntry The schema entry to parse. It must not be
* {@code null}.
Expand Down Expand Up @@ -1051,9 +1061,7 @@ public static Schema getSchema(@NotNull final LDAPConnection connection,
}

final Entry schemaEntry = connection.searchForEntry(subschemaSubentryDN,
SearchScope.BASE,
Filter.createEqualityFilter("objectClass", "subschema"),
SCHEMA_REQUEST_ATTRS);
SearchScope.BASE, SUBSCHEMA_SUBENTRY_FILTER, SCHEMA_REQUEST_ATTRS);
if (schemaEntry == null)
{
return null;
Expand Down
9 changes: 9 additions & 0 deletions src/com/unboundid/ldap/sdk/unboundidds/Launcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
import com.unboundid.ldap.sdk.unboundidds.examples.SubtreeAccessibility;
import com.unboundid.ldap.sdk.unboundidds.examples.SummarizeAccessLog;
import com.unboundid.ldap.sdk.unboundidds.tools.CollectSupportData;
import com.unboundid.ldap.sdk.unboundidds.tools.CompareLDAPSchemas;
import com.unboundid.ldap.sdk.unboundidds.tools.GenerateTOTPSharedSecret;
import com.unboundid.ldap.sdk.unboundidds.tools.LDAPCompare;
import com.unboundid.ldap.sdk.unboundidds.tools.LDAPDelete;
Expand Down Expand Up @@ -120,6 +121,8 @@
* <LI>base64 -- Launch the {@link Base64Tool} tool.</LI>
* <LI>collect-support-data -- Launch the
* {@link CollectSupportData} tool.</LI>
* <LI>compare-ldap-schemas -- Launch the
* {@link CompareLDAPSchemas} tool.</LI>
* <LI>deliver-one-time-password -- Launch the
* {@link DeliverOneTimePassword} tool.</LI>
* <LI>deliver-password-reset-token -- Launch the
Expand Down Expand Up @@ -251,6 +254,10 @@ else if (firstArg.equals("collect-support-data"))
{
return CollectSupportData.main(outStream, errStream, remainingArgs);
}
else if (firstArg.equals("compare-ldap-schemas"))
{
return CompareLDAPSchemas.main(outStream, errStream, remainingArgs);
}
else if (firstArg.equals("deliver-one-time-password"))
{
return DeliverOneTimePassword.main(remainingArgs, outStream, errStream);
Expand Down Expand Up @@ -418,6 +425,7 @@ else if (firstArg.equals("validate-ldif"))
err.println(" authrate");
err.println(" base64");
err.println(" collect-support-data");
err.println(" compare-ldap-schemas");
err.println(" deliver-one-time-password");
err.println(" deliver-password-reset-token");
err.println(" dump-dns");
Expand Down Expand Up @@ -479,6 +487,7 @@ public static List<Class<? extends CommandLineTool>> getToolClasses()
AuthRate.class,
Base64Tool.class,
CollectSupportData.class,
CompareLDAPSchemas.class,
DeliverOneTimePassword.class,
DeliverPasswordResetToken.class,
DumpDNs.class,
Expand Down
Loading

0 comments on commit 62aa718

Please sign in to comment.