From e1e451f8b0c3490bddbd3d6ee3d0fe5105639bad Mon Sep 17 00:00:00 2001
From: Mark Craig <mark.craig@forgerock.com>
Date: Thu, 31 Jan 2013 14:59:53 +0000
Subject: [PATCH] CR-1234 Fix for OPENDJ-638: Describe how to authenticate with client certificates
---
opendj3/src/main/docbkx/admin-guide/chap-listeners.xml | 372 ++++++++++++++++++++-
opendj3/src/main/docbkx/admin-guide/chap-ldap-operations.xml | 592 ++++++++++++++++++++++++++++++++++
2 files changed, 945 insertions(+), 19 deletions(-)
diff --git a/opendj3/src/main/docbkx/admin-guide/chap-ldap-operations.xml b/opendj3/src/main/docbkx/admin-guide/chap-ldap-operations.xml
index a0d73b9..f6848a4 100644
--- a/opendj3/src/main/docbkx/admin-guide/chap-ldap-operations.xml
+++ b/opendj3/src/main/docbkx/admin-guide/chap-ldap-operations.xml
@@ -20,7 +20,7 @@
!
! CCPL HEADER END
!
- ! Copyright 2011-2012 ForgeRock AS
+ ! Copyright 2011-2013 ForgeRock AS
!
-->
<chapter xml:id='chap-ldap-operations'
@@ -1133,4 +1133,594 @@
</step>
</procedure>
</section>
+
+ <section xml:id="client-cert-auth">
+ <title>Authenticating Using a Certificate</title>
+ <indexterm><primary>Certificates</primary></indexterm>
+ <indexterm><primary>StartTLS</primary></indexterm>
+ <indexterm><primary>SSL</primary></indexterm>
+
+ <para>One alternative to simple binds with user name/password combinations
+ consists in storing a digital certificate on the user entry, and then using
+ the certificate as credentials during the bind. You can use this mechanism for
+ example to let applications bind without using passwords.</para>
+
+ <para>Simply by setting up a secure connection with a certificate, the client
+ is in effect authenticating to the server. The server must close the
+ connection if it cannot trust the client certificate. However, the process
+ of establishing a secure connection does not in itself identify the client
+ to OpenDJ directory server.</para>
+
+ <para>Instead when binding with a certificate, the client must request the
+ SASL External mechanism by which OpenDJ directory server maps the certificate
+ to the client entry in the directory. When it finds a match, OpenDJ sets the
+ authorization identity for the connection to that of the client, and the bind
+ is successful.</para>
+
+ <para>For the whole process of authenticating with a certificate to work
+ smoothly, OpenDJ and the client must trust each others' certificates, the
+ client certificate must be stored on the client entry in the directory, and
+ OpenDJ must be configured to map the certificate to the client entry.</para>
+
+ <procedure xml:id="add-client-cert">
+ <title>To Add Certificate Information to an Entry</title>
+
+ <para>Before trying to bind to OpenDJ directory server using a certificate,
+ create a certificate, and then add the certificate attributes to the
+ entry.</para>
+
+ <para><link xlink:href="http://opendj.forgerock.org/Example.ldif"
+ xlink:show="new">Example.ldif</link> includes an entry for
+ <literal>cn=My App,ou=Apps,dc=example,dc=com</literal>. Examples in this
+ section use that entry, and use the Java <command>keytool</command> command
+ to manage the certificate.</para>
+
+ <step>
+ <para>Create a certificate using the DN of the client entry as the
+ distinguished name string.</para>
+
+ <screen>$ keytool
+ -genkey
+ -alias myapp-cert
+ -keyalg rsa
+ -dname "cn=My App,ou=Apps,dc=example,dc=com"
+ -keystore keystore
+ -storepass changeit
+ -keypass changeit</screen>
+ </step>
+
+ <step>
+ <para>Get the certificate signed.</para>
+
+ <para>If you cannot get the certificate signed by a Certificate Authority,
+ self-sign the certificate.</para>
+
+ <screen>$ keytool
+ -selfcert
+ -alias myapp-cert
+ -validity 7300
+ -keystore keystore
+ -storepass changeit
+ -keypass changeit</screen>
+ </step>
+
+ <step>
+ <para>Make note of the certificate fingerprints.</para>
+
+ <para>Later in this procedure you update the client application entry with
+ the MD5 fingerprint, which in this example is
+ <literal>48:AC:F9:13:11:E0:AB:C4:65:A2:83:9E:DB:FE:0C:37</literal>.</para>
+ <screen>$ keytool
+ -list
+ -v
+ -alias myapp-cert
+ -keystore keystore
+ -storepass changeit
+Alias name: myapp-cert
+Creation date: Jan 18, 2013
+Entry type: PrivateKeyEntry
+Certificate chain length: 1
+Certificate[1]:
+Owner: CN=My App, OU=Apps, DC=example, DC=com
+Issuer: CN=My App, OU=Apps, DC=example, DC=com
+Serial number: 5ae2277
+Valid from: Fri Jan 18 18:27:09 CET 2013 until: Thu Jan 13 18:27:09 CET 2033
+Certificate fingerprints:
+ MD5: 48:AC:F9:13:11:E0:AB:C4:65:A2:83:9E:DB:FE:0C:37
+ SHA1: F9:61:54:37:AA:C1:BC:92:45:07:64:4B:23:6C:BC:C9:CD:1D:44:0F
+ SHA256: 2D:B1:58:CD:33:40:E9:...:FD:61:EA:C9:FF:6A:19:93:FE:E4:84:E3
+ Signature algorithm name: SHA256withRSA
+ Version: 3
+
+Extensions:
+
+#1: ObjectId: 2.5.29.14 Criticality=false
+SubjectKeyIdentifier [
+KeyIdentifier [
+0000: 54 C0 C5 9C 73 37 85 4B F2 3B D3 37 FD 45 0A AB T...s7.K.;.7.E..
+0010: C9 6B 32 95 .k2.
+]
+]</screen>
+ </step>
+
+ <step>
+ <para>Export the certificate to a file in binary format.</para>
+
+ <screen>$ keytool
+ -export
+ -alias myapp-cert
+ -keystore keystore
+ -storepass changeit
+ -keypass changeit
+ -file myapp-cert.crt
+Certificate stored in file </path/to/myapp-cert.crt></screen>
+ </step>
+
+ <step>
+ <para>Modify the entry to add attributes related to the certificate.</para>
+
+ <para>By default, you need the <literal>userCertificate</literal>
+ value.</para>
+
+ <para>If you want OpenDJ to map the certificate to its fingerprint, use
+ <literal>ds-certificate-fingerprint</literal>. This example uses the MD5
+ fingerprint, which corresponds to the default setting for the Fingerprint
+ Certificate Mapper.</para>
+
+ <para>If you want to map the certificate subject DN to an attribute of the
+ entry, use <literal>ds-certificate-subject-dn</literal>.</para>
+
+ <screen>$ cat addcert.ldif
+dn: cn=My App,ou=Apps,dc=example,dc=com
+changetype: modify
+add: objectclass
+objectclass: ds-certificate-user
+-
+add: ds-certificate-fingerprint
+ds-certificate-fingerprint: 48:AC:F9:13:11:E0:AB:C4:65:A2:83:9E:DB:FE:0C:37
+-
+add: ds-certificate-subject-dn
+ds-certificate-subject-dn: CN=My App, OU=Apps, DC=example, DC=com
+-
+add: userCertificate;binary
+userCertificate;binary:<file:///path/to/myapp-cert.crt
+
+$ ldapmodify
+ --port 1389
+ --hostname opendj.example.com
+ --bindDN "cn=Directory Manager"
+ --bindPassword password
+ --filename addcert.ldif
+Processing MODIFY request for cn=My App,ou=Apps,dc=example,dc=com
+MODIFY operation successful for DN cn=My App,ou=Apps,dc=example,dc=com</screen>
+ </step>
+
+ <step>
+ <para>Check your work.</para>
+
+ <screen>$ ldapsearch
+ --port 1389
+ --hostname opendj.example.com
+ --baseDN dc=example,dc=com
+ "(cn=My App)"
+dn: cn=My App,ou=Apps,dc=example,dc=com
+ds-certificate-fingerprint: 4B:F5:CF:2C:2D:B3:86:14:FF:43:A8:37:17:DD:E7:55
+userCertificate;binary:: MIIDOzCCAiOgAwIBAgIESfC6IjANBgkqhkiG9w0BAQsFADBOMRMwEQY
+ KCZImiZPyLGQBGRYDY29tMRcwFQYKCZImiZPyLGQBGRYHZXhhbXBsZTENMAsGA1UECxMEQXBwczEPMA
+ 0GA1UEAxMGTXkgQXBwMB4XDTEzMDExNzE3MTEwM1oXDTEzMDQxNzE3MTEwM1owTjETMBEGCgmSJomT8
+ ixkARkWA2NvbTEXMBUGCgmSJomT8ixkARkWB2V4YW1wbGUxDTALBgNVBAsTBEFwcHMxDzANBgNVBAMT
+ Bk15IEFwcDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJQYq+jG4ZQdNkyBT4OQBZ0sFkl
+ X5o2yBViDMGl1sSWIRGLpFwu6iq1chndPBJYTC+FkT66yEEOwWOpSfcYdFHkMQP0qp5A8mgP6bYkeH1
+ ROvQ1nhLs0ILuksR10CVIQ5b1zv6bGEFhA9gSKmpHfQOSt9PXq8+kuz+4RgZk9Il28tgDNMm91wSJr7
+ kqi5g7a2a7Io5s9L2FeLhVSBYwinWQnASk8nENrhcE0hHkrpGsaxdhIQBQQvm+SRC0dI4E9iwBGI3Lw
+ lV3a4KTa5DlYD6cDREI6B8XlSdc1DaIhwC8CbsE0WJQoCERSURdjkuHrPck6f69HKUFRiC7JMT3dFbs
+ CAwEAAaMhMB8wHQYDVR0OBBYEFFTAxZxzN4VL8jvTN/1FCqvJazKVMA0GCSqGSIb3DQEBCwUAA4IBAQ
+ BXsAIEw7I5XUzLFHvXb2N0hmW/Vmhb/Vlv9LTT8JcCRJy4zaiyS9Q+Sp9zQUkrXauFnNAhJLwpAymjZ
+ MCOq1Th1bw9LnIzbccPQ/1+ZHLKDU5pgnc5BcvaV6Zl6COLLH2OOt0XMZ/OrODBV1M6STfhChqcowff
+ xp72pWMQe+kpZfzjeDBk4kK2hUNTZsimB9qRyrDAMCIXdmdmFv1o07orxjy8c/6S1329swiiVqFckBR
+ aXIa8wCcXjpQbZacDODeKk6wZIKxw4miLg1YByCMa7vkUfz+Jj+JHgbHjyoT/G82mtDbX02chLgXbDm
+ xJPFN3mwAC7NEkSPbqd35nJlf3
+objectClass: person
+objectClass: inetOrgPerson
+objectClass: organizationalPerson
+objectClass: ds-certificate-user
+objectClass: top
+ds-certificate-subject-dn: CN=My App, OU=Apps, DC=example, DC=com
+cn: My App
+sn: App</screen>
+ </step>
+
+ <step>
+ <para>When using a self-signed certificate, import the client certificate
+ into the trust store for OpenDJ.</para>
+
+ <para>When the client presents its certificate to OpenDJ, by default OpenDJ
+ has to be able to trust the client certificate before it can accept the
+ connection.</para>
+
+ <screen>$ keytool
+ -import
+ -alias myapp-cert
+ -file /path/to/myapp-cert.crt
+ -keystore /path/to/OpenDJ/config/truststore
+ -storepass `cat /path/to/OpenDJ/config/keystore.pin`
+Owner: CN=My App, OU=Apps, DC=example, DC=com
+Issuer: CN=My App, OU=Apps, DC=example, DC=com
+Serial number: 5ae2277
+Valid from: Fri Jan 18 18:27:09 CET 2013 until: Thu Jan 13 18:27:09 CET 2033
+Certificate fingerprints:
+ MD5: 48:AC:F9:13:11:E0:AB:C4:65:A2:83:9E:DB:FE:0C:37
+ SHA1: F9:61:54:37:AA:C1:BC:92:45:07:64:4B:23:6C:BC:C9:CD:1D:44:0F
+ SHA256: 2D:B1:58:CD:33:40:E9:...:FD:61:EA:C9:FF:6A:19:93:FE:E4:84:E3
+ Signature algorithm name: SHA256withRSA
+ Version: 3
+
+Extensions:
+
+#1: ObjectId: 2.5.29.14 Criticality=false
+SubjectKeyIdentifier [
+KeyIdentifier [
+0000: 54 C0 C5 9C 73 37 85 4B F2 3B D3 37 FD 45 0A AB T...s7.K.;.7.E..
+0010: C9 6B 32 95 .k2.
+]
+]
+
+Trust this certificate? [no]: yes
+Certificate was added to keystore</screen>
+ </step>
+
+ <step>
+ <para>When using a certificate signed by a CA whose certificate is not
+ delivered with the Java runtime environment<footnote>
+ <para><filename>$JAVA_HOME/jre/lib/security/cacerts</filename> holds the
+ certificates for many CAs. To get the full list, use the following
+ command.</para>
+ <screen>$ keytool
+ -list
+ -v
+ -keystore $JAVA_HOME/jre/lib/security/cacerts
+ -storepass changeit</screen></footnote>, import the CA certificate either
+ into the Java runtime environment trust store, or into the OpenDJ trust
+ store as shown in the following example.</para>
+
+ <screen>$ keytool
+ -import
+ -alias ca-cert
+ -file ca.crt
+ -keystore /path/to/OpenDJ/config/truststore
+ -storepass `cat /path/to/OpenDJ/config/keystore.pin`
+Owner: EMAILADDRESS=admin@example.com, CN=Example CA, O=Example Corp, C=FR
+Issuer: EMAILADDRESS=admin@example.com, CN=Example CA, O=Example Corp, C=FR
+Serial number: d4586ea05c878b0c
+Valid from: Tue Jan 29 09:30:31 CET 2013 until: Mon Jan 24 09:30:31 CET 2033
+Certificate fingerprints:
+ MD5: 8A:83:61:9B:E7:18:A2:21:CE:92:94:96:59:68:60:FA
+ SHA1: 01:99:18:38:3A:57:D7:92:7B:D6:03:8C:7B:E4:1D:37:45:0E:29:DA
+ SHA256: 5D:20:F1:86:CC:CD:64:50:1E:54:...:DF:15:43:07:69:44:00:FB:36:CF
+ Signature algorithm name: SHA1withRSA
+ Version: 3
+
+Extensions:
+
+#1: ObjectId: 2.5.29.35 Criticality=false
+AuthorityKeyIdentifier [
+KeyIdentifier [
+0000: 30 07 67 7D 1F 09 B6 E6 90 85 95 58 94 37 FD 31 0.g........X.7.1
+0010: 03 D4 56 7B ..V.
+]
+[EMAILADDRESS=admin@example.com, CN=Example CA, O=Example Corp, C=FR]
+SerialNumber: [ d4586ea0 5c878b0c]
+]
+
+#2: ObjectId: 2.5.29.19 Criticality=false
+BasicConstraints:[
+ CA:true
+ PathLen:2147483647
+]
+
+#3: ObjectId: 2.5.29.14 Criticality=false
+SubjectKeyIdentifier [
+KeyIdentifier [
+0000: 30 07 67 7D 1F 09 B6 E6 90 85 95 58 94 37 FD 31 0.g........X.7.1
+0010: 03 D4 56 7B ..V.
+]
+]
+
+Trust this certificate? [no]: yes
+Certificate was added to keystore</screen>
+ </step>
+
+ <step>
+ <para>If you updated the OpenDJ trust store to add a certificate, restart
+ OpenDJ to make sure it reads the updated trust store and can recognize the
+ certificate.</para>
+
+ <screen>$ stop-ds --restart
+Stopping Server...
+...
+... The Directory Server has started successfully</screen>
+ </step>
+ </procedure>
+
+ <procedure xml:id="config-cert-mappers">
+ <title>To Configure Certificate Mappers</title>
+
+ <variablelist>
+ <para>OpenDJ uses certificate mappers during binds to establish a mapping
+ between a client certificate and the entry that corresponds to that
+ certificate. The certificate mappers provided out of the box include the
+ following.</para>
+
+ <varlistentry>
+ <term>Fingerprint Certificate Mapper</term>
+ <listitem>
+ <para>Looks for the MD5 (default) or SHA1 certificate fingerprint in an
+ attribute of the entry (default:
+ <literal>ds-certificate-fingerprint</literal>).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Subject Attribute To User Attribute Mapper</term>
+ <listitem>
+ <para>Looks for a match between an attribute of the certificate subject
+ and an attribute of the entry (default: match <literal>cn</literal> in
+ the certificate to <literal>cn</literal> on the entry, or match
+ <literal>e</literal> in the certificate to <literal>mail</literal> on
+ the entry).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Subject DN to User Attribute Certificate Mapper</term>
+ <listitem>
+ <para>Looks for the certificate subject DN in an attribute of the entry
+ (default: <literal>ds-certificate-subject-dn</literal>).</para>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term>Subject Equals DN Certificate Mapper</term>
+ <listitem>
+ <para>Looks for an entry whose DN matches the certificate subject DN.</para>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ <para>If the default configurations for the certificate mappers are
+ acceptable, you do not need to change them. They are enabled by
+ default.</para>
+
+ <para>The following steps demonstrate how to change the Fingerprint Mapper
+ default algorithm of MD5 to SHA1.</para>
+
+ <step>
+ <para>List the certificate mappers to retrieve the correct name.</para>
+
+ <screen width="83">$ dsconfig
+ list-certificate-mappers
+ --port 4444
+ --hostname opendj.example.com
+ --bindDN "cn=Directory Manager"
+ --bindPassword password
+
+Certificate Mapper : Type : enabled
+------------------------------------:-------------------------------------:--------
+Fingerprint Mapper : fingerprint : true
+Subject Attribute to User Attribute : subject-attribute-to-user-attribute : true
+Subject DN to User Attribute : subject-dn-to-user-attribute : true
+Subject Equals DN : subject-equals-dn : true</screen>
+ </step>
+
+ <step>
+ <para>Examine the current configuration.</para>
+
+ <screen>$ dsconfig
+ get-certificate-mapper-prop
+ --port 4444
+ --hostname opendj.example.com
+ --bindDN "cn=Directory Manager"
+ --bindPassword password
+ --mapper-name "Fingerprint Mapper"
+
+Property : Value(s)
+----------------------:---------------------------
+enabled : true
+fingerprint-algorithm : md5
+fingerprint-attribute : ds-certificate-fingerprint
+user-base-dn : -</screen>
+ </step>
+
+ <step>
+ <para>Change the configuration as necessary.</para>
+
+ <screen>$ dsconfig
+ set-certificate-mapper-prop
+ --port 4444
+ --hostname opendj.example.com
+ --bindDN "cn=Directory Manager"
+ --bindPassword password
+ --mapper-name "Fingerprint Mapper"
+ --set fingerprint-algorithm:sha1
+ --no-prompt</screen>
+ </step>
+
+ <step>
+ <para>Set the External SASL Mechanism Handler to use the appropriate
+ certificate mapper (default: Subject Equals DN).</para>
+
+ <para>Clients applications use the SASL External mechanism during the bind
+ to have OpenDJ set the authorization identifier based on the entry that
+ matches the client certificate.</para>
+
+ <screen>$ dsconfig
+ set-sasl-mechanism-handler-prop
+ --port 4444
+ --hostname opendj.example.com
+ --bindDN "cn=Directory Manager"
+ --bindPassword password
+ --handler-name External
+ --set certificate-mapper:"Fingerprint Mapper"
+ --no-prompt</screen>
+ </step>
+ </procedure>
+
+ <example xml:id="auth-with-client-cert"><?dbfo keep-together="auto"?>
+ <title>Authenticate With Client Certificate</title>
+
+ <para>Instead of providing a bind DN and password as for simple
+ authentication, use the SASL EXTERNAL authentication mechanism, and provide
+ the certificate. As a test with example data you can try an anonymous search,
+ and then try with certificate-based authentication.</para>
+
+ <para>Before you try this example, make sure OpenDJ is set up to accept
+ StartTLS from clients, and that you have set up the client certificate
+ as described above. Next, create a password .pin file for your client key
+ store.</para>
+
+ <screen>$ echo changeit > keystore.pin
+$ chmod 400 keystore.pin</screen>
+
+ <para>Also, if OpenDJ directory server uses a certificate for StartTLS that
+ was not signed by a well-known CA, import the appropriate certificate into
+ the client key store, which can then double as a trust store. For example,
+ if OpenDJ uses a self-signed certificate, import the server certificate into
+ the key store.</para>
+
+ <screen>$ keytool
+ -export
+ -alias server-cert
+ -file server-cert.crt
+ -keystore /path/to/OpenDJ/config/keystore
+ -storepass `cat /path/to/OpenDJ/config/keystore.pin`
+$ keytool
+ -import
+ -trustcacerts
+ -alias server-cert
+ -file server-cert.crt
+ -keystore keystore
+ -storepass `cat keystore.pin`</screen>
+
+ <para>If OpenDJ directory server uses a CA-signed certificate, but the CA is
+ not well known, import the CA certificate into your keystore.</para>
+
+ <screen>$ keytool
+ -import
+ -trustcacerts
+ -alias ca-cert
+ -file ca-cert.crt
+ -keystore keystore
+ -storepass `cat keystore.pin`</screen>
+
+ <para>Now that you can try the example, notice that OpenDJ does not return
+ the <literal>userPassword</literal> value for an anonymous search.</para>
+
+ <screen>$ ldapsearch
+ --port 1389
+ --hostname opendj.example.com
+ --baseDN dc=example,dc=com
+ --useStartTLS
+ --trustStorePath keystore
+ --trustStorePasswordFile keystore.pin
+ "(cn=My App)" userPassword
+dn: cn=My App,ou=Apps,dc=example,dc=com
+</screen>
+
+ <para>OpenDJ does let users read the values of their own
+ <literal>userPassword</literal> attributes after they bind
+ successfully.</para>
+
+ <screen>$ ldapsearch
+ --port 1389
+ --hostname opendj.example.com
+ --baseDN dc=example,dc=com
+ --useStartTLS
+ --useSASLExternal
+ --certNickName myapp-cert
+ --keyStorePath keystore
+ --keyStorePasswordFile keystore.pin
+ --trustStorePath keystore
+ --trustStorePasswordFile keystore.pin
+ "(cn=My App)" userPassword
+dn: cn=My App,ou=Apps,dc=example,dc=com
+userPassword: {SSHA}vy/vTthOQoV/wH3MciTOBKKR4OX+0dSN/a09Ew==</screen>
+
+ <para>You can also try the same test with other certificate mappers.</para>
+
+ <screen># Fingerprint mapper
+$ dsconfig
+ set-sasl-mechanism-handler-prop
+ --port 4444
+ --hostname opendj.example.com
+ --bindDN "cn=Directory Manager"
+ --bindPassword password
+ --handler-name External
+ --set certificate-mapper:"Fingerprint Mapper"
+ --no-prompt
+$ ldapsearch
+ --port 1389
+ --hostname opendj.example.com
+ --baseDN dc=example,dc=com
+ --useStartTLS
+ --useSASLExternal
+ --certNickName myapp-cert
+ --keyStorePath keystore
+ --keyStorePasswordFile keystore.pin
+ --trustStorePath keystore
+ --trustStorePasswordFile keystore.pin
+ "(cn=My App)" userPassword
+dn: cn=My App,ou=Apps,dc=example,dc=com
+userPassword: {SSHA}vy/vTthOQoV/wH3MciTOBKKR4OX+0dSN/a09Ew==
+
+# Subject Attribute to User Attribute mapper
+$ dsconfig
+ set-sasl-mechanism-handler-prop
+ --port 4444
+ --hostname opendj.example.com
+ --bindDN "cn=Directory Manager"
+ --bindPassword password
+ --handler-name External
+ --set certificate-mapper:"Subject Attribute to User Attribute"
+ --no-prompt
+$ ldapsearch
+ --port 1389
+ --hostname opendj.example.com
+ --baseDN dc=example,dc=com
+ --useStartTLS
+ --useSASLExternal
+ --certNickName myapp-cert
+ --keyStorePath keystore
+ --keyStorePasswordFile keystore.pin
+ --trustStorePath keystore
+ --trustStorePasswordFile keystore.pin
+ "(cn=My App)" userPassword
+dn: cn=My App,ou=Apps,dc=example,dc=com
+userPassword: {SSHA}vy/vTthOQoV/wH3MciTOBKKR4OX+0dSN/a09Ew==
+
+# Subject DN to User Attribute mapper
+$ dsconfig
+ set-sasl-mechanism-handler-prop
+ --port 4444
+ --hostname opendj.example.com
+ --bindDN "cn=Directory Manager"
+ --bindPassword password
+ --handler-name External
+ --set certificate-mapper:"Subject DN to User Attribute"
+ --no-prompt
+$ ldapsearch
+ --port 1389
+ --hostname opendj.example.com
+ --baseDN dc=example,dc=com
+ --useStartTLS
+ --useSASLExternal
+ --certNickName myapp-cert
+ --keyStorePath keystore
+ --keyStorePasswordFile keystore.pin
+ --trustStorePath keystore
+ --trustStorePasswordFile keystore.pin
+ "(cn=My App)" userPassword
+dn: cn=My App,ou=Apps,dc=example,dc=com
+userPassword: {SSHA}vy/vTthOQoV/wH3MciTOBKKR4OX+0dSN/a09Ew==</screen>
+ </example>
+ </section>
</chapter>
diff --git a/opendj3/src/main/docbkx/admin-guide/chap-listeners.xml b/opendj3/src/main/docbkx/admin-guide/chap-listeners.xml
index 6ca45b6..7b2ccee 100644
--- a/opendj3/src/main/docbkx/admin-guide/chap-listeners.xml
+++ b/opendj3/src/main/docbkx/admin-guide/chap-listeners.xml
@@ -20,7 +20,7 @@
!
! CCPL HEADER END
!
- ! Copyright 2011-2012 ForgeRock AS
+ ! Copyright 2011-2013 ForgeRock AS
!
-->
<chapter xml:id='chap-listeners'
@@ -99,20 +99,356 @@
<title>Preparing For Secure Communications</title>
<subtitle>Setting Up a Self-Signed Certificate</subtitle>
<indexterm><primary>Certificates</primary></indexterm>
- <para>You can set up a self-signed certificate as part of the OpenDJ
- installation process. You can also choose to import your own CA-signed
- certificate as part of the installation process.</para>
-
- <para>Other applications recognize certificates signed by CAs whose root
- certificates are installed already. If you need your server certificate to
- be recognized automagically by applications configured to use SSL out of the
- box, then use a CA-signed certificate.</para>
-
- <para>Yet for testing purposes self-signed certificates can be a cheap
- alternative. This section covers how to set up a self-signed certificate
- after installation. With the self-signed certificate you can set up, for
- example, secure communications with StartTLS and over LDAPS.</para>
-
+
+ <para>One common way to protect connections between OpenDJ and client
+ applications involves using StartTLS for LDAP or LDAPS to secure
+ connections. OpenDJ and client applications use X.509 digital certificates
+ to set up secure connections.</para>
+
+ <para>Both OpenDJ and client applications check that certificates are signed
+ by a trusted party before accepting them. Merely setting up a secure
+ connection therefore involves a sort of authentication using certificates.
+ If either OpenDJ or the client application cannot trust the peer certificate,
+ then the attempt to set up a secure connection must fail.</para>
+
+ <para>By default OpenDJ client tools prompt you if they do not recognize the
+ server certificate. Other clients might not prompt you. OpenDJ server has no
+ one to prompt when a client presents a certificate that cannot be
+ trusted, so it must simply refuse to set up the
+ connection.<footnote><para>Unless you use the Blind Trust Manager
+ Provider, which is recommended only for test purposes.</para></footnote>
+ In other words, it is important for both OpenDJ and client applications
+ to be able to verify that peer certificates exchanged have been signed by
+ a trusted party.</para>
+
+ <para>In practice this means that both OpenDJ and client applications must
+ have the certificates used to sign each others' certificates in their
+ respective trust stores. Conventionally, certificates are therefore signed by
+ a Certificate Authority (CA). A CA is trusted to sign other certificates. The
+ Java runtime environment for example comes with a trust store holding
+ certificates from many well-known CAs.<footnote><para><filename
+ >$JAVA_HOME/jre/lib/security/cacerts</filename> holds the CA certificates.
+ To read the full list, use the following command.</para>
+ <screen>$ keytool
+ -list
+ -v
+ -keystore $JAVA_HOME/jre/lib/security/cacerts
+ -storepass changeit</screen></footnote> If your client uses a valid
+ certificate signed by one of these CAs, then OpenDJ can verify the
+ certificate without additional configuration, because OpenDJ can find
+ the CA certificate in the Java CA certificate trust store. Likewise if
+ you set up StartTLS or LDAPS in OpenDJ using a valid certificate signed
+ by one of these CAs, then many client applications can verify the OpenDJ
+ server certificate without further configuration.</para>
+
+ <para>In summary, if you need a certificate to be recognized automatically,
+ then use a CA-signed certificate from a well-known CA.</para>
+
+ <para>You can, however, choose to have your certificates signed some other
+ way. You can set up your own CA. You can use a CA whose signing certificate
+ is not widely distributed. You can also use self-signed certificates. In each
+ case, you must add the signing certificates into the trust store of each
+ peer making secure connections.</para>
+
+ <para>For OpenDJ directory server, you can choose to import your own CA-signed
+ certificate as part of the installation process, or later using command-line
+ tools. Alternatively, you can let the OpenDJ installation program create a
+ self-signed certificate as part of the OpenDJ installation process. In
+ addition, you can add a signing certificate to the OpenDJ trust store using
+ the Java <command>keytool</command> command.</para>
+
+ <para>The following example shows the <command>keytool</command> command to
+ add a client application's binary format, self-signed certificate to the
+ OpenDJ trust store (assuming OpenDJ is already configured to use secure
+ connections). This enables OpenDJ to recognize the self-signed client
+ application certificate. (By definition a self-signed certificate is itself
+ the signing certificate. Notice that the Owner and the Issuer are the
+ same.)</para>
+
+ <screen>$ keytool
+ -import
+ -alias myapp-cert
+ -file myapp-cert.crt
+ -keystore /path/to/OpenDJ/config/truststore
+ -storepass `cat /path/to/OpenDJ/config/keystore.pin`
+Owner: CN=My App, OU=Apps, DC=example, DC=com
+Issuer: CN=My App, OU=Apps, DC=example, DC=com
+Serial number: 5ae2277
+Valid from: Fri Jan 18 18:27:09 CET 2013 until: Thu Jan 13 18:27:09 CET 2033
+Certificate fingerprints:
+ MD5: 48:AC:F9:13:11:E0:AB:C4:65:A2:83:9E:DB:FE:0C:37
+ SHA1: F9:61:54:37:AA:C1:BC:92:45:07:64:4B:23:6C:BC:C9:CD:1D:44:0F
+ SHA256: 2D:B1:58:CD:33:40:E9:ED:...:EA:C9:FF:6A:19:93:FE:E4:84:E3
+ Signature algorithm name: SHA256withRSA
+ Version: 3
+
+Extensions:
+
+#1: ObjectId: 2.5.29.14 Criticality=false
+SubjectKeyIdentifier [
+KeyIdentifier [
+0000: 54 C0 C5 9C 73 37 85 4B F2 3B D3 37 FD 45 0A AB T...s7.K.;.7.E..
+0010: C9 6B 32 95 .k2.
+]
+]
+
+Trust this certificate? [no]: yes
+Certificate was added to keystore</screen>
+
+ <para>When working with a certificate in printable encoding format (.pem)
+ rather than binary format, use the keytool <option>-rfc</option> option,
+ too.</para>
+
+ <para>Restart OpenDJ after adding certificates to the trust store to make
+ sure that OpenDJ reads the updated trust store file.</para>
+
+ <para>On the client side, if your applications are also Java applications,
+ then you can also import the OpenDJ signing certificate into the trust
+ store for the applications using the <command>keytool</command>
+ command.</para>
+
+ <para>The following example shows the <command>keytool</command> command
+ to export the OpenDJ self-signed certificate in binary format.</para>
+
+ <screen>$ keytool
+ -export
+ -alias server-cert
+ -file server-cert.crt
+ -keystore /path/to/OpenDJ/config/keystore
+ -storepass `cat /path/to/OpenDJ/config/keystore.pin`
+Certificate stored in file <server-cert.crt></screen>
+
+ <para>Importing the server certificate is similar to importing the client
+ certificate, as shown above.</para>
+
+ <para>The following sections describe how to get and install certificates
+ for OpenDJ directory server on the command line, for use when setting up
+ StartTLS or LDAPS.</para>
+
+ <procedure xml:id="new-ca-signed-cert">
+ <title>To Request and Install a CA-Signed Certificate</title>
+
+ <para>First you create a server certificate in a Java Key Store. Next you
+ issue a signing request to the CA, and get the CA-signed certificate as a
+ reply. Then you set up the Key Manager Provider and Trust Manager Provider
+ to rely on your new server certificate stored in the OpenDJ key store.</para>
+
+ <step>
+ <para>Generate the server certificate by using the Java
+ <command>keytool</command> command.</para>
+
+ <para>The CN attribute value is the FQDN for OpenDJ directory server, which
+ you can see under Server Details in the OpenDJ Control Panel.</para>
+
+ <screen>$ keytool
+ -genkey
+ -alias server-cert
+ -keyalg rsa
+ -dname "CN=opendj.example.com,O=Example Corp,C=FR"
+ -keystore /path/to/OpenDJ/config/keystore
+ -storepass changeit
+ -keypass changeit</screen>
+
+ <note><para>Notice that the <option>-storepass</option> and
+ <option>-keypass</option> options take identical password arguments.
+ OpenDJ requires that you use the same password to protect both the keystore
+ and also the private key.</para></note>
+ </step>
+
+ <step>
+ <para>Create a certificate signing request file for the certificate you
+ generated.</para>
+
+ <screen>$ keytool
+ -certreq
+ -alias server-cert
+ -keystore /path/to/OpenDJ/config/keystore
+ -storepass changeit
+ -file server-cert.csr</screen>
+ </step>
+
+ <step>
+ <para>Have the CA sign the request
+ (<filename>server-cert.csr</filename>).</para>
+ <para>See the instructions from your CA on how to provide the
+ request.</para>
+ <para>The CA returns the signed certificate.</para>
+
+ <!-- Create a CA cert for signing certificates.
+
+Not part of the procedure, but helpful when trying this out:
+http://social.rocho.org/jan/selfsign.html
+
+$ openssl genrsa -des3 -out ca.key 4096
+Generating RSA private key, 4096 bit long modulus
+.....++
+.......................++
+e is 65537 (0x10001)
+Enter pass phrase for ca.key:
+Verifying - Enter pass phrase for ca.key:
+
+$ openssl req -new -x509 -days 7300 -key ca.key -out ca.crt
+Enter pass phrase for ca.key:
+You are about to be asked to enter information that will be incorporated
+into your certificate request.
+What you are about to enter is what is called a Distinguished Name or a DN.
+There are quite a few fields but you can leave some blank
+For some fields there will be a default value,
+If you enter '.', the field will be left blank.
+
+Country Name (2 letter code) [AU]:FR
+State or Province Name (full name) [Some-State]:
+Locality Name (eg, city) []:Grenoble
+Organization Name (eg, company) [Internet Widgits Pty Ltd]:Example Corp
+Organizational Unit Name (eg, section) []:
+Common Name (eg, YOUR name) []:Example CA
+Email Address []:mark.craig@forgerock.com
+
+$ openssl x509 -req -in server-cert.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out server-cert.crt
+Signature ok
+subject=/C=FR/O=Example Corp/CN=openam.example.com
+Getting CA Private Key
+Enter pass phrase for ca.key:
+
+$ openssl x509 -req -in myapp-cert.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out myapp-cert.crt
+Signature ok
+subject=/DC=com/DC=example/OU=Apps/CN=My App
+Getting CA Private Key
+Enter pass phrase for ca.key:
+
+-->
+ </step>
+
+ <step>
+ <para>If you have set up your own CA and signed the certificate, or are
+ using a CA whose signing certificate is not included in the Java runtime
+ environment, import the CA certificate into the key store so that it can be
+ trusted.</para>
+
+ <para>Otherwise, when you import the signed certificate in the reply from
+ the (unknown) CA, <command>keytool</command> fails to import the signed
+ certificate with the message <literal>keytool error: java.lang.Exception:
+ Failed to establish chain from reply</literal>.</para>
+
+ <para>The following example illustrates import of a CA certificate created
+ with the <command>openssl</command> command. See the
+ <command>openssl</command> documentation for instructions on creating CAs
+ and on signing other certificates with the CA you created.</para>
+
+ <screen>$ keytool
+ -import
+ -keystore /path/to/OpenDJ/config/keystore
+ -file ca.crt
+ -alias ca-cert
+ -storepass changeit
+Owner: EMAILADDRESS=admin@example.com, CN=Example CA, O=Example Corp, C=FR
+Issuer: EMAILADDRESS=admin@example.com, CN=Example CA, O=Example Corp, C=FR
+Serial number: d4586ea05c878b0c
+Valid from: Tue Jan 29 09:30:31 CET 2013 until: Mon Jan 24 09:30:31 CET 2033
+Certificate fingerprints:
+ MD5: 8A:83:61:9B:E7:18:A2:21:CE:92:94:96:59:68:60:FA
+ SHA1: 01:99:18:38:3A:57:D7:92:7B:D6:03:8C:7B:E4:1D:37:45:0E:29:DA
+ SHA256: 5D:20:F1:86:CC:CD:64:50:...:DF:15:43:07:69:44:00:FB:36:CF
+ Signature algorithm name: SHA1withRSA
+ Version: 3
+
+Extensions:
+
+#1: ObjectId: 2.5.29.35 Criticality=false
+AuthorityKeyIdentifier [
+KeyIdentifier [
+0000: 30 07 67 7D 1F 09 B6 E6 90 85 95 58 94 37 FD 31 0.g........X.7.1
+0010: 03 D4 56 7B ..V.
+]
+[EMAILADDRESS=admin@example.com, CN=Example CA, O=Example Corp, C=FR]
+SerialNumber: [ d4586ea0 5c878b0c]
+]
+
+#2: ObjectId: 2.5.29.19 Criticality=false
+BasicConstraints:[
+ CA:true
+ PathLen:2147483647
+]
+
+#3: ObjectId: 2.5.29.14 Criticality=false
+SubjectKeyIdentifier [
+KeyIdentifier [
+0000: 30 07 67 7D 1F 09 B6 E6 90 85 95 58 94 37 FD 31 0.g........X.7.1
+0010: 03 D4 56 7B ..V.
+]
+]
+
+Trust this certificate? [no]: yes
+Certificate was added to keystore</screen>
+ </step>
+
+ <step>
+ <para>Import the signed certificate from the CA reply into the keystore
+ where you generated the server certificate.</para>
+
+ <para>In this example the certificate from the reply is
+ <filename>~/Downloads/server-cert.crt</filename>.</para>
+
+ <screen>$ keytool
+ -import
+ -trustcacerts
+ -alias server-cert
+ -file ~/Downloads/server-cert.crt
+ -keystore /path/to/OpenDJ/config/keystore
+ -storepass changeit
+ -keypass changeit
+Certificate reply was installed in keystore</screen>
+ </step>
+
+ <step>
+ <para>Configure the File Based Key Manager Provider for JKS to use the file
+ name and key store PIN that you set up with the <command>keytool</command>
+ command.</para>
+
+ <screen>$ dsconfig
+ set-key-manager-provider-prop
+ --hostname opendj.example.com
+ --port 4444
+ --bindDN "cn=Directory Manager"
+ --bindPassword password
+ --provider-name JKS
+ --set enabled:true
+ --set key-store-pin:changeit
+ --remove key-store-pin-file:config/keystore.pin
+ --trustAll
+ --no-prompt</screen>
+ </step>
+
+ <step>
+ <para>Configure the File Based Trust Manager Provider for JKS to use the
+ key store and PIN as well.</para>
+
+ <screen>$ dsconfig
+ set-trust-manager-provider-prop
+ --hostname opendj.example.com
+ --port 4444
+ --bindDN "cn=Directory Manager"
+ --bindPassword password
+ --provider-name JKS
+ --set enabled:true
+ --set trust-store-file:config/keystore
+ --set trust-store-pin:changeit
+ --trustAll
+ --no-prompt</screen>
+
+ <para>At this point, OpenDJ directory server can use your new CA-signed
+ certificate, for example for StartTLS and LDAPS connection handlers.</para>
+ </step>
+
+ <step>
+ <para>If you use a CA certificate that is not known to clients, such as a
+ CA that you set up yourself rather than a well-known CA whose certificate
+ is included with the client system, import the CA certificate into the
+ client application trust store. Otherwise the client application cannot
+ trust the signature on the OpenDJ CA-signed server certificate.</para>
+ </step>
+ </procedure>
+
<procedure xml:id="new-self-signed-cert">
<title>To Create & Install a Self-Signed Certificate</title>
@@ -128,7 +464,7 @@
-alias server-cert
-keyalg rsa
-dname "CN=opendj.example.com,O=Example Corp,C=FR"
- -keystore OpenDJ/config/keystore
+ -keystore /path/to/OpenDJ/config/keystore
-storepass changeit
-keypass changeit</screen>
<para>In this example, OpenDJ is running on a system with fully qualified
@@ -148,12 +484,12 @@
<screen>$ keytool
-selfcert
-alias server-cert
- -keystore OpenDJ/config/keystore
+ -keystore /path/to/OpenDJ/config/keystore
-storepass changeit</screen>
</step>
<step>
<para>Configure the File Based Key Manager Provider for JKS to use the
- filename and key store PIN that you set up with the
+ file name and key store PIN that you set up with the
<command>keytool</command> command.</para>
<screen>$ dsconfig
set-key-manager-provider-prop
--
Gitblit v1.10.0