<?xml version="1.0" encoding="UTF-8"?>
<!--
! CCPL HEADER START
!
! This work is licensed under the Creative Commons
! Attribution-NonCommercial-NoDerivs 3.0 Unported License.
! To view a copy of this license, visit
! http://creativecommons.org/licenses/by-nc-nd/3.0/
! or send a letter to Creative Commons, 444 Castro Street,
! Suite 900, Mountain View, California, 94041, USA.
!
! You can also obtain a copy of the license at
! trunk/opendj3/legal-notices/CC-BY-NC-ND.txt.
! See the License for the specific language governing permissions
! and limitations under the License.
!
! If applicable, add the following below this CCPL HEADER, with the fields
! enclosed by brackets "[]" replaced with your own identifying information:
! Portions Copyright [yyyy] [name of copyright owner]
!
! CCPL HEADER END
!
! Copyright 2013-2014 ForgeRock AS
!
-->
<chapter xml:id='chap-change-certs'
xmlns='http://docbook.org/ns/docbook' version='5.0' xml:lang='en'
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
xsi:schemaLocation='http://docbook.org/ns/docbook
http://docbook.org/xml/5.0/xsd/docbook.xsd'
xmlns:xlink='http://www.w3.org/1999/xlink'>
<title>Changing Server Certificates</title>
<indexterm><primary>Certificates</primary></indexterm>
<para>OpenDJ uses key stores (for private keys) and trust stores (for
public, signed certificates). Up to three sets of key stores are used,
as shown in the following illustration.</para>
<mediaobject xml:id="figure-keystores">
<imageobject>
<imagedata fileref="images/keystores.png" format="PNG" />
</imageobject>
<caption><para>OpenDJ uses different sets of public and private keys for
different secure connections.</para></caption>
</mediaobject>
<itemizedlist>
<para>By default the key stores are located in the
<filename>/path/to/opendj/config</filename> directory.</para>
<listitem>
<para>The <filename>keystore</filename> and <filename>truststore</filename>
hold keys for securing connections with client applications.</para>
</listitem>
<listitem>
<para>The <filename>admin-keystore</filename> and
<filename>admin-truststore</filename> hold keys for securing administrative
connections, such as those used when connecting with the
<command>dsconfig</command> command.</para>
</listitem>
<listitem>
<para>The <filename>ads-truststore</filename> holds keys for securing
replication connections with other OpenDJ servers in the replication
topology.</para>
</listitem>
</itemizedlist>
<variablelist>
<para>Each key store has a specific purpose.</para>
<varlistentry>
<term><filename>admin-keystore</filename></term>
<listitem>
<para>This Java Key Store holds the private key and administrative
certificate for the server, <literal>admin-cert</literal>. This key pair
is used to protect communications on the administration port. The password,
stored in <filename>admin-keystore.pin</filename>, is also the key password
for <literal>admin-cert</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>admin-truststore</filename></term>
<listitem>
<para>This Java Key Store holds a copy of the administrative certificate,
<literal>admin-cert</literal>. The password is the same as for the
<filename>admin-keystore</filename>, in other words the string in
<filename>admin-keystore.pin</filename>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>ads-truststore</filename></term>
<listitem>
<para>This Java Key Store holds public key certificates of all servers
replicating with the current server. It also includes the
<literal>ads-certificate</literal> key pair of the current server.
The password is stored in <filename>ads-truststore.pin</filename>.</para>
<para>Do not change this key store directly.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>keystore</filename></term>
<listitem>
<para>This Java Key Store holds the private key and server certificate,
<literal>server-cert</literal>, used to protect TLS/SSL communications
with client applications. The password, stored in
<filename>keystore.pin</filename>, is also the key password for
<literal>server-cert</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><filename>truststore</filename></term>
<listitem>
<para>This Java Key Store holds a copy of the <literal>server-cert</literal>
certificate from the <filename>keystore</filename>. This is also where you
import certificates of client applications if you want OpenDJ to recognize
them. The password is the same as for the <filename>keystore</filename>,
in other words the string in <filename>keystore.pin</filename>.</para>
</listitem>
</varlistentry>
</variablelist>
<tip>
<para>Examples in this chapter use self-signed certificates, but you can
also use certificates signed by a Certificate Authority (CA).</para>
<para>When importing a certificate (<command>keytool -import</command>)
signed by a well-known CA, use the <option>-trustcacerts</option> option
to trust the CA certificates delivered with the Java runtime
environment.</para>
</tip>
<procedure xml:id="replace-key-pair">
<title>To Replace a Server Key Pair</title>
<para>This procedure shows how to replace a server key pair in the
<filename>admin-keystore</filename> and copy of the administrative certificate
in <filename>admin-truststore</filename>.</para>
<para>The examples also apply when replacing a key pair in the
<filename>keystore</filename> and copy of the server certificate in
<filename>truststore</filename>. Just adapt the commands to use the correct
key store, trust store, and PIN file names.</para>
<para>This procedure does not apply for replication key pairs. Instead, see
<xref linkend="replace-ads-cert" />.</para>
<step>
<para>Check the alias of the key pair and certificate copy to replace.</para>
<screen>
$ <userinput>cd /path/to/opendj/config</userinput>
$ <userinput>keytool -list -keystore admin-keystore -storepass `cat admin-keystore.pin`</userinput>
<computeroutput>Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
admin-cert, Mar 15, 2013, PrivateKeyEntry,
Certificate fingerprint (SHA1): 54:9F:C3:F8:7B:B6:...:0A:98:D0:17:8E</computeroutput>
$ <userinput>keytool -list -keystore admin-truststore -storepass `cat admin-keystore.pin`</userinput>
<computeroutput>Keystore type: JKS
Keystore provider: SUN
Your keystore contains 1 entry
admin-cert, Mar 15, 2013, trustedCertEntry,
Certificate fingerprint (SHA1): 54:9F:C3:F8:7B:B6:...:0A:98:D0:17:8E</computeroutput>
</screen>
<para>This alias is also stored in the server configuration.</para>
</step>
<step>
<para>Remove the key pair and certificate copy to replace.</para>
<screen>
$ <userinput>keytool \
-delete \
-alias admin-cert \
-keystore admin-keystore \
-storepass `cat admin-keystore.pin`</userinput>
$ <userinput>keytool \
-delete \
-alias admin-cert \
-keystore admin-truststore \
-storepass `cat admin-keystore.pin`</userinput>
</screen>
</step>
<step>
<para>Generate a new key pair in the key store.</para>
<screen width="85">
$ <userinput>keytool \
-genkey \
-alias admin-cert \
-keyalg RSA \
-validity 7300 \
-keysize 2048 \
-ext "san=dns:opendj.example.com" \
-dname "CN=opendj.example.com, O=Administration Connector Self-Signed Certificate" \
-keystore admin-keystore \
-storepass `cat admin-keystore.pin` \
-keypass `cat admin-keystore.pin`</userinput>
</screen>
<para>Notice that the <option>-alias</option> option takes the same alias
as before. This is because the <literal>ssl-cert-nickname</literal> for
the Administration Connector is configured as <literal>admin-cert</literal>.
Also, the <option>-dname</option> option has a CN value corresponding to the
fully-qualified domain name of the host where OpenDJ directory server is
running.</para>
</step>
<step>
<para>Get the new key pair's certificate signed, using one of the following
alternatives.</para>
<stepalternatives>
<step>
<para>Self-sign the certificate.</para>
<screen>
$ <userinput>keytool \
-selfcert \
-alias admin-cert \
-keystore admin-keystore \
-storepass `cat admin-keystore.pin`</userinput>
</screen>
</step>
<step>
<para>Create a certificate signing request, have it signed by a CA, and
import the signed certificate from the CA reply.</para>
<para>For examples of the <command>keytool</command> commands to use, see
the procedure <link xlink:href="admin-guide#new-ca-signed-cert"
xlink:role="http://docbook.org/xlink/role/olink"><citetitle>To Request and
Install a CA-Signed Certificate</citetitle></link>.</para>
</step>
</stepalternatives>
</step>
<step>
<para>Export a copy of the certificate from the key store.</para>
<screen>
$ <userinput>keytool \
-export \
-alias admin-cert \
-keystore admin-keystore \
-storepass `cat admin-keystore.pin` \
-file admin-cert.crt</userinput>
<computeroutput>Certificate stored in file &lt;admin-cert.crt&gt;</computeroutput>
</screen>
</step>
<step>
<para>Import the copy of the certificate into the trust store.</para>
<screen width="81">
$ <userinput>keytool \
-import \
-alias admin-cert \
-keystore admin-truststore \
-storepass `cat admin-keystore.pin` \
-file admin-cert.crt</userinput>
<computeroutput>Owner: CN=opendj.example.com, O=Administration Connector Self-Signed Certificate
Issuer: CN=opendj.example.com, O=Administration Connector Self-Signed Certificate
Serial number: 904fc2b
Valid from: Fri Mar 15 15:15:20 CET 2013 until: Thu Jun 13 16:15:20 CEST 2013
Certificate fingerprints:
MD5: DD:2A:A1:3A:39:87:DF:02:15:A4:8A:9D:77:89:F1:E4
SHA1: E1:99:82:92:D7:9B:28:B7:93:D2:B5:5B:C9:DA:4E:D2:62:C2:E7:B0
SHA256: C5:34:9C:04:E2:87:A9:B1:72:B5:...:99:86:3A:02:28:D0:AB:02:5F:F4:BE
Signature algorithm name: SHA256withRSA
Version: 3
Extensions:
#1: ObjectId: 2.5.29.17 Criticality=false
SubjectAlternativeName [
DNSName: opendj.example.com
]
#2: ObjectId: 2.5.29.14 Criticality=false
SubjectKeyIdentifier [
KeyIdentifier [
0000: FE 33 69 67 FF E8 64 F6 D3 FB CD 14 1C D3 01 44 .3ig..d........D
0010: EE 62 40 DD .b@.
]
]
Trust this certificate? [no]:</computeroutput> <userinput>yes</userinput>
<computeroutput>Certificate was added to keystore</computeroutput>
</screen>
</step>
<step>
<para>Restart OpenDJ to make sure it reloads the key stores.</para>
<screen>
$ <userinput>cd /path/to/opendj/bin</userinput>
$ <userinput>stop-ds --restart</userinput>
</screen>
</step>
<step>
<para>If you have client applications trusting the self-signed certificate,
have them import the new one (<filename>admin-cert.crt</filename> in this
example).</para>
</step>
</procedure>
<procedure xml:id="replace-ads-cert">
<title>To Replace the Key Pair Used for Replication</title>
<para>Follow these steps to replace the key pair that is used to
secure replication connections.</para>
<step>
<para>Generate a new key pair for the server.</para>
<para>The changes you perform are replicated across the topology.</para>
<para>OpenDJ has an <literal>ads-certificate</literal> and private
key, which is a local copy of the key pair used to secure replication
connections.</para>
<para>To generate the new key pair, you remove the
<literal>ads-certificate</literal> key pair, prompt OpenDJ to
generate a new <literal>ads-certificate</literal> key pair, and
then add a copy to the administrative data using the MD5 fingerprint
of the certificate to define the RDN.</para>
<substeps>
<step>
<para>Delete the <literal>ads-certificate</literal> entry.</para>
<screen>
$ <userinput>ldapmodify \
--port 1389 \
--hostname opendj.example.com \
--bindDN "cn=Directory Manager" \
--bindPassword password</userinput>
<computeroutput>dn: ds-cfg-key-id=ads-certificate,cn=ads-truststore
changetype: delete
Processing DELETE request for ds-cfg-key-id=ads-certificate,cn=ads-truststore
DELETE operation successful for DN ds-cfg-key-id=ads-certificate,
cn=ads-truststore</computeroutput>
</screen>
</step>
<step>
<para>Prompt OpenDJ to generate a new, self-signed
<literal>ads-certificate</literal> key pair.</para>
<para>You do this by adding an <literal>ads-certificate</literal> entry
with object class <literal>ds-cfg-self-signed-cert-request</literal>.</para>
<screen>
$ <userinput>ldapmodify \
--port 1389 \
--hostname opendj.example.com \
--bindDN "cn=Directory Manager" \
--bindPassword password</userinput>
<computeroutput>dn: ds-cfg-key-id=ads-certificate,cn=ads-truststore
changetype: add
objectclass: ds-cfg-self-signed-cert-request
Processing ADD request for ds-cfg-key-id=ads-certificate,cn=ads-truststore
ADD operation successful for DN ds-cfg-key-id=ads-certificate,cn=ads-truststore</computeroutput>
</screen>
</step>
<step>
<para>Retrieve the <literal>ads-certificate</literal> entry.</para>
<screen>
$ <userinput>ldapsearch \
--port 1389 \
--hostname opendj.example.com \
--baseDN cn=ads-truststore \
"(ds-cfg-key-id=ads-certificate)"</userinput>
<computeroutput>dn: ds-cfg-key-id=ads-certificate,cn=ads-truststore
ds-cfg-key-id: ads-certificate
ds-cfg-public-key-certificate;binary:: MIIB6zCCAVSgAwIBAgIEDKSUFjANBgkqhkiG9w0BA
QUFADA6MRswGQYDVQQKExJPcGVuREogQ2VydGlmaWNhdGUxGzAZBgNVBAMTEm9wZW5hbS5leGFtcGxl
LmNvbTAeFw0xMzAyMDcxMDMwMzNaFw0zMzAyMDIxMDMwMzNaMDoxGzAZBgNVBAoTEk9wZW5ESiBDZXJ
0aWZpY2F0ZTEbMBkGA1UEAxMSb3BlbmFtLmV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNAD
CBiQKBgQCfGLAiUOz4sC8CM9T5DPTk9V9ErNC8N59XwBt1aN7UjhQl4/JZZsetubtUrZBLS9cRrnYdZ
cpFgLQNEmXifS+PdZ0DJkaLNFmd8ZX0spX8++fb4SkkggkmNRmi1fccDQ/DHMlwl7kk884lXummrzcD
GbZ7p4vnY7y7GmD1vZSP+wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAJciUzUP8T8A9VV6dQB0SYCNG1o
7IvpE7jGVZh6KvM0m5sBNX3wPbTVJQNij3TDm8nx6yhi6DUkpiAZfz/OBL5k+WSw80TjpIZ2+klhP1s
srsST4Um4fHzDZXOXHR6NM83XxZBsR6MazYecL8CiGwnYW2AeBapzbAnGn1J831q1q
objectClass: top
objectClass: ds-cfg-instance-key</computeroutput>
</screen>
</step>
<step>
<para>Retrieve the MD5 fingerprint of the
<literal>ads-certificate</literal>.</para>
<para>In this example, the MD5 fingerprint is
<literal>07:35:80:D8:F3:CE:E1:39:9C:D0:73:DB:6C:FA:CC:1C</literal>.</para>
<screen>
$ <userinput>keytool \
-list \
-v \
-alias ads-certificate \
-keystore /path/to/opendj/config/ads-truststore \
-storepass `cat /path/to/opendj/config/ads-truststore.pin`</userinput>
<computeroutput>Alias name: ads-certificate
Creation date: Feb 7, 2013
Entry type: PrivateKeyEntry
Certificate chain length: 1
Certificate[1]:
Owner: CN=opendj.example.com, O=OpenDJ Certificate
Issuer: CN=opendj.example.com, O=OpenDJ Certificate
Serial number: ca49416
Valid from: Thu Feb 07 11:30:33 CET 2013 until: Wed Feb 02 11:30:33 CET 2033
Certificate fingerprints:
MD5: 07:35:80:D8:F3:CE:E1:39:9C:D0:73:DB:6C:FA:CC:1C
SHA1: 56:30:F6:79:AA:C0:BD:61:88:3E:FB:38:38:9D:84:70:0B:E4:43:57
SHA256: A8:4B:81:EE:30:2A:0C:09:2E:...:C1:41:F5:AB:19:C6:EE:AB:50:64
Signature algorithm name: SHA1withRSA
Version: 3</computeroutput>
</screen>
</step>
<step>
<para>Using the MD5 fingerprint and the certificate entry, prepare LDIF
to update <literal>cn=admin data</literal> with the new server
certificate.</para>
<screen>
$ <userinput>cat /path/to/update-server-cert.ldif</userinput>
<computeroutput>dn: ds-cfg-key-id=073580D8F3CEE1399CD073DB6CFACC1C,cn=instance keys,
cn=admin data
changetype: add
ds-cfg-key-id: 073580D8F3CEE1399CD073DB6CFACC1C
ds-cfg-public-key-certificate;binary:: MIIB6zCCAVSgAwIBAgIEDKSUFjANBgkqhkiG9w0BA
QUFADA6MRswGQYDVQQKExJPcGVuREogQ2VydGlmaWNhdGUxGzAZBgNVBAMTEm9wZW5hbS5leGFtcGxl
LmNvbTAeFw0xMzAyMDcxMDMwMzNaFw0zMzAyMDIxMDMwMzNaMDoxGzAZBgNVBAoTEk9wZW5ESiBDZXJ
0aWZpY2F0ZTEbMBkGA1UEAxMSb3BlbmFtLmV4YW1wbGUuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNAD
CBiQKBgQCfGLAiUOz4sC8CM9T5DPTk9V9ErNC8N59XwBt1aN7UjhQl4/JZZsetubtUrZBLS9cRrnYdZ
cpFgLQNEmXifS+PdZ0DJkaLNFmd8ZX0spX8++fb4SkkggkmNRmi1fccDQ/DHMlwl7kk884lXummrzcD
GbZ7p4vnY7y7GmD1vZSP+wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAJciUzUP8T8A9VV6dQB0SYCNG1o
7IvpE7jGVZh6KvM0m5sBNX3wPbTVJQNij3TDm8nx6yhi6DUkpiAZfz/OBL5k+WSw80TjpIZ2+klhP1s
srsST4Um4fHzDZXOXHR6NM83XxZBsR6MazYecL8CiGwnYW2AeBapzbAnGn1J831q1q
objectClass: top
objectClass: ds-cfg-instance-key
dn: cn=opendj.example.com:4444,cn=Servers,cn=admin data
changetype: modify
replace: ds-cfg-key-id
ds-cfg-key-id: 073580D8F3CEE1399CD073DB6CFACC1C
</computeroutput>
</screen>
</step>
<step>
<para>Update the administrative data, causing OpenDJ to create a
copy of the new <literal>ads-certificate</literal> with its MD5 signature
as the alias in the <filename>ads-truststore</filename>.</para>
<screen>
$ <userinput>ldapmodify \
--port 1389 \
--hostname opendj.example.com \
--bindDN "cn=Directory Manager" \
--bindPassword password \
--filename /path/to/update-server-cert.ldif</userinput>
<computeroutput>Processing ADD request for ds-cfg-key-id=073580D8F3CEE1399CD073DB6CFACC1C,
cn=instance keys,cn=admin data
ADD operation successful for DN ds-cfg-key-id=073580D8F3CEE1399CD073DB6CFACC1C,
cn=instance keys,cn=admin data
Processing MODIFY request for cn=opendj.example.com:4444,cn=Servers,
cn=admin data
MODIFY operation successful for DN cn=opendj.example.com:4444,cn=Servers,
cn=admin data</computeroutput>
</screen>
</step>
</substeps>
</step>
<step>
<para>Force OpenDJ to reopen replication connections using the new key
pair.</para>
<para>Stop replication temporarily and then start it again as described
in the <citetitle>Administration Guide</citetitle> section on <link
xlink:show="new"
xlink:href="admin-guide#configure-repl"
xlink:role="http://docbook.org/xlink/role/olink"
><citetitle>Configuring Replication</citetitle></link>.</para>
<screen>
$ <userinput>dsconfig \
set-synchronization-provider-prop \
--port 4444 \
--hostname opendj.example.com \
--bindDN "cn=Directory Manager" \
--bindPassword password \
--provider-name "Multimaster Synchronization" \
--set enabled:false \
--no-prompt</userinput>
$ <userinput>dsconfig \
set-synchronization-provider-prop \
--port 4444 \
--hostname opendj.example.com \
--bindDN "cn=Directory Manager" \
--bindPassword password \
--provider-name "Multimaster Synchronization" \
--set enabled:true \
--no-prompt</userinput>
</screen>
</step>
</procedure>
</chapter>