From 812381739ee2294c75db4b3db9f3c15a0541e59d Mon Sep 17 00:00:00 2001
From: Endi Sukma Dewata <edewata@redhat.com>
Date: Thu, 6 Sep 2012 16:33:48 -0500
Subject: [PATCH] Enabled authentication for security domain REST interface.

The REST interface for security domain has been refactored and
configured such that it requires authentication. A CLI has been
added to get an installation token.

Ticket #309
---
 CMakeLists.txt                                     |   4 +-
 base/ca/shared/webapps/ca/WEB-INF/auth.properties  |   1 +
 base/ca/shared/webapps/ca/WEB-INF/web.xml          |  13 +++
 .../ca/CertificateAuthorityApplication.java        |  15 +++
 .../com/netscape/certsrv/system/InstallToken.java  |   7 +-
 .../certsrv/system/InstallTokenRequest.java        |  99 ------------------
 ...ConfigClient.java => SecurityDomainClient.java} |  17 ++--
 ...nfigClient.java => SecurityDomainResource.java} |  37 +++----
 .../certsrv/system/SystemConfigClient.java         |   4 -
 .../certsrv/system/SystemConfigResource.java       |   6 --
 .../com/netscape/cms/authorization/AAclAuthz.java  |   4 +-
 .../cms/servlet/csadmin/ConfigurationUtils.java    |  13 ++-
 .../servlet/csadmin/SecurityDomainProcessor.java   | 112 +++++++++++++++++++++
 .../cms/servlet/csadmin/SecurityDomainService.java |  44 ++++++++
 .../cms/servlet/csadmin/SystemConfigService.java   |  34 -------
 .../src/com/netscape/cmstools/cli/MainCLI.java     |   2 +
 .../cmstools/system/SecurityDomainCLI.java         |  93 +++++++++++++++++
 .../system/SecurityDomainGetInstallTokenCLI.java   |  86 ++++++++++++++++
 18 files changed, 400 insertions(+), 191 deletions(-)
 delete mode 100644 base/common/src/com/netscape/certsrv/system/InstallTokenRequest.java
 copy base/common/src/com/netscape/certsrv/system/{SystemConfigClient.java => SecurityDomainClient.java} (67%)
 copy base/common/src/com/netscape/certsrv/system/{SystemConfigClient.java => SecurityDomainResource.java} (56%)
 create mode 100644 base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainProcessor.java
 create mode 100644 base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainService.java
 create mode 100644 base/java-tools/src/com/netscape/cmstools/system/SecurityDomainCLI.java
 create mode 100644 base/java-tools/src/com/netscape/cmstools/system/SecurityDomainGetInstallTokenCLI.java

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3bb5be00bfdca0ba06000d76b78344db1a0361d3..2f3dd86daa6a446c0b6a9555082d52ed400ae39d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,9 +6,9 @@ cmake_minimum_required(VERSION 2.6.0)
 # global needed variables
 set(APPLICATION_NAME ${PROJECT_NAME})
 
-if (NOT ${VERSION})
+if (NOT DEFINED ${VERSION})
     set(VERSION "10.0.0")
-endif(NOT ${VERSION})
+endif(NOT DEFINED ${VERSION})
 
 string(REGEX REPLACE "^([0-9]+).*" "\\1" APPLICATION_VERSION_MAJOR ${VERSION})
 string(REGEX REPLACE "^[0-9]+\\.([0-9]+).*" "\\1" APPLICATION_VERSION_MINOR ${VERSION})
diff --git a/base/ca/shared/webapps/ca/WEB-INF/auth.properties b/base/ca/shared/webapps/ca/WEB-INF/auth.properties
index ebb1c6c3fd6a80addf52575d3bbfda21c352312a..b1379576042b5e95d5fdbfdf2dcf11c981f3d542 100644
--- a/base/ca/shared/webapps/ca/WEB-INF/auth.properties
+++ b/base/ca/shared/webapps/ca/WEB-INF/auth.properties
@@ -7,3 +7,4 @@
 /ca/rest/admin/users = certServer.ca.users,execute
 /ca/rest/admin/groups = certServer.ca.groups,execute
 /ca/rest/agent/certs = certServer.ca.certs,execute
+/ca/rest/securityDomain/installToken = certServer.securitydomain.domainxml,read
diff --git a/base/ca/shared/webapps/ca/WEB-INF/web.xml b/base/ca/shared/webapps/ca/WEB-INF/web.xml
index c1b2738c833024a33f73e1ab5669340bc644f63b..9f876e5c24a1c53754698899f0e1ae6bdec6618e 100644
--- a/base/ca/shared/webapps/ca/WEB-INF/web.xml
+++ b/base/ca/shared/webapps/ca/WEB-INF/web.xml
@@ -2411,6 +2411,19 @@
         </user-data-constraint>
     </security-constraint>
 
+    <security-constraint>
+        <web-resource-collection>
+            <web-resource-name>Security Domain Services</web-resource-name>
+            <url-pattern>/rest/securityDomain/installToken</url-pattern>
+        </web-resource-collection>
+        <auth-constraint>
+            <role-name>*</role-name>
+        </auth-constraint>
+        <user-data-constraint>
+            <transport-guarantee>CONFIDENTIAL</transport-guarantee>
+        </user-data-constraint>
+    </security-constraint>
+
     <login-config>
         <realm-name>Certificate Authority</realm-name>
     </login-config>
diff --git a/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java b/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java
index bb6431907ee77c9ff7890b8c18fae95d96adf129..51d48cf5ed384d5707530ab4dfe5ad12f0785166 100644
--- a/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java
+++ b/base/ca/src/com/netscape/ca/CertificateAuthorityApplication.java
@@ -5,6 +5,9 @@ import java.util.Set;
 
 import javax.ws.rs.core.Application;
 
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.IConfigStore;
 import com.netscape.certsrv.base.PKIException;
 import com.netscape.cms.servlet.admin.GroupMemberService;
 import com.netscape.cms.servlet.admin.GroupService;
@@ -12,6 +15,7 @@ import com.netscape.cms.servlet.admin.SystemCertService;
 import com.netscape.cms.servlet.admin.UserCertService;
 import com.netscape.cms.servlet.admin.UserService;
 import com.netscape.cms.servlet.cert.CertService;
+import com.netscape.cms.servlet.csadmin.SecurityDomainService;
 import com.netscape.cms.servlet.csadmin.SystemConfigService;
 import com.netscape.cms.servlet.profile.ProfileService;
 import com.netscape.cms.servlet.request.CertRequestService;
@@ -40,6 +44,17 @@ public class CertificateAuthorityApplication extends Application {
         // system certs
         classes.add(SystemCertService.class);
 
+        // security domain
+        try {
+            IConfigStore cs = CMS.getConfigStore();
+            String select = cs.getString("securitydomain.select");
+            if ("new".equals(select)) {
+                classes.add(SecurityDomainService.class);
+            }
+        } catch (EBaseException e) {
+            CMS.debug(e);
+        }
+
         // exception mapper
         classes.add(PKIException.Mapper.class);
     }
diff --git a/base/common/src/com/netscape/certsrv/system/InstallToken.java b/base/common/src/com/netscape/certsrv/system/InstallToken.java
index aa34893a1f71c09288f33aa98f98e637ae20bae9..06accc3f2ea36a1e7732751b07b978316d2b29bb 100644
--- a/base/common/src/com/netscape/certsrv/system/InstallToken.java
+++ b/base/common/src/com/netscape/certsrv/system/InstallToken.java
@@ -14,7 +14,7 @@
 //
 // (C) 2012 Red Hat, Inc.
 // All rights reserved.
-// --- END COPYRIGHT BLOCK --- 
+// --- END COPYRIGHT BLOCK ---
 package com.netscape.certsrv.system;
 
 import javax.xml.bind.annotation.XmlAccessType;
@@ -26,16 +26,17 @@ import javax.xml.bind.annotation.XmlRootElement;
  * @author alee
  *
  */
-@XmlRootElement(name="CertData")
+@XmlRootElement(name="InstallToken")
 @XmlAccessorType(XmlAccessType.FIELD)
 public class InstallToken {
+
     @XmlElement
     private String token;
 
     public InstallToken(String token) {
         this.token = token;
     }
-    
+
     public InstallToken() {
         // required by jaxb
     }
diff --git a/base/common/src/com/netscape/certsrv/system/InstallTokenRequest.java b/base/common/src/com/netscape/certsrv/system/InstallTokenRequest.java
deleted file mode 100644
index bc000a96a9eb19f88919ab41789557f7469fd5aa..0000000000000000000000000000000000000000
--- a/base/common/src/com/netscape/certsrv/system/InstallTokenRequest.java
+++ /dev/null
@@ -1,99 +0,0 @@
-// --- BEGIN COPYRIGHT BLOCK ---
-// This program is free software; you can redistribute it and/or modify
-// it under the terms of the GNU General Public License as published by
-// the Free Software Foundation; version 2 of the License.
-//
-// 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 along
-// with this program; if not, write to the Free Software Foundation, Inc.,
-// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
-//
-// (C) 2012 Red Hat, Inc.
-// All rights reserved.
-// --- END COPYRIGHT BLOCK --- 
-package com.netscape.certsrv.system;
-
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlRootElement;
-import javax.xml.bind.annotation.XmlAccessType;
-
-/**
- * @author alee
- *
- */
-@XmlRootElement(name="InstallTokenRequest")
-@XmlAccessorType(XmlAccessType.FIELD)
-public class InstallTokenRequest {
-    @XmlElement
-    private String user;
-    
-    @XmlElement
-    private String password;
-    
-    @XmlElement
-    private String subsystem;
-    
-    @XmlElement
-    private String host;
-    
-    @XmlElement
-    private String port;
-
-    public InstallTokenRequest(String user, String password, String subsystem, String host, String port) {
-        this.user = user;
-        this.password = password;
-        this.subsystem = subsystem;
-        this.host = host;
-        this.port = port;
-    }
-
-    public InstallTokenRequest() {
-        // required for jaxb
-    }
-
-    public String getUser() {
-        return user;
-    }
-
-    public void setUser(String user) {
-        this.user = user;
-    }
-
-    public String getPassword() {
-        return password;
-    }
-
-    public void setPassword(String password) {
-        this.password = password;
-    }
-
-    public String getSubsystem() {
-        return subsystem;
-    }
-
-    public void setSubsystem(String subsystem) {
-        this.subsystem = subsystem;
-    }
-
-    public String getHost() {
-        return host;
-    }
-
-    public void setHost(String host) {
-        this.host = host;
-    }
-
-    public String getPort() {
-        return port;
-    }
-
-    public void setPort(String port) {
-        this.port = port;
-    }
-    
-}
diff --git a/base/common/src/com/netscape/certsrv/system/SystemConfigClient.java b/base/common/src/com/netscape/certsrv/system/SecurityDomainClient.java
similarity index 67%
copy from base/common/src/com/netscape/certsrv/system/SystemConfigClient.java
copy to base/common/src/com/netscape/certsrv/system/SecurityDomainClient.java
index 876ed9bacc85d6da90eeddf38463852d8ac7a3d9..fd7eb342b68634594657837864565a5522b56016 100644
--- a/base/common/src/com/netscape/certsrv/system/SystemConfigClient.java
+++ b/base/common/src/com/netscape/certsrv/system/SecurityDomainClient.java
@@ -25,23 +25,18 @@ import com.netscape.certsrv.client.PKIClient;
 
 /**
  * @author alee
- *
  */
-public class SystemConfigClient extends PKIClient {
+public class SecurityDomainClient extends PKIClient {
 
-    private SystemConfigResource configClient;
+    private SecurityDomainResource client;
 
-    public SystemConfigClient(ClientConfig config) throws URISyntaxException {
+    public SecurityDomainClient(ClientConfig config) throws URISyntaxException {
         super(config);
 
-        configClient = createProxy(SystemConfigResource.class);
+        client = createProxy(SecurityDomainResource.class);
     }
 
-    public ConfigurationResponse configure(ConfigurationRequest data) {
-        return configClient.configure(data);
-    }
-
-    public InstallToken getInstallToken(InstallTokenRequest data) {
-        return configClient.getInstallToken(data);
+    public InstallToken getInstallToken(String hostname, String subsystem) {
+        return client.getInstallToken(hostname, subsystem);
     }
 }
diff --git a/base/common/src/com/netscape/certsrv/system/SystemConfigClient.java b/base/common/src/com/netscape/certsrv/system/SecurityDomainResource.java
similarity index 56%
copy from base/common/src/com/netscape/certsrv/system/SystemConfigClient.java
copy to base/common/src/com/netscape/certsrv/system/SecurityDomainResource.java
index 876ed9bacc85d6da90eeddf38463852d8ac7a3d9..41bbf779ea2e2e4da0e3054f571dbd5ee3f2d812 100644
--- a/base/common/src/com/netscape/certsrv/system/SystemConfigClient.java
+++ b/base/common/src/com/netscape/certsrv/system/SecurityDomainResource.java
@@ -17,31 +17,22 @@
 // --- END COPYRIGHT BLOCK ---
 package com.netscape.certsrv.system;
 
-import java.net.URISyntaxException;
-
-import com.netscape.certsrv.client.ClientConfig;
-import com.netscape.certsrv.client.PKIClient;
-
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
 
 /**
  * @author alee
- *
  */
-public class SystemConfigClient extends PKIClient {
-
-    private SystemConfigResource configClient;
-
-    public SystemConfigClient(ClientConfig config) throws URISyntaxException {
-        super(config);
-
-        configClient = createProxy(SystemConfigResource.class);
-    }
-
-    public ConfigurationResponse configure(ConfigurationRequest data) {
-        return configClient.configure(data);
-    }
-
-    public InstallToken getInstallToken(InstallTokenRequest data) {
-        return configClient.getInstallToken(data);
-    }
+@Path("securityDomain")
+public interface SecurityDomainResource {
+
+    @GET
+    @Path("installToken")
+    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
+    public InstallToken getInstallToken(
+            @QueryParam("hostname") String hostname,
+            @QueryParam("subsystem") String subsystem);
 }
diff --git a/base/common/src/com/netscape/certsrv/system/SystemConfigClient.java b/base/common/src/com/netscape/certsrv/system/SystemConfigClient.java
index 876ed9bacc85d6da90eeddf38463852d8ac7a3d9..fd14bbe19efda2d742d9c03939d3f96753a36d4f 100644
--- a/base/common/src/com/netscape/certsrv/system/SystemConfigClient.java
+++ b/base/common/src/com/netscape/certsrv/system/SystemConfigClient.java
@@ -40,8 +40,4 @@ public class SystemConfigClient extends PKIClient {
     public ConfigurationResponse configure(ConfigurationRequest data) {
         return configClient.configure(data);
     }
-
-    public InstallToken getInstallToken(InstallTokenRequest data) {
-        return configClient.getInstallToken(data);
-    }
 }
diff --git a/base/common/src/com/netscape/certsrv/system/SystemConfigResource.java b/base/common/src/com/netscape/certsrv/system/SystemConfigResource.java
index 4ecafc6f779dcc9ffe8577b30b629a8d8b1a5834..ca06ededb2ac4bc3fcdba83334c09041c7d62888 100644
--- a/base/common/src/com/netscape/certsrv/system/SystemConfigResource.java
+++ b/base/common/src/com/netscape/certsrv/system/SystemConfigResource.java
@@ -44,12 +44,6 @@ public interface SystemConfigResource {
     @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
     public ConfigurationResponse configure(ConfigurationRequest data);
 
-    @POST
-    @Path("installToken")
-    @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    @Consumes({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
-    public InstallToken getInstallToken(InstallTokenRequest data);
-
     @GET
     @Path("domainInfo")
     @Produces({ MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON })
diff --git a/base/common/src/com/netscape/cms/authorization/AAclAuthz.java b/base/common/src/com/netscape/cms/authorization/AAclAuthz.java
index b47956fb3bdd87832d0edd36e1ad574bc8adfe42..089cca9bea9f7cfcdac65f6023060109eb6b8d10 100644
--- a/base/common/src/com/netscape/cms/authorization/AAclAuthz.java
+++ b/base/common/src/com/netscape/cms/authorization/AAclAuthz.java
@@ -521,7 +521,7 @@ public abstract class AAclAuthz {
             log(ILogger.LL_INFO, infoMsg);
             return;
         } else {
-            Object[] params = new Object[2];
+            String[] params = new String[2];
 
             params[0] = name;
             params[1] = perm;
@@ -530,7 +530,7 @@ public abstract class AAclAuthz {
                     CMS.getLogMessage("AUTHZ_EVALUATOR_ACCESS_DENIED", name, perm));
 
             throw new EACLsException(CMS.getUserMessage("CMS_ACL_NO_PERMISSION",
-                        (String[]) params));
+                        params));
         }
     }
 
diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
index 89233bdc2f82c842ee3add8b7a311865bac9202c..531fc212faf735f3b5b9ac7b2f60eee6abd83676 100644
--- a/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
+++ b/base/common/src/com/netscape/cms/servlet/csadmin/ConfigurationUtils.java
@@ -146,8 +146,7 @@ import com.netscape.certsrv.ldap.ILdapConnFactory;
 import com.netscape.certsrv.ocsp.IDefStore;
 import com.netscape.certsrv.ocsp.IOCSPAuthority;
 import com.netscape.certsrv.system.InstallToken;
-import com.netscape.certsrv.system.InstallTokenRequest;
-import com.netscape.certsrv.system.SystemConfigClient;
+import com.netscape.certsrv.system.SecurityDomainClient;
 import com.netscape.certsrv.usrgrp.EUsrGrpException;
 import com.netscape.certsrv.usrgrp.IGroup;
 import com.netscape.certsrv.usrgrp.IUGSubsystem;
@@ -322,17 +321,17 @@ public class ConfigurationUtils {
         }
         String csType = cs.getString("cs.type");
 
-        InstallTokenRequest data = new InstallTokenRequest(user, passwd, csType, CMS.getEEHost(), CMS.getAdminPort());
-
         ClientConfig config = new ClientConfig();
         config.setServerURI("https://" + sdhost + ":" + sdport + "/ca");
+        config.setUsername(user);
+        config.setPassword(passwd);
 
-        SystemConfigClient client = new SystemConfigClient(config);
+        SecurityDomainClient client = new SecurityDomainClient(config);
 
-        InstallToken token = null;
         try {
-            token = client.getInstallToken(data);
+            InstallToken token = client.getInstallToken(sdhost, csType);
             return token.getToken();
+
         } catch (ClientResponseFailure e) {
             if (e.getResponse().getResponseStatus() == Response.Status.NOT_FOUND) {
                 // try the old servlet
diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainProcessor.java b/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainProcessor.java
new file mode 100644
index 0000000000000000000000000000000000000000..f6cb4c63850918a36a0edba5c8c4b349c2c1800b
--- /dev/null
+++ b/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainProcessor.java
@@ -0,0 +1,112 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// 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 along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import java.net.InetAddress;
+import java.util.Locale;
+import java.util.Random;
+
+import com.netscape.certsrv.apps.CMS;
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.EPropertyNotFound;
+import com.netscape.certsrv.base.ISecurityDomainSessionTable;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.base.UnauthorizedException;
+import com.netscape.certsrv.logging.ILogger;
+import com.netscape.certsrv.system.InstallToken;
+import com.netscape.cms.servlet.processors.Processor;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class SecurityDomainProcessor extends Processor {
+
+    private final static String LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE =
+            "LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE_1";
+
+    Random random = new Random();
+
+    public SecurityDomainProcessor(Locale locale) throws EPropertyNotFound, EBaseException {
+        super("securitydomain", locale);
+    }
+
+    public InstallToken getInstallToken(
+            String user,
+            String hostname,
+            String subsystem) throws EBaseException {
+
+        String groupname = ConfigurationUtils.getGroupName(user, subsystem);
+
+        if (groupname == null) {
+            String message = CMS.getLogMessage(
+                    LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+                    user,
+                    ILogger.FAILURE,
+                    "Enterprise " + subsystem + " Administrators");
+            audit(message);
+
+            throw new UnauthorizedException("Access denied.");
+        }
+
+        String message = CMS.getLogMessage(
+                LOGGING_SIGNED_AUDIT_ROLE_ASSUME,
+                user,
+                ILogger.SUCCESS,
+                groupname);
+        audit(message);
+
+        String ip = "";
+        try {
+            ip = InetAddress.getByName(hostname).getHostAddress();
+        } catch (Exception e) {
+            CMS.debug("Unable to determine IP address for "+hostname);
+        }
+
+        // assign cookie
+        Long num = random.nextLong();
+        String cookie = num.toString();
+
+        String auditParams = "operation;;issue_token+token;;" + cookie + "+ip;;" + ip +
+                      "+uid;;" + user + "+groupname;;" + groupname;
+
+        ISecurityDomainSessionTable ctable = CMS.getSecurityDomainSessionTable();
+        int status = ctable.addEntry(cookie, ip, user, groupname);
+
+        if (status == ISecurityDomainSessionTable.SUCCESS) {
+            message = CMS.getLogMessage(
+                               LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE,
+                               user,
+                               ILogger.SUCCESS,
+                               auditParams);
+            audit(message);
+
+        } else {
+            message = CMS.getLogMessage(
+                               LOGGING_SIGNED_AUDIT_SECURITY_DOMAIN_UPDATE,
+                               user,
+                               ILogger.FAILURE,
+                               auditParams);
+            audit(message);
+
+            throw new PKIException("Failed to update security domain.");
+        }
+
+
+        return new InstallToken(cookie);
+    }
+}
diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainService.java b/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainService.java
new file mode 100644
index 0000000000000000000000000000000000000000..3a2bac49c1c00f9c1a6002635ce92255f4cc2a17
--- /dev/null
+++ b/base/common/src/com/netscape/cms/servlet/csadmin/SecurityDomainService.java
@@ -0,0 +1,44 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// 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 along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+package com.netscape.cms.servlet.csadmin;
+
+import com.netscape.certsrv.base.EBaseException;
+import com.netscape.certsrv.base.PKIException;
+import com.netscape.certsrv.system.InstallToken;
+import com.netscape.certsrv.system.SecurityDomainResource;
+import com.netscape.cms.servlet.base.PKIService;
+
+/**
+ * @author alee
+ */
+public class SecurityDomainService extends PKIService implements SecurityDomainResource {
+
+    @Override
+    public InstallToken getInstallToken(String hostname, String subsystem) {
+        try {
+            // Get uid from realm authentication.
+            String user = servletRequest.getUserPrincipal().getName();
+
+            SecurityDomainProcessor processor = new SecurityDomainProcessor(getLocale());
+            return processor.getInstallToken(user, hostname, subsystem);
+
+        } catch (EBaseException e) {
+            throw new PKIException(e.getMessage(), e);
+        }
+    }
+}
diff --git a/base/common/src/com/netscape/cms/servlet/csadmin/SystemConfigService.java b/base/common/src/com/netscape/cms/servlet/csadmin/SystemConfigService.java
index 3bbe3ca8099f0e722271e9bf7ae21812bffb5404..8bc3c59467f4f6e3155bce6705cc06b3809ffbdf 100644
--- a/base/common/src/com/netscape/cms/servlet/csadmin/SystemConfigService.java
+++ b/base/common/src/com/netscape/cms/servlet/csadmin/SystemConfigService.java
@@ -18,10 +18,8 @@
 package com.netscape.cms.servlet.csadmin;
 
 import java.math.BigInteger;
-import java.net.InetAddress;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.net.UnknownHostException;
 import java.security.NoSuchAlgorithmException;
 import java.util.Collection;
 import java.util.Enumeration;
@@ -46,7 +44,6 @@ import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.EPropertyNotFound;
 import com.netscape.certsrv.base.IConfigStore;
-import com.netscape.certsrv.base.ISecurityDomainSessionTable;
 import com.netscape.certsrv.base.PKIException;
 import com.netscape.certsrv.ca.ICertificateAuthority;
 import com.netscape.certsrv.dbs.certdb.ICertificateRepository;
@@ -54,8 +51,6 @@ import com.netscape.certsrv.ocsp.IOCSPAuthority;
 import com.netscape.certsrv.system.ConfigurationRequest;
 import com.netscape.certsrv.system.ConfigurationResponse;
 import com.netscape.certsrv.system.DomainInfo;
-import com.netscape.certsrv.system.InstallToken;
-import com.netscape.certsrv.system.InstallTokenRequest;
 import com.netscape.certsrv.system.SystemCertData;
 import com.netscape.certsrv.system.SystemConfigResource;
 import com.netscape.certsrv.usrgrp.IUGSubsystem;
@@ -909,35 +904,6 @@ public class SystemConfigService extends PKIService implements SystemConfigResou
     }
 
     @Override
-    public InstallToken getInstallToken(InstallTokenRequest data) {
-        // TODO Figure out how to do authentication here based on user/pass
-        // For now, allow all user/pass to be valid
-        CMS.debug("getInstallToken(): starting");
-        String user = data.getUser();
-        String host = data.getHost();
-        String subsystem = data.getSubsystem();
-        String groupname = ConfigurationUtils.getGroupName(user, subsystem);
-
-        // assign cookie
-        long num = random.nextLong();
-        String cookie = num + "";
-        ISecurityDomainSessionTable ctable = CMS.getSecurityDomainSessionTable();
-        String ip;
-        try {
-            ip = InetAddress.getByName(host).toString();
-        } catch (UnknownHostException e) {
-            throw new PKIException(Response.Status.BAD_REQUEST, "Unable to resolve host " + host +
-                    "to an IP address: " + e);
-        }
-        int index = ip.indexOf("/");
-        if (index > 0)  ip = ip.substring(index + 1);
-
-        ctable.addEntry(cookie, ip, user, groupname);
-
-        return new InstallToken(cookie);
-    }
-
-    @Override
     public DomainInfo getDomainInfo() {
         // TODO Auto-generated method stub for a RESTful method that returns the security domain
         return null;
diff --git a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
index 44ccf95110364e44427af4daee49f35308b89dab..bcc3bb27e4dff1a0046e89279183e88fb6197ce9 100644
--- a/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
+++ b/base/java-tools/src/com/netscape/cmstools/cli/MainCLI.java
@@ -33,6 +33,7 @@ import org.mozilla.jss.util.Password;
 import com.netscape.certsrv.client.ClientConfig;
 import com.netscape.cmstools.cert.CertCLI;
 import com.netscape.cmstools.group.GroupCLI;
+import com.netscape.cmstools.system.SecurityDomainCLI;
 import com.netscape.cmstools.user.UserCLI;
 
 /**
@@ -47,6 +48,7 @@ public class MainCLI extends CLI {
 
         addModule(new CertCLI(this));
         addModule(new GroupCLI(this));
+        addModule(new SecurityDomainCLI(this));
         addModule(new UserCLI(this));
     }
 
diff --git a/base/java-tools/src/com/netscape/cmstools/system/SecurityDomainCLI.java b/base/java-tools/src/com/netscape/cmstools/system/SecurityDomainCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..93c4c4b631e50770edba457fecff41e338c947f6
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/system/SecurityDomainCLI.java
@@ -0,0 +1,93 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// 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 along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cmstools.system;
+
+import java.util.Arrays;
+
+import org.apache.commons.lang.StringUtils;
+
+import com.netscape.certsrv.system.SecurityDomainClient;
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class SecurityDomainCLI extends CLI {
+
+    public MainCLI parent;
+    public SecurityDomainClient client;
+
+    public SecurityDomainCLI(MainCLI parent) {
+        super("securitydomain", "Security domain commands");
+        this.parent = parent;
+
+        addModule(new SecurityDomainGetInstallTokenCLI(this));
+    }
+
+    public void printHelp() {
+
+        System.out.println("Commands:");
+
+        int leftPadding = 1;
+        int rightPadding = 25;
+
+        for (CLI module : modules.values()) {
+            String label = name + "-" + module.getName();
+
+            int padding = rightPadding - leftPadding - label.length();
+            if (padding < 1)
+                padding = 1;
+
+            System.out.print(StringUtils.repeat(" ", leftPadding));
+            System.out.print(label);
+            System.out.print(StringUtils.repeat(" ", padding));
+            System.out.println(module.getDescription());
+        }
+    }
+
+    public void execute(String[] args) throws Exception {
+
+        client = new SecurityDomainClient(parent.config);
+        client.setVerbose(verbose);
+
+        if (args.length == 0) {
+            printHelp();
+            System.exit(1);
+        }
+
+        String command = args[0];
+        String[] commandArgs = Arrays.copyOfRange(args, 1, args.length);
+
+        if (command == null) {
+            printHelp();
+            System.exit(1);
+        }
+
+        CLI module = getModule(command);
+        if (module != null) {
+            module.execute(commandArgs);
+
+        } else {
+            System.err.println("Error: Invalid command \"" + command + "\"");
+            printHelp();
+            System.exit(1);
+        }
+    }
+}
diff --git a/base/java-tools/src/com/netscape/cmstools/system/SecurityDomainGetInstallTokenCLI.java b/base/java-tools/src/com/netscape/cmstools/system/SecurityDomainGetInstallTokenCLI.java
new file mode 100644
index 0000000000000000000000000000000000000000..15b8def2a88d16680896c56a96f9c7d219b61895
--- /dev/null
+++ b/base/java-tools/src/com/netscape/cmstools/system/SecurityDomainGetInstallTokenCLI.java
@@ -0,0 +1,86 @@
+// --- BEGIN COPYRIGHT BLOCK ---
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; version 2 of the License.
+//
+// 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 along
+// with this program; if not, write to the Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+//
+// (C) 2012 Red Hat, Inc.
+// All rights reserved.
+// --- END COPYRIGHT BLOCK ---
+
+package com.netscape.cmstools.system;
+
+import java.net.InetAddress;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.Option;
+
+import com.netscape.certsrv.system.InstallToken;
+import com.netscape.cmstools.cli.CLI;
+import com.netscape.cmstools.cli.MainCLI;
+
+/**
+ * @author Endi S. Dewata
+ */
+public class SecurityDomainGetInstallTokenCLI extends CLI {
+
+    public SecurityDomainCLI parent;
+
+    public SecurityDomainGetInstallTokenCLI(SecurityDomainCLI parent) {
+        super("get-install-token", "Get install token");
+        this.parent = parent;
+    }
+
+    public void printHelp() {
+        formatter.printHelp(parent.name + "-" + name, options);
+    }
+
+    public void execute(String[] args) throws Exception {
+
+        Option option = new Option(null, "hostname", true, "Hostname");
+        option.setArgName("hostname");
+        options.addOption(option);
+
+        option = new Option(null, "subsystem", true, "Subsystem");
+        option.setArgName("subsystem");
+        option.setRequired(true);
+        options.addOption(option);
+
+        CommandLine cmd = null;
+
+        try {
+            cmd = parser.parse(options, args);
+
+        } catch (Exception e) {
+            System.err.println("Error: " + e.getMessage());
+            printHelp();
+            System.exit(1);
+        }
+
+        String[] cmdArgs = cmd.getArgs();
+
+        if (cmdArgs.length != 0) {
+            printHelp();
+            System.exit(1);
+        }
+
+        String hostname = cmd.getOptionValue("hostname");
+        if (hostname == null) {
+            hostname = InetAddress.getLocalHost().getHostName();
+        }
+
+        String subsystem = cmd.getOptionValue("subsystem");
+
+        InstallToken token = parent.client.getInstallToken(hostname, subsystem);
+
+        MainCLI.printMessage("Install token: \"" + token.getToken() + "\"");
+    }
+}
-- 
1.7.11.4

