mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

david_page
31.55.2007 894bcfabe2aac051adc47d9a2c6b2fcb7421c9d1
Issue 466 partial

Follow-on to commit r2858. ADSContext#updateServer is called by Installer#updateADS (via registerOrUpdateServer) in the case the server entry already exists in ADS. With this commit, updateServer checks 'cn=instance keys,cn=admin data' for an entry with the instance key public-key certificate of the server being (re)registered (or otherwise updated and the instance-key certificate server property is supplied). If the entry exists, it is used. Otherwise, a new entry is created. The new routine ADSContext#registerInstanceKeyCertificate contains the code common to registerServer and updateServer.

Note that the updateServer is not fully tested since I cannot figure out how to re-register an existing instance (i.e., unregister, but not uninstall, an instance; then re-register the instance so the existing instance-key entry is reused).

M src/ads/org/opends/admin/ads/ServerDescriptor.java
M src/ads/org/opends/admin/ads/ADSContext.java
2 files modified
146 ■■■■■ changed files
opends/src/ads/org/opends/admin/ads/ADSContext.java 126 ●●●●● patch | view | raw | blame | history
opends/src/ads/org/opends/admin/ads/ServerDescriptor.java 20 ●●●●● patch | view | raw | blame | history
opends/src/ads/org/opends/admin/ads/ADSContext.java
@@ -415,45 +415,13 @@
  {
    LdapName dn = makeDNFromServerProperties(serverProperties);
    BasicAttributes attrs = makeAttrsFromServerProperties(serverProperties);
    /* Instance key-pair public-key certificate: generate a key-id attribute
       for the server entry, then an instance key entry for the key. */
    LdapName keyDn = null;
    BasicAttributes keyAttrs = null;
    if (serverProperties.containsKey(ServerProperty.INSTANCE_KEY_CERT))
    {
      String keyID
              = (String)serverProperties.get(ServerProperty.INSTANCE_KEY_ID);
      if (null == keyID)
      {
        keyID = java.util.UUID.randomUUID().toString();
      }
      attrs.put(new BasicAttribute(
                       ServerProperty.INSTANCE_KEY_ID.getAttributeName(),
                       keyID));
      String rdnStr = Rdn.escapeValue(keyID);
      keyDn = nameFromDN(ServerProperty.INSTANCE_KEY_ID.getAttributeName()
                          + "=" + rdnStr + "," + getInstanceKeysContainerDN());
      keyAttrs = new BasicAttributes();
      Attribute oc = new BasicAttribute("objectclass");
      oc.add("top");
      oc.add("ds-cfg-instance-key-OID");
      keyAttrs.put(oc);
      keyAttrs.put(new BasicAttribute(
                          ServerProperty.INSTANCE_KEY_ID.getAttributeName(),
                          rdnStr));
      keyAttrs.put(new BasicAttribute(
              ServerProperty.INSTANCE_KEY_CERT.getAttributeName() + ";binary",
              serverProperties.get(ServerProperty.INSTANCE_KEY_CERT)));
    }
    try
    {
      DirContext ctx = dirContext.createSubcontext(dn, attrs);
      ctx.close();
      ctx = dirContext.createSubcontext(keyDn, keyAttrs);
      ctx.close();
      dirContext.createSubcontext(dn, attrs).close();
      if (serverProperties.containsKey(ServerProperty.INSTANCE_KEY_CERT))
      {
        registerInstanceKeyCertificate(serverProperties, dn);
      }
    }
    catch (NameAlreadyBoundException x)
    {
@@ -494,6 +462,10 @@
      BasicAttributes attrs = makeAttrsFromServerProperties(serverProperties);
      dirContext.modifyAttributes(dn, InitialLdapContext.REPLACE_ATTRIBUTE,
          attrs);
      if (serverProperties.containsKey(ServerProperty.INSTANCE_KEY_CERT))
      {
        registerInstanceKeyCertificate(serverProperties, dn);
      }
    }
    catch (NameNotFoundException x)
    {
@@ -508,7 +480,9 @@
  }
  /**
   * Method called to unregister a server in the ADS.
   * Method called to unregister a server in the ADS. Note that the server's
   * instance key-pair public-key certificate entry (created in registerServer)
   * is left untouched.
   * @param serverProperties the properties of the server.
   * @throws ADSContextException if the server could not be unregistered.
   */
@@ -1344,7 +1318,7 @@
        }
        else
        {
          privilegeAtt.add(p.toString());
          privilegeAtt.add(p);
        }
      }
    }
@@ -2050,4 +2024,78 @@
  {
    return "cn=instance keys," + getAdministrationSuffixDN();
  }
  /**
   Register instance key-pair public-key certificate provided in
   serverProperties: generate a key-id attribute if one is not provided (as
   expected); add an instance key public-key certificate entry for the key
   certificate; and associate the certificate entry with the server entry via
   the key ID attribute.
   @param serverProperties Properties of the server being registered to which
   the instance key entry belongs.
   @param serverEntryDn The server's ADS entry DN.
   @throws NamingException In case some JNDI operation fails.
   */
  private void registerInstanceKeyCertificate(
          Map<ServerProperty, Object> serverProperties,
          LdapName serverEntryDn) throws NamingException
  {
    assert serverProperties.containsKey(ServerProperty.INSTANCE_KEY_CERT);
    if (! serverProperties.containsKey(ServerProperty.INSTANCE_KEY_CERT)) {
      return;
    }
    /* the key ID might be supplied in serverProperties (although, I am unaware
       of any such case). */
    String keyID = (String)serverProperties.get(ServerProperty.INSTANCE_KEY_ID);
    /* these attributes are used both to search for an existing certificate
       entry and, if one does not exist, add a new certificate entry */
    final BasicAttributes keyAttrs = new BasicAttributes();
    final Attribute oc = new BasicAttribute("objectclass");
    oc.add("top"); oc.add("ds-cfg-instance-key");
    keyAttrs.put(oc);
    if (null != keyID) {
      keyAttrs.put(new BasicAttribute(
              ServerProperty.INSTANCE_KEY_ID.getAttributeName(), keyID));
    }
    keyAttrs.put(new BasicAttribute(
            ServerProperty.INSTANCE_KEY_CERT.getAttributeName() + ";binary",
            serverProperties.get(ServerProperty.INSTANCE_KEY_CERT)));
    /* search for public-key certificate entry in ADS DIT */
    final String attrIDs[] = { "ds-cfg-key-id" };
    final NamingEnumeration<SearchResult> results
           = dirContext.search(getInstanceKeysContainerDN(), keyAttrs, attrIDs);
    if (results.hasMore()) {
      final Attribute keyIdAttr
              = results.next().getAttributes().get(attrIDs[0]);
      if (null != keyIdAttr) {
        /* attribute ds-cfg-key-id is the entry is a MUST in the schema */
        keyID = (String)keyIdAttr.get();
      }
    }
    else {
      /* create key ID, if it was not supplied in serverProperties */
      if (null == keyID) {
        keyID = java.util.UUID.randomUUID().toString();
        keyAttrs.put(new BasicAttribute(
                ServerProperty.INSTANCE_KEY_ID.getAttributeName(), keyID));
      }
      /* add public-key certificate entry */
      final LdapName keyDn = new LdapName((new StringBuilder())
              .append(ServerProperty.INSTANCE_KEY_ID.getAttributeName())
              .append("=").append(Rdn.escapeValue(keyID)).append(",")
              .append(getInstanceKeysContainerDN()).toString());
      dirContext.createSubcontext(keyDn, keyAttrs).close();
    }
    /* associate server entry with certificate entry via key ID attribute */
    dirContext.modifyAttributes(serverEntryDn,
            InitialLdapContext.REPLACE_ATTRIBUTE,
            (new BasicAttributes(
                   ServerProperty.INSTANCE_KEY_ID.getAttributeName(), keyID)));
  }
}
opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
@@ -40,7 +40,6 @@
import javax.naming.directory.Attribute;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
@@ -841,8 +840,7 @@
       file for the installer and import it into the core. */
    final String dnStr = "ds-cfg-key-id=ads-certificate,cn=ads-truststore";
    final LdapName dn = new LdapName(dnStr);
    byte[] localInstanceKeyCertificate = null;
    for (int i = 0; null == localInstanceKeyCertificate && i < 2 ; ++i ) {
    for (int i = 0; i < 2 ; ++i) {
      /* If the entry does not exist in the instance's truststore backend, add
         it (which induces the CryptoManager to create the public-key
         certificate attribute), then repeat the search. */
@@ -852,12 +850,15 @@
        final String attrIDs[] = { "ds-cfg-public-key-certificate;binary" };
        sc.setReturningAttributes(attrIDs);
        final SearchResult certEntry
           = ctx.search(dn, "(objectclass=*)", sc).next();
        final Attribute certAttr = certEntry.getAttributes().get(
                                        "ds-cfg-public-key-certificate;binary");
           = ctx.search(dn, "(objectclass=ds-cfg-instance-key)", sc).next();
        final Attribute certAttr = certEntry.getAttributes().get(attrIDs[0]);
        if (null != certAttr) {
          localInstanceKeyCertificate = (byte[])certAttr.get();
          /* attribute ds-cfg-public-key-certificate is a MUST in the schema */
          desc.serverProperties.put(
                  ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE,
                  certAttr.get());
        }
        break;
      }
      catch (NameNotFoundException x) {
        if (0 == i) {
@@ -868,16 +869,13 @@
          oc.add("top");
          oc.add("ds-cfg-self-signed-cert-request");
          attrs.put(oc);
          DirContext pokeCtx = ctx.createSubcontext(dn, attrs);
          pokeCtx.close();
          ctx.createSubcontext(dn, attrs).close();
        }
        else {
          throw x;
        }
      }
    }
    desc.serverProperties.put(ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE,
            localInstanceKeyCertificate);
  }