AT&T 2.0.19 Code drop, stage 3

Issue-ID: AAF-197
Change-Id: I8b02cb073ccba318ccaf6ea0276446bdce88fb82
Signed-off-by: Instrumental <jcgmisc@stl.gathman.org>
diff --git a/auth/auth-certman/.gitignore b/auth/auth-certman/.gitignore
new file mode 100644
index 0000000..7092237
--- /dev/null
+++ b/auth/auth-certman/.gitignore
@@ -0,0 +1,6 @@
+/target/
+/logs/
+/.settings/
+/.classpath
+/tokens/
+/.project
diff --git a/auth/auth-certman/pom.xml b/auth/auth-certman/pom.xml
new file mode 100644
index 0000000..42be041
--- /dev/null
+++ b/auth/auth-certman/pom.xml
@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2017 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<parent>
+		<groupId>org.onap.aaf.auth</groupId>
+		<artifactId>parent</artifactId>
+		<version>2.1.0-SNAPSHOT</version>
+		<relativePath>../pom.xml</relativePath>
+	</parent>
+
+	<artifactId>aaf-auth-certman</artifactId>
+	<name>AAF Auth Certificate Manager</name>
+	<description>Certificate Manager API</description>
+
+	<properties>
+		<project.swmVersion>21</project.swmVersion>
+	</properties>
+
+	<dependencies>
+		<dependency>
+			<groupId>org.onap.aaf.auth</groupId>
+			<artifactId>aaf-auth-core</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.onap.aaf.auth</groupId>
+			<artifactId>aaf-auth-cass</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>org.onap.aaf.cadi</groupId>
+			<artifactId>aaf-cadi-aaf</artifactId>
+		</dependency>
+
+		<dependency>
+			<groupId>com.google.code.jscep</groupId>
+			<artifactId>jscep</artifactId>
+			<version>2.4.0</version>
+		</dependency>
+
+	</dependencies>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-jar-plugin</artifactId>
+				<configuration>
+					<includes>
+						<include>**/*.class</include>
+					</includes>
+				</configuration>
+				<version>2.3.1</version>
+			</plugin>
+
+			<!--This plugin's configuration is used to store Eclipse m2e settings 
+				only. It has no influence on the Maven build itself. -->
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-deploy-plugin</artifactId>
+				<configuration>
+					<skip>true</skip>
+				</configuration>
+			</plugin>
+			<plugin>
+				<groupId>org.codehaus.mojo</groupId>
+				<artifactId>appassembler-maven-plugin</artifactId>
+				<configuration>
+					<programs>
+						<program>
+							<mainClass>org.onap.aaf.auth.cm.AAF_CM</mainClass>
+							<name>cm</name>
+							<commandLineArguments>
+				                <commandLineArgument>cadi_prop_files=${project.conf_dir}/org.osaaf.cm.props</commandLineArgument>
+				             </commandLineArguments>
+						</program>
+					</programs>
+				</configuration>
+			</plugin>
+			
+		</plugins>
+	</build>
+
+	<distributionManagement>
+		<repository>
+			<id>nexus</id>
+			<name>attarch-releases</name>
+			<url>http://mavencentral.it.att.com:8084/nexus/content/repositories/attarch-releases</url>
+		</repository>
+		<snapshotRepository>
+			<id>nexus</id>
+			<name>attarch-snapshots</name>
+			<url>http://mavencentral.it.att.com:8084/nexus/content/repositories/attarch-snapshots</url>
+		</snapshotRepository>
+	</distributionManagement>
+</project>
diff --git a/auth/auth-certman/src/main/config/.gitignore b/auth/auth-certman/src/main/config/.gitignore
new file mode 100644
index 0000000..e53ef90
--- /dev/null
+++ b/auth/auth-certman/src/main/config/.gitignore
@@ -0,0 +1 @@
+/log4j.properties
diff --git a/auth/auth-certman/src/main/config/certman.props b/auth/auth-certman/src/main/config/certman.props
new file mode 100644
index 0000000..1cd42f4
--- /dev/null
+++ b/auth/auth-certman/src/main/config/certman.props
@@ -0,0 +1,22 @@
+##
+## AUTHZ Certman (authz-certman) Properties
+##
+
+hostname=_HOSTNAME_
+
+## DISCOVERY (DME2) Parameters on the Command Line
+AFT_LATITUDE=_AFT_LATITUDE_
+AFT_LONGITUDE=_AFT_LONGITUDE_
+AFT_ENVIRONMENT=_AFT_ENVIRONMENT_
+DEPLOYED_VERSION=_ARTIFACT_VERSION_
+
+## Pull in common/security properties
+
+cadi_prop_files=_COMMON_DIR_/com.att.aaf.common.props:_COMMON_DIR_/com.att.aaf.props
+
+##DME2 related parameters
+DMEServiceName=service=com.att.authz.certman/version=_MAJOR_VER_._MINOR_VER_._PATCH_VER_/envContext=_ENV_CONTEXT_/routeOffer=_ROUTE_OFFER_
+AFT_DME2_PORT_RANGE=_AUTHZ_CERTMAN_PORT_RANGE_
+
+
+
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/AAF_CM.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/AAF_CM.java
new file mode 100644
index 0000000..c1bc820
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/AAF_CM.java
@@ -0,0 +1,239 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+
+package org.onap.aaf.auth.cm;
+
+import java.lang.reflect.Constructor;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.TreeMap;
+
+import javax.servlet.Filter;
+
+import org.onap.aaf.auth.cache.Cache;
+import org.onap.aaf.auth.cache.Cache.Dated;
+import org.onap.aaf.auth.cm.api.API_Artifact;
+import org.onap.aaf.auth.cm.api.API_Cert;
+import org.onap.aaf.auth.cm.ca.CA;
+import org.onap.aaf.auth.cm.facade.Facade1_0;
+import org.onap.aaf.auth.cm.facade.FacadeFactory;
+import org.onap.aaf.auth.cm.mapper.Mapper.API;
+import org.onap.aaf.auth.cm.service.CMService;
+import org.onap.aaf.auth.cm.service.Code;
+import org.onap.aaf.auth.dao.CassAccess;
+import org.onap.aaf.auth.dao.cass.LocateDAO;
+import org.onap.aaf.auth.direct.DirectLocatorCreator;
+import org.onap.aaf.auth.direct.DirectRegistrar;
+import org.onap.aaf.auth.env.AuthzEnv;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.env.AuthzTransFilter;
+import org.onap.aaf.auth.rserv.HttpMethods;
+import org.onap.aaf.auth.server.AbsService;
+import org.onap.aaf.auth.server.JettyServiceStarter;
+import org.onap.aaf.cadi.Access;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.LocatorException;
+import org.onap.aaf.cadi.PropAccess;
+import org.onap.aaf.cadi.Access.Level;
+import org.onap.aaf.cadi.aaf.v2_0.AAFAuthn;
+import org.onap.aaf.cadi.aaf.v2_0.AAFLurPerm;
+import org.onap.aaf.cadi.aaf.v2_0.AAFTrustChecker;
+import org.onap.aaf.cadi.aaf.v2_0.AbsAAFLocator;
+import org.onap.aaf.cadi.config.Config;
+import org.onap.aaf.cadi.register.Registrant;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Data;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.util.Split;
+
+import com.datastax.driver.core.Cluster;
+
+public class AAF_CM extends AbsService<AuthzEnv, AuthzTrans> {
+
+	private static final String USER_PERMS = "userPerms";
+	private static final Map<String,CA> certAuths = new TreeMap<String,CA>();
+	public Facade1_0 facade1_0; // this is the default Facade
+	public Facade1_0 facade1_0_XML; // this is the XML Facade
+	public Map<String, Dated> cacheUser;
+	public AAFAuthn<?> aafAuthn;
+	public AAFLurPerm aafLurPerm;
+	final public Cluster cluster;
+	public final LocateDAO locateDAO;
+
+
+	/**
+	 * Construct AuthzAPI with all the Context Supporting Routes that Authz needs
+	 * 
+	 * @param env
+	 * @param si 
+	 * @param dm 
+	 * @param decryptor 
+	 * @throws APIException 
+	 */
+	public AAF_CM(AuthzEnv env) throws Exception {
+		super(env.access(),env);
+		aafLurPerm = aafCon().newLur();
+		// Note: If you need both Authn and Authz construct the following:
+		aafAuthn = aafCon().newAuthn(aafLurPerm);
+
+		String aaf_env = env.getProperty(Config.AAF_ENV);
+		if(aaf_env==null) {
+			throw new APIException("aaf_env needs to be set");
+		}
+
+		// Initialize Facade for all uses
+		AuthzTrans trans = env.newTrans();
+
+		cluster = org.onap.aaf.auth.dao.CassAccess.cluster(env,null);
+		locateDAO = new LocateDAO(trans,cluster,CassAccess.KEYSPACE);
+
+		// Have AAFLocator object Create DirectLocators for Location needs
+		AbsAAFLocator.setCreator(new DirectLocatorCreator(env, locateDAO));
+
+		// Load Supported Certificate Authorities by property
+		// Note: Some will be dynamic Properties, so we need to look through all
+		for(Entry<Object, Object> es : env.access().getProperties().entrySet()) {
+			String key = es.getKey().toString();
+			if(key.startsWith(CA.CM_CA_PREFIX)) {
+				int idx = key.indexOf('.');
+				if(idx==key.lastIndexOf('.')) { // else it's a regular property 
+	
+					env.log(Level.INIT, "Loading Certificate Authority Module: " + key.substring(idx+1));
+					String[] segs = Split.split(',', env.getProperty(key));
+					if(segs.length>0) {
+						String[][] multiParams = new String[segs.length-1][];
+						for(int i=0;i<multiParams.length;++i) {
+							multiParams[i]=Split.split(';',segs[1+i]);
+						}
+						@SuppressWarnings("unchecked")
+						Class<CA> cac = (Class<CA>)Class.forName(segs[0]);
+						Constructor<CA> cons = cac.getConstructor(new Class<?>[] {
+							Access.class,String.class,String.class,String[][].class
+						});
+						Object pinst[] = new Object[4];
+						pinst[0]=env;
+						pinst[1]= key.substring(idx+1);
+						pinst[2]= aaf_env;
+						pinst[3] = multiParams; 
+						CA ca = cons.newInstance(pinst);
+						certAuths.put(ca.getName(),ca);
+					}
+				}
+			}
+		}
+		if(certAuths.size()==0) {
+			throw new APIException("No Certificate Authorities have been configured in CertMan");
+		}
+
+		CMService service = new CMService(trans, this);
+		// note: Service knows how to shutdown Cluster on Shutdown, etc.  See Constructor
+		facade1_0 = FacadeFactory.v1_0(this,trans, service,Data.TYPE.JSON);   // Default Facade
+		facade1_0_XML = FacadeFactory.v1_0(this,trans,service,Data.TYPE.XML); 
+
+
+		synchronized(env) {
+			if(cacheUser == null) {
+				cacheUser = Cache.obtain(USER_PERMS);
+				Cache.startCleansing(env, USER_PERMS);
+			}
+		}
+
+		////////////////////////////////////////////////////////////////////////////
+		// APIs
+		////////////////////////////////////////////////////////////////////////
+		API_Cert.init(this);
+		API_Artifact.init(this);
+
+		StringBuilder sb = new StringBuilder();
+		trans.auditTrail(2, sb);
+		trans.init().log(sb);
+	}
+
+	public CA getCA(String key) {
+		return certAuths.get(key);
+	}
+
+	/**
+	 * Setup XML and JSON implementations for each supported Version type
+	 * 
+	 * We do this by taking the Code passed in and creating clones of these with the appropriate Facades and properties
+	 * to do Versions and Content switches
+	 * 
+	 */
+	public void route(HttpMethods meth, String path, API api, Code code) throws Exception {
+		String version = "1.0";
+		// Get Correct API Class from Mapper
+		Class<?> respCls = facade1_0.mapper().getClass(api); 
+		if(respCls==null) throw new Exception("Unknown class associated with " + api.getClass().getName() + ' ' + api.name());
+		// setup Application API HTML ContentTypes for JSON and Route
+		String application = applicationJSON(respCls, version);
+		route(env,meth,path,code,application,"application/json;version="+version,"*/*");
+
+		// setup Application API HTML ContentTypes for XML and Route
+		application = applicationXML(respCls, version);
+		route(env,meth,path,code.clone(facade1_0_XML),application,"application/xml;version="+version);
+
+		// Add other Supported APIs here as created
+	}
+
+	public void routeAll(HttpMethods meth, String path, API api, Code code) throws Exception {
+		route(env,meth,path,code,""); // this will always match
+	}
+
+	@Override
+	public Filter[] filters() throws CadiException, LocatorException {
+		try {
+			return new Filter[] {
+					new AuthzTransFilter(env,aafCon(),
+		        			new AAFTrustChecker((Env)env))
+				};
+		} catch (NumberFormatException e) {
+			throw new CadiException("Invalid Property information", e);
+		}
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public Registrant<AuthzEnv>[] registrants(final int port) throws CadiException, LocatorException {
+		return new Registrant[] {
+			new DirectRegistrar(access,locateDAO,app_name,app_version,port)
+		};
+	}
+
+	public void destroy() {
+		Cache.stopTimer();
+		locateDAO.close(env.newTransNoAvg());
+		cluster.close();
+	}
+
+	public static void main(final String[] args) {
+		PropAccess propAccess = new PropAccess(args);
+		try {
+ 			AAF_CM service = new AAF_CM(new AuthzEnv(propAccess));
+//			env.setLog4JNames("log4j.properties","authz","cm","audit","init","trace");
+			JettyServiceStarter<AuthzEnv,AuthzTrans> jss = new JettyServiceStarter<AuthzEnv,AuthzTrans>(service);
+			jss.start();
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+	}
+}
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/api/API_Artifact.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/api/API_Artifact.java
new file mode 100644
index 0000000..5c067ce
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/api/API_Artifact.java
@@ -0,0 +1,134 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cm.api;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.http.HttpStatus;
+import org.onap.aaf.auth.cm.AAF_CM;
+import org.onap.aaf.auth.cm.mapper.Mapper.API;
+import org.onap.aaf.auth.cm.service.Code;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.layer.Result;
+import org.onap.aaf.auth.rserv.HttpMethods;
+
+/**
+ * API Deployment Artifact Apis.. using Redirect for mechanism
+ * 
+ * @author Jonathan
+ *
+ */
+public class API_Artifact {
+	private static final String GET_ARTIFACTS = "Get Artifacts";
+
+	/**
+	 * Normal Init level APIs
+	 * 
+	 * @param cmAPI
+	 * @param facade
+	 * @throws Exception
+	 */
+	public static void init(final AAF_CM cmAPI) throws Exception {
+		cmAPI.route(HttpMethods.POST, "/cert/artifacts", API.ARTIFACTS, new Code(cmAPI,"Create Artifacts") {
+			@Override
+			public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
+				Result<Void> r = context.createArtifacts(trans, req, resp);
+				if(r.isOK()) {
+					resp.setStatus(HttpStatus.CREATED_201);
+				} else {
+					context.error(trans,resp,r);
+				}
+			}
+		});
+
+		/**
+		 * Use Query Params to get Artifacts by Machine or MechID
+		 */
+		cmAPI.route(HttpMethods.GET, "/cert/artifacts", API.ARTIFACTS, new Code(cmAPI,GET_ARTIFACTS) {
+			@Override
+			public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
+				Result<Void> r = context.readArtifacts(trans, req, resp);
+				if(r.isOK()) {
+					resp.setStatus(HttpStatus.OK_200);
+				} else {
+					context.error(trans,resp,r);
+				}
+			}
+		});
+
+
+		cmAPI.route(HttpMethods.GET, "/cert/artifacts/:mechid/:machine", API.ARTIFACTS, new Code(cmAPI,GET_ARTIFACTS) {
+			@Override
+			public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
+				
+				Result<Void> r = context.readArtifacts(trans, resp, pathParam(req,":mechid"), pathParam(req,":machine"));
+				if(r.isOK()) {
+					resp.setStatus(HttpStatus.OK_200);
+				} else {
+					context.error(trans,resp,r);
+				}
+			}
+		});
+		
+		
+		cmAPI.route(HttpMethods.PUT, "/cert/artifacts", API.ARTIFACTS, new Code(cmAPI,"Update Artifacts") {
+			@Override
+			public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
+				Result<Void> r = context.updateArtifacts(trans, req, resp);
+				if(r.isOK()) {
+					resp.setStatus(HttpStatus.OK_200);
+				} else {
+					context.error(trans,resp,r);
+				}
+			}
+		});
+
+		cmAPI.route(HttpMethods.DELETE, "/cert/artifacts/:mechid/:machine", API.VOID, new Code(cmAPI,"Delete Artifacts") {
+			@Override
+			public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
+				Result<Void> r = context.deleteArtifacts(trans, resp, 
+						pathParam(req, ":mechid"), pathParam(req,":machine"));
+				if(r.isOK()) {
+					resp.setStatus(HttpStatus.OK_200);
+				} else {
+					context.error(trans,resp,r);
+				}
+			}
+		});
+		
+
+		cmAPI.route(HttpMethods.DELETE, "/cert/artifacts", API.VOID, new Code(cmAPI,"Delete Artifacts") {
+			@Override
+			public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
+				Result<Void> r = context.deleteArtifacts(trans, req, resp);
+				if(r.isOK()) {
+					resp.setStatus(HttpStatus.OK_200);
+				} else {
+					context.error(trans,resp,r);
+				}
+			}
+		});
+		
+
+	}
+}
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/api/API_Cert.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/api/API_Cert.java
new file mode 100644
index 0000000..0cea9c7
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/api/API_Cert.java
@@ -0,0 +1,142 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cm.api;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.http.HttpStatus;
+import org.onap.aaf.auth.cm.AAF_CM;
+import org.onap.aaf.auth.cm.ca.CA;
+import org.onap.aaf.auth.cm.mapper.Mapper.API;
+import org.onap.aaf.auth.cm.service.Code;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.layer.Result;
+import org.onap.aaf.auth.rserv.HttpMethods;
+import org.onap.aaf.misc.env.Slot;
+
+/**
+ * API Apis.. using Redirect for mechanism
+ * 
+ * @author Jonathan
+ *
+ */
+public class API_Cert {
+	public static final String CERT_AUTH = "CertAuthority";
+	private static Slot sCertAuth;
+
+	/**
+	 * Normal Init level APIs
+	 * 
+	 * @param aafCM
+	 * @param facade
+	 * @throws Exception
+	 */
+	public static void init(final AAF_CM aafCM) throws Exception {
+		// Check for Created Certificate Authorities in TRANS
+		sCertAuth = aafCM.env.slot(CERT_AUTH);
+		
+		////////
+		// Overall APIs
+		///////
+		aafCM.route(HttpMethods.PUT,"/cert/:ca",API.CERT_REQ,new Code(aafCM,"Request Certificate") {
+			@Override
+			public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
+				String key = pathParam(req, ":ca");
+				CA ca;
+				if((ca = aafCM.getCA(key))==null) {
+					context.error(trans,resp,Result.ERR_BadData,"CA %s is not supported",key);
+				} else {
+					trans.put(sCertAuth, ca);
+					Result<Void> r = context.requestCert(trans, req, resp, ca);
+					if(r.isOK()) {
+						resp.setStatus(HttpStatus.OK_200);
+					} else {
+						context.error(trans,resp,r);
+					}
+				}
+			}
+		});
+		
+		aafCM.route(HttpMethods.GET,"/cert/:ca/personal",API.CERT,new Code(aafCM,"Request Personal Certificate") {
+			@Override
+			public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
+				String key = pathParam(req, ":ca");
+				CA ca;
+				if((ca = aafCM.getCA(key))==null) {
+					context.error(trans,resp,Result.ERR_BadData,"CA %s is not supported",key);
+				} else {
+					trans.put(sCertAuth, ca);
+					Result<Void> r = context.requestPersonalCert(trans, req, resp, ca);
+					if(r.isOK()) {
+						resp.setStatus(HttpStatus.OK_200);
+					} else {
+						context.error(trans,resp,r);
+					}
+				}
+			}
+		});
+
+		
+		/**
+		 * 
+		 */
+		aafCM.route(HttpMethods.GET, "/cert/may/:perm", API.VOID, new Code(aafCM,"Check Permission") {
+			@Override
+			public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
+				Result<Void> r = context.check(trans, resp, pathParam(req,"perm"));
+				if(r.isOK()) {
+					resp.setStatus(HttpStatus.OK_200);
+				} else {
+					trans.checkpoint(r.errorString());
+					context.error(trans,resp,Result.err(Result.ERR_Denied,"%s does not have Permission.",trans.user()));
+				}
+			}
+		});
+
+		/**
+		 * Get Cert by ID and Machine 
+		 */
+
+		
+		/**
+		 * Get Certs by ID
+		 */
+		aafCM.route(HttpMethods.GET, "/cert/id/:id", API.CERT, new Code(aafCM,"GetByID") {
+			@Override
+			public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
+				Result<Void> r = context.readCertsByMechID(trans, resp, pathParam(req,"id"));
+				if(r.isOK()) {
+					resp.setStatus(HttpStatus.OK_200);
+				} else {
+					context.error(trans,resp,r);
+				}
+			}
+		});
+
+		
+		/**
+		 * Get Certs by Machine
+		 */
+		
+	}
+}
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/CA.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/CA.java
new file mode 100644
index 0000000..521c501
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/CA.java
@@ -0,0 +1,209 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+package org.onap.aaf.auth.cm.ca;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.bouncycastle.asn1.x500.style.BCStyle;
+import org.onap.aaf.auth.cm.cert.CSRMeta;
+import org.onap.aaf.auth.cm.cert.RDN;
+import org.onap.aaf.cadi.Access;
+import org.onap.aaf.cadi.Access.Level;
+import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.misc.env.Trans;
+import org.onap.aaf.misc.env.util.Split;
+
+public abstract class CA {
+	private static final String MUST_EXIST_TO_CREATE_CSRS_FOR = " must exist to create CSRs for ";
+	//TODO figuring out what is an Issuing CA is a matter of convention.  Consider SubClassing for Open Source
+	public static final String ISSUING_CA = "Issuing CA";
+	public static final String CM_CA_PREFIX = "cm_ca.";
+	public static final String CM_CA_BASE_SUBJECT = ".baseSubject";
+	protected static final String CM_PUBLIC_DIR = "cm_public_dir";
+	private static final String CM_TRUST_CAS = "cm_trust_cas";
+	protected static final String CM_BACKUP_CAS = "cm_backup_cas";
+
+	public static final Set<String> EMPTY = Collections.unmodifiableSet(new HashSet<String>());
+
+	
+	private final String name,env;
+	private MessageDigest messageDigest;
+	private final String permType;
+	private Set<String> caIssuerDNs;
+	private final ArrayList<String> idDomains;
+	private String[] trustedCAs;
+	private List<RDN> rdns; 
+
+
+	protected CA(Access access, String caName, String env) throws IOException, CertException {
+		trustedCAs = new String[4]; // starting array
+		this.name = caName;
+		this.env = env;
+		permType = access.getProperty(CM_CA_PREFIX + name + ".perm_type",null);
+		if(permType==null) {
+			throw new CertException(CM_CA_PREFIX + name + ".perm_type" + MUST_EXIST_TO_CREATE_CSRS_FOR + caName);
+		}
+		caIssuerDNs = new HashSet<String>();
+		
+		String tag = CA.CM_CA_PREFIX+caName+CA.CM_CA_BASE_SUBJECT;
+		
+		String fields = access.getProperty(tag, null);
+		if(fields==null) {
+			throw new CertException(tag + MUST_EXIST_TO_CREATE_CSRS_FOR + caName);
+		}
+		for(RDN rdn : rdns = RDN.parse('/',fields)) {
+			if(rdn.aoi==BCStyle.EmailAddress) { // Cert Specs say Emails belong in Subject
+				throw new CertException("email address is not allowed in " + CM_CA_BASE_SUBJECT);
+			}
+		}
+		
+		idDomains = new ArrayList<String>();
+		StringBuilder sb = null;
+		for(String s : Split.splitTrim(',', access.getProperty(CA.CM_CA_PREFIX+caName+".idDomains", ""))) {
+			if(s.length()>0) {
+				if(sb==null) {
+					sb = new StringBuilder();
+				} else {
+					sb.append(", ");
+				}
+				idDomains.add(s);
+				sb.append(s);
+			}
+		}
+		if(sb!=null) {
+			access.printf(Level.INIT, "CA '%s' supports Personal Certificates for %s", caName, sb);
+		}
+		
+		String data_dir = access.getProperty(CM_PUBLIC_DIR,null);
+		if(data_dir!=null) {
+			File data = new File(data_dir);
+			byte[] bytes;
+			if(data.exists()) {
+				String trust_cas = access.getProperty(CM_TRUST_CAS,null);
+				if(trust_cas!=null) {
+					for(String fname : Split.splitTrim(',', trust_cas)) {
+						File crt = new File(data,fname);
+						if(crt.exists()) {
+							access.printf(Level.INIT, "Loading CA Cert from %s", crt.getAbsolutePath());
+							bytes = new byte[(int)crt.length()];
+							FileInputStream fis = new FileInputStream(crt);
+							try {
+								fis.read(bytes);
+								addTrustedCA(new String(bytes));
+							} finally {
+								fis.close();
+							}
+						} else {
+							access.printf(Level.INIT, "FAILED to Load CA Cert from %s", crt.getAbsolutePath());
+						}
+					}
+				} else {
+					access.printf(Level.INIT, "Cannot load external TRUST CAs: No property %s",CM_TRUST_CAS);
+				}
+			} else {
+				access.printf(Level.INIT, "Cannot load external TRUST CAs: %s doesn't exist, or is not accessible",data.getAbsolutePath());
+			}
+		}
+	}
+
+	protected void addCaIssuerDN(String issuerDN) {
+		caIssuerDNs.add(issuerDN);
+	}
+	
+	protected synchronized void addTrustedCA(final String crtString) {
+		String crt;
+		if(crtString.endsWith("\n")) {
+			crt = crtString;
+		} else {
+			crt = crtString + '\n';
+		}
+		for(int i=0;i<trustedCAs.length;++i) {
+			if(trustedCAs[i]==null) {
+				trustedCAs[i]=crt;
+				return;
+			}
+		}
+		String[] temp = new String[trustedCAs.length+5];
+		System.arraycopy(trustedCAs,0,temp, 0, trustedCAs.length);
+		temp[trustedCAs.length]=crt;
+		trustedCAs = temp;
+	}
+	
+	public Set<String> getCaIssuerDNs() {
+		return caIssuerDNs;
+	}
+	
+	public String[] getTrustedCAs() {
+		return trustedCAs;
+	}
+	
+	public String getEnv() {
+		return env;
+	}
+
+	protected void setMessageDigest(MessageDigest md) {
+		messageDigest = md;
+	}
+
+	/*
+	 * End Required Constructor calls
+	 */
+
+	public String getName() {
+		return name;
+	}
+	
+	
+	public String getPermType() {
+		return permType;
+	}
+	
+	public abstract X509andChain sign(Trans trans, CSRMeta csrmeta) throws IOException, CertException;
+
+	/* (non-Javadoc)
+	 * @see org.onap.aaf.auth.cm.ca.CA#inPersonalDomains(java.security.Principal)
+	 */
+	public boolean inPersonalDomains(Principal p) {
+		int at = p.getName().indexOf('@');
+		if(at>=0) {
+			return idDomains.contains(p.getName().substring(at+1));
+		} else {
+			return false;
+		}
+	}
+
+	public MessageDigest messageDigest() {
+		return messageDigest;
+	}
+
+	public CSRMeta newCSRMeta() {
+		return new CSRMeta(rdns);
+	}
+}
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/JscepCA.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/JscepCA.java
new file mode 100644
index 0000000..ae4e21a
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/JscepCA.java
@@ -0,0 +1,268 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+package org.onap.aaf.auth.cm.ca;
+
+import java.io.FileReader;
+import java.io.IOException;
+import java.net.Authenticator;
+import java.net.MalformedURLException;
+import java.net.PasswordAuthentication;
+import java.net.URL;
+import java.security.cert.CertStoreException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.pkcs.PKCS10CertificationRequest;
+import org.jscep.client.Client;
+import org.jscep.client.ClientException;
+import org.jscep.client.EnrollmentResponse;
+import org.jscep.client.verification.CertificateVerifier;
+import org.jscep.transaction.TransactionException;
+import org.onap.aaf.auth.cm.cert.BCFactory;
+import org.onap.aaf.auth.cm.cert.CSRMeta;
+import org.onap.aaf.cadi.Access;
+import org.onap.aaf.cadi.LocatorException;
+import org.onap.aaf.cadi.Access.Level;
+import org.onap.aaf.cadi.Locator.Item;
+import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.cadi.locator.HotPeerLocator;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.env.Trans;
+import org.onap.aaf.misc.env.util.Split;
+
+public class JscepCA extends CA {
+	static final String CA_PREFIX = "http://";
+	static final String CA_POSTFIX="/certsrv/mscep_admin/mscep.dll";
+
+	private final static String MS_PROFILE="1";
+	private final static int MAX_RETRY=3;
+	public static final long INVALIDATE_TIME = 1000*60*10; // 10 mins
+
+	// package on purpose
+	private Map<String,X509ChainWithIssuer> mxcwi_s;
+	private Map<Client,X509ChainWithIssuer> mxcwi_c;
+
+
+	private JscepClientLocator clients;
+
+	public JscepCA(final Access access, final String name, final String env, String [][] params) throws IOException, CertException, LocatorException {
+ 		super(access, name, env);
+ 		mxcwi_s = new ConcurrentHashMap<String,X509ChainWithIssuer>();
+ 		mxcwi_c = new ConcurrentHashMap<Client,X509ChainWithIssuer>();
+ 		
+ 		if(params.length<2) {
+ 			throw new CertException("No Trust Chain parameters are included");
+ 		} 
+ 		if(params[0].length<2) {
+ 			throw new CertException("User/Password required for JSCEP");
+ 		}
+ 		final String id = params[0][0];
+ 		final String pw = params[0][1]; 
+		
+		// Set this for NTLM password Microsoft
+		Authenticator.setDefault(new Authenticator() {
+			  public PasswordAuthentication getPasswordAuthentication () {
+		            try {
+						return new PasswordAuthentication (id,access.decrypt(pw,true).toCharArray());
+					} catch (IOException e) {
+						access.log(e);
+					}
+					return null;
+		      }
+		});
+		
+		StringBuilder urlstr = new StringBuilder();
+
+		for(int i=1;i<params.length;++i) { // skip first section, which is user/pass
+			// Work 
+			if(i>1) {
+				urlstr.append(','); // delimiter
+			}
+			urlstr.append(params[i][0]);
+			
+			String dir = access.getProperty(CM_PUBLIC_DIR, "");
+			if(!"".equals(dir) && !dir.endsWith("/")) {
+				dir = dir + '/';
+			}
+			String path;
+			List<FileReader> frs = new ArrayList<FileReader>(params.length-1);
+			try {
+				for(int j=1; j<params[i].length; ++j) { // first 3 taken up, see above
+					path = !params[i][j].contains("/")?dir+params[i][j]:params[i][j];
+					access.printf(Level.INIT, "Loading a TrustChain Member for %s from %s",name, path);
+					frs.add(new FileReader(path));
+				}
+				X509ChainWithIssuer xcwi = new X509ChainWithIssuer(frs);
+				addCaIssuerDN(xcwi.getIssuerDN());
+				mxcwi_s.put(params[i][0],xcwi);
+			} finally {
+				for(FileReader fr : frs) {
+					if(fr!=null) {
+						fr.close();
+					}
+				}
+			}
+		}		
+		clients = new JscepClientLocator(access,urlstr.toString());
+	}
+
+	// package on purpose
+	
+	@Override
+	public X509ChainWithIssuer sign(Trans trans, CSRMeta csrmeta) throws IOException, CertException {
+		TimeTaken tt = trans.start("Generating CSR and Keys for New Certificate", Env.SUB);
+		PKCS10CertificationRequest csr;
+		try {
+			csr = csrmeta.generateCSR(trans);
+			if(trans.info().isLoggable()) {
+				trans.info().log(BCFactory.toString(csr));
+			} 
+			if(trans.info().isLoggable()) {
+				trans.info().log(csr);
+			}
+		} finally {
+			tt.done();
+		}
+		
+		tt = trans.start("Enroll CSR", Env.SUB);
+		Client client = null;
+		Item item = null;
+		for(int i=0; i<MAX_RETRY;++i) {
+			try {
+				item = clients.best();
+				client = clients.get(item);
+				
+				EnrollmentResponse er = client.enrol(
+						csrmeta.initialConversationCert(trans),
+						csrmeta.keypair(trans).getPrivate(),
+						csr,
+						MS_PROFILE /* profile... MS can't deal with blanks*/);
+				
+				while(true) {
+					if(er.isSuccess()) {
+						trans.checkpoint("Cert from " + clients.info(item));
+						X509Certificate x509 = null;
+						for( Certificate cert : er.getCertStore().getCertificates(null)) {
+							if(x509==null) {
+								x509 = (X509Certificate)cert;
+								break;
+							}
+						}
+						X509ChainWithIssuer mxcwi = mxcwi_c.get(client);
+						return new X509ChainWithIssuer(mxcwi,x509);
+//						break;
+					} else if (er.isPending()) {
+						trans.checkpoint("Polling, waiting on CA to complete");
+						Thread.sleep(3000);
+					} else if (er.isFailure()) {
+//						switch(er.getFailInfo()) {
+//							case badMessageCheck:
+//								throw new ClientException("Received BadMessageCheck from Jscep");
+//							case badAlg:
+//							case badCertId:
+//							case badRequest:
+//							case badTime:
+//							default:
+//						}
+						throw new CertException(clients.info(item)+':'+er.getFailInfo().toString());
+					}
+				}
+				//i=MAX_RETRY;
+			} catch(LocatorException e) {
+				trans.error().log(e);
+				i=MAX_RETRY;
+			} catch (ClientException e) {
+				trans.error().log(e,"SCEP Client Error, Temporarily Invalidating Client: " + clients.info(item));
+				try  { 
+					clients.invalidate(client);
+					if(!clients.hasItems()) {
+						clients.refresh();
+					}
+				} catch (LocatorException e1) {
+					trans.error().log(e,clients.info(item));
+					i=MAX_RETRY;  // can't go any further
+				}
+			} catch (InterruptedException|TransactionException|CertificateException|OperatorCreationException | CertStoreException e) {
+				trans.error().log(e);
+				i=MAX_RETRY;
+			} finally {
+				tt.done();
+			}
+		}
+		
+		return null;
+	}
+	
+	/**
+	 * Locator specifically for Jscep Clients.
+	 * 
+	 * Class based client for access to common Map
+	 */
+	private class JscepClientLocator extends HotPeerLocator<Client> {
+
+		protected JscepClientLocator(Access access, String urlstr)throws LocatorException {
+			super(access, urlstr, JscepCA.INVALIDATE_TIME,
+			 	access.getProperty("cadi_latitude","39.833333"), //Note: Defaulting to GEO center of US
+			 	access.getProperty("cadi_longitude","-98.583333")
+			 	);
+		}
+
+		@Override
+		protected Client _newClient(String urlinfo) throws LocatorException {
+			try {
+				String[] info = Split.split('/', urlinfo);
+				Client c = new Client(new URL(JscepCA.CA_PREFIX + info[0] + JscepCA.CA_POSTFIX), 
+						new CertificateVerifier() {
+						@Override
+						public boolean verify(X509Certificate cert) {
+							//TODO checkIssuer
+							return true;
+						}
+					}
+				);
+				// Map URL to Client, because Client doesn't expose Connection
+				mxcwi_c.put(c,mxcwi_s.get(urlinfo));
+				return c;
+			} catch (MalformedURLException e) {
+				throw new LocatorException(e);
+			}
+		}
+
+		@Override
+		protected Client _invalidate(Client client) {
+			return null;
+		}
+
+		@Override
+		protected void _destroy(Client client) {
+			mxcwi_c.remove(client);
+		}
+		
+		
+	}
+}
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/LocalCA.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/LocalCA.java
new file mode 100644
index 0000000..b6a2a0a
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/LocalCA.java
@@ -0,0 +1,182 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+package org.onap.aaf.auth.cm.ca;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x500.X500NameBuilder;
+import org.bouncycastle.asn1.x509.BasicConstraints;
+import org.bouncycastle.asn1.x509.ExtendedKeyUsage;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.GeneralName;
+import org.bouncycastle.asn1.x509.GeneralNames;
+import org.bouncycastle.asn1.x509.KeyPurposeId;
+import org.bouncycastle.asn1.x509.KeyUsage;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
+import org.bouncycastle.crypto.params.RSAKeyParameters;
+import org.bouncycastle.crypto.util.SubjectPublicKeyInfoFactory;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.onap.aaf.auth.cm.cert.BCFactory;
+import org.onap.aaf.auth.cm.cert.CSRMeta;
+import org.onap.aaf.auth.cm.cert.RDN;
+import org.onap.aaf.auth.env.NullTrans;
+import org.onap.aaf.cadi.Access;
+import org.onap.aaf.cadi.Access.Level;
+import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.cadi.cm.Factory;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.env.Trans;
+
+public class LocalCA extends CA {
+
+	// Extensions
+	private static final KeyPurposeId[] ASN_WebUsage = new KeyPurposeId[] {
+				KeyPurposeId.id_kp_serverAuth, // WebServer
+				KeyPurposeId.id_kp_clientAuth};// WebClient
+				
+	private final RSAPrivateKey caKey;
+	private final X500Name issuer;
+	private final SecureRandom random = new SecureRandom();
+	private byte[] serialish;
+	private final X509ChainWithIssuer x509cwi; // "Cert" is CACert
+
+	public LocalCA(Access access, final String name, final String env, final String[][] params) throws IOException, CertException {
+		super(access, name, env);
+		serialish = new byte[24];
+		if(params.length<1 || params[0].length<2) {
+			throw new IOException("LocalCA expects cm_ca.<ca name>=org.onap.aaf.auth.cm.ca.LocalCA,<full path to key file>[;<Full Path to Trust Chain, ending with actual CA>]+");
+		}
+		
+		// Read in the Private Key
+		File f = new File(params[0][0]); // key
+		if(f.exists()) {
+			caKey = (RSAPrivateKey)Factory.toPrivateKey(NullTrans.singleton(),f);
+		} else {
+			throw new CertException("Private Key, " + f.getPath() + ", does not exist");
+		}
+
+		String dir = access.getProperty(CM_PUBLIC_DIR, "");
+		if(!"".equals(dir) && !dir.endsWith("/")) {
+			dir = dir + '/';
+		}
+		List<FileReader> frs = new ArrayList<FileReader>(params.length-1);
+		try {
+			String path;
+			for(int i=1; i<params[0].length; ++i) { // first param is Private Key, remainder are TrustChain
+				path = !params[0][i].contains("/")?dir+params[0][i]:params[0][i];
+				access.printf(Level.INIT, "Loading a TrustChain Member for %s from %s\n",name, path);
+				frs.add(new FileReader(path));
+			}
+			x509cwi = new X509ChainWithIssuer(frs);
+			X500NameBuilder xnb = new X500NameBuilder();
+			for(RDN rnd : RDN.parse(',', x509cwi.getIssuerDN())) {
+				xnb.addRDN(rnd.aoi,rnd.value);
+			}
+			issuer = xnb.build();
+		} finally {
+			for(FileReader fr : frs) {
+				if(fr!=null) {
+					fr.close();
+				}
+			}
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.onap.aaf.auth.cm.service.CA#sign(org.bouncycastle.pkcs.PKCS10CertificationRequest)
+	 */
+	@Override
+	public X509andChain sign(Trans trans, CSRMeta csrmeta) throws IOException, CertException {
+		GregorianCalendar gc = new GregorianCalendar();
+		Date start = gc.getTime();
+		gc.add(GregorianCalendar.MONTH, 2);
+		Date end = gc.getTime();
+		X509Certificate x509;
+		TimeTaken tt = trans.start("Create/Sign Cert",Env.SUB);
+		try {
+			BigInteger bi;
+			synchronized(serialish) {
+				random.nextBytes(serialish);
+				bi = new BigInteger(serialish);
+			}
+				
+			RSAPublicKey rpk = (RSAPublicKey)csrmeta.keypair(trans).getPublic();
+			X509v3CertificateBuilder xcb = new X509v3CertificateBuilder(
+					issuer,
+					bi, // replace with Serialnumber scheme
+					start,
+					end,
+					csrmeta.x500Name(),
+					SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(new RSAKeyParameters(false,rpk.getModulus(),rpk.getPublicExponent()))
+//					new SubjectPublicKeyInfo(ASN1Sequence.getInstance(caCert.getPublicKey().getEncoded()))
+					);
+			List<GeneralName> lsan = new ArrayList<GeneralName>();
+			for(String s : csrmeta.sans()) {
+				lsan.add(new GeneralName(GeneralName.dNSName,s));
+			}
+			GeneralName[] sans = new GeneralName[lsan.size()];
+			lsan.toArray(sans);
+
+		    JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils();
+		    	xcb.addExtension(Extension.basicConstraints,
+                    	false, new BasicConstraints(false))
+		            .addExtension(Extension.keyUsage,
+		                true, new KeyUsage(KeyUsage.digitalSignature
+		                                 | KeyUsage.keyEncipherment))
+		            .addExtension(Extension.extendedKeyUsage,
+		                          true, new ExtendedKeyUsage(ASN_WebUsage))
+
+                    .addExtension(Extension.authorityKeyIdentifier,
+		                          false, extUtils.createAuthorityKeyIdentifier(x509cwi.cert))
+		            .addExtension(Extension.subjectKeyIdentifier,
+		                          false, extUtils.createSubjectKeyIdentifier(x509cwi.cert.getPublicKey()))
+		            .addExtension(Extension.subjectAlternativeName,
+		            		false, new GeneralNames(sans))
+		                                           ;
+	
+			x509 = new JcaX509CertificateConverter().getCertificate(
+					xcb.build(BCFactory.contentSigner(caKey)));
+		} catch (GeneralSecurityException|OperatorCreationException e) {
+			throw new CertException(e);
+		} finally {
+			tt.done();
+		}
+		
+		return new X509ChainWithIssuer(x509cwi,x509);
+	}
+
+}
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/X509ChainWithIssuer.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/X509ChainWithIssuer.java
new file mode 100644
index 0000000..e0a8567
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/X509ChainWithIssuer.java
@@ -0,0 +1,74 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+package org.onap.aaf.auth.cm.ca;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.security.Principal;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.List;
+
+import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.cadi.cm.Factory;
+
+public class X509ChainWithIssuer extends X509andChain {
+	private String issuerDN;
+
+	public X509ChainWithIssuer(X509ChainWithIssuer orig, X509Certificate x509) {
+		super(x509,orig.trustChain);
+		issuerDN=orig.issuerDN;		
+	}
+	
+	public X509ChainWithIssuer(final List<? extends Reader> rdrs) throws IOException, CertException {
+		// Trust Chain.  Last one should be the CA
+		Collection<? extends Certificate> certs;
+		X509Certificate x509;
+		for(Reader rdr : rdrs) {
+			if(rdr!=null) { // cover for badly formed array
+				byte[] bytes = Factory.decode(rdr);
+				try {
+					certs = Factory.toX509Certificate(bytes);
+				} catch (CertificateException e) {
+					throw new CertException(e);
+				}
+				for(Certificate c : certs) {
+					x509=(X509Certificate)c;
+					Principal subject = x509.getSubjectDN();
+					if(subject!=null) {
+						if(cert==null) { // first in Trust Chain
+							issuerDN= subject.toString();
+						}
+						addTrustChainEntry(x509);
+						cert=x509; // adding each time makes sure last one is signer.
+					}
+				}
+			}
+		}
+	}
+	
+	public String getIssuerDN() {
+		return issuerDN;
+	}
+
+}
\ No newline at end of file
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/X509andChain.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/X509andChain.java
new file mode 100644
index 0000000..24416c9
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/X509andChain.java
@@ -0,0 +1,79 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+package org.onap.aaf.auth.cm.ca;
+
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+import java.util.List;
+
+import org.onap.aaf.auth.env.NullTrans;
+import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.cadi.cm.Factory;
+
+
+/**
+ * Have to put the Cert and resulting Trust Chain together. 
+ * Treating them separately has caused issues
+ * 
+ * @author jg1555
+ *
+ */
+public class X509andChain {
+	protected X509Certificate cert;
+	protected String[] trustChain;
+	
+	public X509andChain() {
+		cert = null;
+		trustChain = null;
+	}
+	
+	public X509andChain(X509Certificate cert, String[] trustChain) {
+		this.cert = cert;
+		this.trustChain = trustChain;
+	}
+
+	public X509andChain(X509Certificate cert, List<String> chain) {
+		this.cert = cert;
+		trustChain = new String[chain.size()];
+		chain.toArray(trustChain);
+	}
+	
+	
+	public void addTrustChainEntry(X509Certificate x509) throws IOException, CertException {
+		if(trustChain==null) {
+			trustChain = new String[] {Factory.toString(NullTrans.singleton(),x509)};
+		} else {
+			String[] temp = new String[trustChain.length+1];
+			System.arraycopy(trustChain, 0, temp, 0, trustChain.length);
+			temp[trustChain.length]=Factory.toString(NullTrans.singleton(),x509);
+			trustChain=temp;
+		}
+	}
+
+	public X509Certificate getX509() {
+		return cert;
+	}
+	
+	public String[] getTrustChain() {
+		return trustChain;
+	}
+	
+}
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/BCFactory.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/BCFactory.java
new file mode 100644
index 0000000..4fdac6a
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/BCFactory.java
@@ -0,0 +1,151 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+package org.onap.aaf.auth.cm.cert;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.SignatureException;
+import java.util.List;
+
+import org.bouncycastle.asn1.ASN1Object;
+import org.bouncycastle.operator.ContentSigner;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+import org.bouncycastle.pkcs.PKCS10CertificationRequest;
+import org.onap.aaf.auth.cm.ca.CA;
+import org.onap.aaf.auth.cm.validation.CertmanValidator;
+import org.onap.aaf.cadi.Symm;
+import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.cadi.cm.Factory;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.env.Trans;
+
+
+/**
+ * Additional Factory mechanisms for CSRs, and BouncyCastle.  The main Factory
+ * utilizes only Java abstractions, and is useful in Client code.
+ * 
+ * @author jg1555
+ *
+ */
+public class BCFactory extends Factory {
+	private static final JcaContentSignerBuilder jcsb;
+
+
+	static {
+		// Bouncy
+		jcsb = new JcaContentSignerBuilder(Factory.SIG_ALGO);
+	}
+	
+	public static ContentSigner contentSigner(PrivateKey pk) throws OperatorCreationException {
+		return jcsb.build(pk);
+	}
+	
+	public static String toString(PKCS10CertificationRequest csr) throws IOException, CertException {
+		if(csr==null) {
+			throw new CertException("x509 Certificate Request not built");
+		}
+		return textBuilder("CERTIFICATE REQUEST",csr.getEncoded());
+	}
+
+	public static PKCS10CertificationRequest toCSR(Trans trans, File file) throws IOException {
+		TimeTaken tt = trans.start("Reconstitute CSR", Env.SUB);
+		try {
+			FileReader fr = new FileReader(file);
+			return new PKCS10CertificationRequest(decode(strip(fr)));
+		} finally {
+			tt.done();
+		}
+	}
+
+	public static byte[] sign(Trans trans, ASN1Object toSign, PrivateKey pk) throws IOException, InvalidKeyException, SignatureException, NoSuchAlgorithmException {
+		TimeTaken tt = trans.start("Encode Security Object", Env.SUB);
+		try {
+			return sign(trans,toSign.getEncoded(),pk);
+		} finally {
+			tt.done();
+		}
+	}
+	
+	public static CSRMeta createCSRMeta(CA ca, String mechid, String sponsorEmail, List<String> fqdns) throws CertException {
+		CSRMeta csr = ca.newCSRMeta();
+		boolean first = true;
+		// Set CN (and SAN)
+		for(String fqdn : fqdns) {
+			if(first) {
+				first = false;
+				csr.cn(fqdn);
+			}
+			csr.san(fqdn); // duplicate CN in SAN, per RFC 5280 section 4.2.1.6 
+		}
+		
+		csr.challenge(new String(Symm.randomGen(24)));
+		csr.mechID(mechid);
+		csr.email(sponsorEmail);
+		String errs;
+		if((errs=validateApp(csr))!=null) {
+			throw new CertException(errs);
+		}
+		return csr;
+	}
+	
+	private static String validateApp(CSRMeta csr) {
+		CertmanValidator v = new CertmanValidator();
+		if(v.nullOrBlank("cn", csr.cn())
+			.nullOrBlank("mechID", csr.mechID())
+			.nullOrBlank("email", csr.email())
+			.err()) {
+			return v.errs();
+		} else {
+			return null;
+		}
+	}
+
+	public static CSRMeta createPersonalCSRMeta(CA ca, String personal, String email) throws CertException {
+		CSRMeta csr = ca.newCSRMeta();
+		csr.cn(personal);
+		csr.challenge(new String(Symm.randomGen(24)));
+		csr.email(email);
+		String errs;
+		if((errs=validatePersonal(csr))!=null) {
+			throw new CertException(errs);
+		}
+		return csr;
+	}
+
+	private static String validatePersonal(CSRMeta csr) {
+		CertmanValidator v = new CertmanValidator();
+		if(v.nullOrBlank("cn", csr.cn())
+			.nullOrBlank("email", csr.email())
+			.err()) {
+			return v.errs();
+		} else {
+			return null;
+		}
+	}
+	
+
+}
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/CSRMeta.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/CSRMeta.java
new file mode 100644
index 0000000..2541bea
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/CSRMeta.java
@@ -0,0 +1,266 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+package org.onap.aaf.auth.cm.cert;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.SecureRandom;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.DERPrintableString;
+import org.bouncycastle.asn1.pkcs.Attribute;
+import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x500.X500NameBuilder;
+import org.bouncycastle.asn1.x500.style.BCStyle;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.Extensions;
+import org.bouncycastle.asn1.x509.GeneralName;
+import org.bouncycastle.asn1.x509.GeneralNames;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.pkcs.PKCS10CertificationRequest;
+import org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder;
+import org.bouncycastle.pkcs.jcajce.JcaPKCS10CertificationRequestBuilder;
+import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.cadi.cm.Factory;
+import org.onap.aaf.misc.env.Trans;
+
+public class CSRMeta {
+	private String cn;
+	private String mechID;
+	private String environment;
+	private String email;
+	private String challenge;
+	private List<RDN> rdns;
+	
+	public CSRMeta(List<RDN> rdns) {
+		this.rdns = rdns;
+	}
+	
+	private ArrayList<String> sanList = new ArrayList<String>();
+	private KeyPair keyPair;
+	private X500Name name = null;
+	private SecureRandom random = new SecureRandom();
+
+	public X500Name x500Name() throws IOException {
+		if(name==null) {
+			X500NameBuilder xnb = new X500NameBuilder();
+			xnb.addRDN(BCStyle.CN,cn);
+			xnb.addRDN(BCStyle.E,email);
+			if(mechID!=null) {
+				if(environment==null) {
+					xnb.addRDN(BCStyle.OU,mechID);
+				} else {
+					xnb.addRDN(BCStyle.OU,mechID+':'+environment);
+				}
+			}
+			for(RDN rdn : rdns) {
+				xnb.addRDN(rdn.aoi,rdn.value);
+			}
+			name = xnb.build();
+		}
+		return name;
+	}
+	
+	
+	public PKCS10CertificationRequest  generateCSR(Trans trans) throws IOException, CertException {
+		PKCS10CertificationRequestBuilder builder = new JcaPKCS10CertificationRequestBuilder(x500Name(),keypair(trans).getPublic());
+		if(challenge!=null) {
+			DERPrintableString password = new DERPrintableString(challenge);
+			builder.addAttribute(PKCSObjectIdentifiers.pkcs_9_at_challengePassword, password);
+		}
+		
+		int plus = email==null?0:1;
+		if(sanList.size()>0) {
+			GeneralName[] gna = new GeneralName[sanList.size()+plus];
+			int i=-1;
+			for(String s : sanList) {
+				gna[++i]=new GeneralName(GeneralName.dNSName,s);
+			}
+			gna[++i]=new GeneralName(GeneralName.rfc822Name,email);
+			
+			builder.addAttribute(
+					PKCSObjectIdentifiers.pkcs_9_at_extensionRequest,
+					new Extensions(new Extension[] {
+							new Extension(Extension.subjectAlternativeName,false,new GeneralNames(gna).getEncoded())
+					})
+			);
+		}
+		
+		if(email!=null) {
+			
+		}
+		try {
+			return builder.build(BCFactory.contentSigner(keypair(trans).getPrivate()));
+		} catch (OperatorCreationException e) {
+			throw new CertException(e);
+		}
+	}
+	
+	@SuppressWarnings("deprecation")
+	public static void dump(PKCS10CertificationRequest csr) {
+		 Attribute[] certAttributes = csr.getAttributes();
+		 for (Attribute attribute : certAttributes) {
+		     if (attribute.getAttrType().equals(PKCSObjectIdentifiers.pkcs_9_at_extensionRequest)) {
+		         Extensions extensions = Extensions.getInstance(attribute.getAttrValues().getObjectAt(0));
+		         GeneralNames gns = GeneralNames.fromExtensions(extensions,Extension.subjectAlternativeName);
+		         GeneralName[] names = gns.getNames();
+		         for(int k=0; k < names.length; k++) {
+		             String title = "";
+		             if(names[k].getTagNo() == GeneralName.dNSName) {
+		                 title = "dNSName";
+		             } else if(names[k].getTagNo() == GeneralName.iPAddress) {
+		                 title = "iPAddress";
+		                 // Deprecated, but I don't see anything better to use.
+		                 names[k].toASN1Object();
+		             } else if(names[k].getTagNo() == GeneralName.otherName) {
+		                 title = "otherName";
+		             } else if(names[k].getTagNo() == GeneralName.rfc822Name) {
+		                 title = "email";
+		             }
+
+		             System.out.println(title + ": "+ names[k].getName());
+		         } 
+		     }
+		 }
+	}
+	
+	public X509Certificate initialConversationCert(Trans trans) throws IOException, CertificateException, OperatorCreationException {
+		GregorianCalendar gc = new GregorianCalendar();
+		Date start = gc.getTime();
+		gc.add(GregorianCalendar.DAY_OF_MONTH,2);
+		Date end = gc.getTime();
+		X509v3CertificateBuilder xcb = new X509v3CertificateBuilder(
+				x500Name(),
+				new BigInteger(12,random), // replace with Serialnumber scheme
+				start,
+				end,
+				x500Name(),
+				new SubjectPublicKeyInfo(ASN1Sequence.getInstance(keypair(trans).getPublic().getEncoded()))
+				);
+		return new JcaX509CertificateConverter().getCertificate(
+				xcb.build(BCFactory.contentSigner(keypair(trans).getPrivate())));
+	}
+
+	public CSRMeta san(String v) {
+		sanList.add(v);
+		return this;
+	}
+
+	public List<String> sans() {
+		return sanList;
+	}
+
+
+	public KeyPair keypair(Trans trans) {
+		if(keyPair == null) {
+			keyPair = Factory.generateKeyPair(trans);
+		}
+		return keyPair;
+	}
+
+	/**
+	 * @return the cn
+	 */
+	public String cn() {
+		return cn;
+	}
+
+
+	/**
+	 * @param cn the cn to set
+	 */
+	public void cn(String cn) {
+		this.cn = cn;
+	}
+
+	/**
+	 * Environment of Service MechID is good for
+	 */
+	public void environment(String env) {
+		environment = env;
+	}
+	
+	/**
+	 * 
+	 * @return
+	 */
+	public String environment() {
+		return environment;
+	}
+	
+	/**
+	 * @return the mechID
+	 */
+	public String mechID() {
+		return mechID;
+	}
+
+
+	/**
+	 * @param mechID the mechID to set
+	 */
+	public void mechID(String mechID) {
+		this.mechID = mechID;
+	}
+
+
+	/**
+	 * @return the email
+	 */
+	public String email() {
+		return email;
+	}
+
+
+	/**
+	 * @param email the email to set
+	 */
+	public void email(String email) {
+		this.email = email;
+	}
+
+	/**
+	 * @return the challenge
+	 */
+	public String challenge() {
+		return challenge;
+	}
+
+
+	/**
+	 * @param challenge the challenge to set
+	 */
+	public void challenge(String challenge) {
+		this.challenge = challenge;
+	}
+	
+}
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/RDN.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/RDN.java
new file mode 100644
index 0000000..7d4161f
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/RDN.java
@@ -0,0 +1,101 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+package org.onap.aaf.auth.cm.cert;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.bouncycastle.asn1.ASN1ObjectIdentifier;
+import org.bouncycastle.asn1.x500.style.BCStyle;
+import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.cadi.util.Split;
+
+public class RDN {
+	public String tag;
+	public String value;
+	public ASN1ObjectIdentifier aoi;
+	public RDN(final String tagValue) throws CertException {
+		String[] tv = Split.splitTrim('=',tagValue);
+		switch(tv[0]) {
+			case "cn":case "CN":			aoi = BCStyle.CN; break;
+			case "c":case "C":			aoi = BCStyle.C;break;
+			case "st":case "ST":			aoi = BCStyle.ST;break;
+			case "l":case "L":  			aoi = BCStyle.L;break;
+			case "o":case "O":			aoi = BCStyle.O;break;
+			case "ou":case "OU":			aoi = BCStyle.OU;break;
+			case "dc":case "DC":			aoi = BCStyle.DC;break;
+			case "gn":case "GN":			aoi = BCStyle.GIVENNAME; break;
+			case "sn":case "SN":			aoi = BCStyle.SN; break;  // surname
+			case "email":case "EMAIL":
+			case "emailaddress":
+			case "EMAILADDRESS":			aoi = BCStyle.EmailAddress;break; // should be SAN extension
+			case "initials":				aoi = BCStyle.INITIALS; break; 
+			case "pseudonym":			aoi = BCStyle.PSEUDONYM; break;
+			case "generationQualifier":	aoi = BCStyle.GENERATION; break;
+			case "serialNumber":			aoi = BCStyle.SERIALNUMBER; break;
+			default:
+				throw new CertException("Unknown ASN1ObjectIdentifier for " + tv[0]);
+		}
+		tag = tv[0];
+		value = tv[1];
+	}
+	
+	/**
+	 * Parse various forms of DNs into appropriate RDNs, which have the ASN1ObjectIdentifier
+	 * @param delim
+	 * @param dnString
+	 * @return
+	 * @throws CertException
+	 */
+	public static List<RDN> parse(final char delim, final String dnString ) throws CertException {
+		List<RDN> lrnd = new ArrayList<RDN>();
+		StringBuilder sb = new StringBuilder();
+		boolean inQuotes = false;
+		for(int i=0;i<dnString.length();++i) {
+			char c = dnString.charAt(i);
+			if(inQuotes) {
+				if('"' == c) {
+					inQuotes=false;
+				} else {
+					sb.append(dnString.charAt(i));
+				}
+			} else {
+				if('"' == c) {
+					inQuotes=true;
+				} else if(delim==c) {
+					lrnd.add(new RDN(sb.toString()));
+					sb.setLength(0);
+				} else {
+					sb.append(dnString.charAt(i));
+				}
+			}
+		}
+		if(sb.indexOf("=")>0) {
+			lrnd.add(new RDN(sb.toString()));
+		}
+		return lrnd;
+	}
+	
+	@Override
+	public String toString() {
+		return tag + '=' + value;
+	}
+}
\ No newline at end of file
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertDrop.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertDrop.java
new file mode 100644
index 0000000..0a9d766
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertDrop.java
@@ -0,0 +1,26 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cm.data;
+
+public class CertDrop {
+
+}
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertRenew.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertRenew.java
new file mode 100644
index 0000000..242a18a
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertRenew.java
@@ -0,0 +1,26 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cm.data;
+
+public class CertRenew {
+
+}
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertReq.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertReq.java
new file mode 100644
index 0000000..aa0b9c2
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertReq.java
@@ -0,0 +1,49 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cm.data;
+
+import java.util.List;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import org.onap.aaf.auth.cm.ca.CA;
+import org.onap.aaf.auth.cm.cert.BCFactory;
+import org.onap.aaf.auth.cm.cert.CSRMeta;
+import org.onap.aaf.cadi.cm.CertException;
+
+public class CertReq {
+	// These cannot be null
+	public CA certAuthority;
+	public String mechid;
+	public List<String> fqdns;
+	// Notify
+	public List<String> emails;
+	
+	
+	// These may be null
+	public String sponsor;
+	public XMLGregorianCalendar start, end;
+	
+	public CSRMeta getCSRMeta() throws CertException {
+		return BCFactory.createCSRMeta(certAuthority, mechid, sponsor,fqdns);
+	}
+}
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertResp.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertResp.java
new file mode 100644
index 0000000..595025e
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertResp.java
@@ -0,0 +1,94 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cm.data;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.cert.X509Certificate;
+import java.util.Set;
+
+import org.onap.aaf.auth.cm.ca.CA;
+import org.onap.aaf.auth.cm.cert.CSRMeta;
+import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.cadi.cm.Factory;
+import org.onap.aaf.misc.env.Trans;
+
+public class CertResp {
+	private CA ca;
+	private KeyPair keyPair;
+	private String challenge;
+	
+	private String privateKey, certString;
+	private String[] trustChain;
+	private String[] trustCAs;
+	private String[] notes;
+	
+	public CertResp(Trans trans, CA ca, X509Certificate x509, CSRMeta csrMeta, String[] trustChain, String[] trustCAs, String[] notes) throws IOException, GeneralSecurityException, CertException {
+		keyPair = csrMeta.keypair(trans);
+		privateKey = Factory.toString(trans, keyPair.getPrivate());
+		certString = Factory.toString(trans,x509);
+		challenge=csrMeta.challenge();
+		this.ca = ca;
+		this.trustChain = trustChain;
+		this.trustCAs = trustCAs;
+		this.notes = notes;
+	}
+
+	// Use for Read Responses, etc
+	public CertResp(String cert) {
+		certString = cert;
+	}
+
+	
+	public String asCertString() {
+		return certString;
+	}
+	
+	public String privateString() throws IOException {
+		return privateKey;
+	}
+	
+	public String challenge() {
+		return challenge==null?"":challenge;
+	}
+	
+	public String[] notes() {
+		return notes;
+	}
+	
+	public Set<String> caIssuerDNs() {
+		return ca.getCaIssuerDNs();
+	}
+	
+	public String env() {
+		return ca.getEnv();
+	}
+	
+	public String[] trustChain() {
+		return trustChain;
+	}
+	
+	public String[] trustCAs() {
+		return trustCAs;
+	}
+}
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/facade/Facade.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/facade/Facade.java
new file mode 100644
index 0000000..9eb9c2f
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/facade/Facade.java
@@ -0,0 +1,182 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cm.facade;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.onap.aaf.auth.cm.ca.CA;
+import org.onap.aaf.auth.cm.mapper.Mapper;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.layer.Result;
+
+
+/**
+ *   
+ * @author Jonathan
+ *
+ */
+public interface Facade<REQ,CERT,ARTIFACTS,ERROR> {
+
+/////////////////////  STANDARD ELEMENTS //////////////////
+	/** 
+	 * @param trans
+	 * @param response
+	 * @param result
+	 */
+	void error(AuthzTrans trans, HttpServletResponse response, Result<?> result);
+
+	/**
+	 * 
+	 * @param trans
+	 * @param response
+	 * @param status
+	 */
+	void error(AuthzTrans trans, HttpServletResponse response, int status,	String msg, String ... detail);
+
+	/**
+	 * Permission checker
+	 *
+	 * @param trans
+	 * @param resp
+	 * @param perm
+	 * @return
+	 * @throws IOException 
+	 */
+	Result<Void> check(AuthzTrans trans, HttpServletResponse resp, String perm) throws IOException;
+
+	/**
+	 * 
+	 * @return
+	 */
+	public Mapper<REQ,CERT,ARTIFACTS,ERROR> mapper();
+
+/////////////////////  STANDARD ELEMENTS //////////////////
+	
+	/**
+	 * 
+	 * @param trans
+	 * @param resp
+	 * @param rservlet
+	 * @return
+	 */
+	public abstract Result<Void> requestCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, CA ca);
+
+	/**
+	 * 
+	 * @param trans
+	 * @param resp
+	 * @param rservlet
+	 * @return
+	 */
+	public abstract Result<Void> requestPersonalCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, CA ca);
+
+
+	/**
+	 * 
+	 * @param trans
+	 * @param req
+	 * @param resp
+	 * @return
+	 */
+	public abstract Result<Void> renewCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, boolean withTrust);
+
+	/**
+	 * 
+	 * @param trans
+	 * @param req
+	 * @param resp
+	 * @return
+	 */
+	public abstract Result<Void> dropCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp);
+	
+
+	/**
+	 * 
+	 * @param trans
+	 * @param resp
+	 * @param pathParam
+	 * @return
+	 */
+	public Result<Void> readCertsByMechID(AuthzTrans trans, HttpServletResponse resp, String mechID);
+	
+
+	/**
+	 * 
+	 * @param trans
+	 * @param req
+	 * @param resp
+	 * @return
+	 */
+	Result<Void> createArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp);
+	
+	/**
+	 * 
+	 * @param trans
+	 * @param req
+	 * @param resp
+	 * @return
+	 */
+	Result<Void> readArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp);
+
+	/**
+	 * 
+	 * @param trans
+	 * @param resp
+	 * @param mechid
+	 * @param machine
+	 * @return
+	 */
+	Result<Void> readArtifacts(AuthzTrans trans, HttpServletResponse resp, String mechid, String machine);
+
+	/**
+	 * 
+	 * @param trans
+	 * @param req
+	 * @param resp
+	 * @return
+	 */
+	Result<Void> updateArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp);
+	
+	/**
+	 * 
+	 * @param trans
+	 * @param req
+	 * @param resp
+	 * @return
+	 */
+	Result<Void> deleteArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp);
+
+	/**
+	 * 
+	 * @param trans
+	 * @param resp
+	 * @param mechid
+	 * @param machine
+	 * @return
+	 */
+	Result<Void> deleteArtifacts(AuthzTrans trans, HttpServletResponse resp, String mechid, String machine);
+
+
+}
\ No newline at end of file
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/facade/Facade1_0.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/facade/Facade1_0.java
new file mode 100644
index 0000000..49d976b
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/facade/Facade1_0.java
@@ -0,0 +1,46 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cm.facade;
+
+import org.onap.aaf.auth.cm.AAF_CM;
+import org.onap.aaf.auth.cm.mapper.Mapper;
+import org.onap.aaf.auth.cm.service.CMService;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Data;
+
+import aaf.v2_0.Error;
+import certman.v1_0.Artifacts;
+import certman.v1_0.BaseRequest;
+import certman.v1_0.CertInfo;
+
+/**
+ * @author Jonathan
+ *
+ */
+public class Facade1_0 extends FacadeImpl<BaseRequest,CertInfo, Artifacts, Error> {
+	public Facade1_0(AAF_CM certman, 
+					 CMService service, 
+					 Mapper<BaseRequest,CertInfo,Artifacts,Error> mapper, 
+					 Data.TYPE type) throws APIException {
+		super(certman, service, mapper, type);
+	}
+}
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/facade/FacadeFactory.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/facade/FacadeFactory.java
new file mode 100644
index 0000000..6eb13f9
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/facade/FacadeFactory.java
@@ -0,0 +1,41 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cm.facade;
+
+import org.onap.aaf.auth.cm.AAF_CM;
+import org.onap.aaf.auth.cm.mapper.Mapper1_0;
+import org.onap.aaf.auth.cm.service.CMService;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Data;
+
+
+public class FacadeFactory {
+	public static Facade1_0 v1_0(AAF_CM certman, AuthzTrans trans, CMService service, Data.TYPE type) throws APIException {
+		return new Facade1_0(
+				certman,
+				service,
+				new Mapper1_0(),
+				type);  
+	}
+
+}
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/facade/FacadeImpl.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/facade/FacadeImpl.java
new file mode 100644
index 0000000..0598ee6
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/facade/FacadeImpl.java
@@ -0,0 +1,643 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cm.facade;
+
+import static org.onap.aaf.auth.layer.Result.ERR_ActionNotCompleted;
+import static org.onap.aaf.auth.layer.Result.ERR_BadData;
+import static org.onap.aaf.auth.layer.Result.ERR_ConflictAlreadyExists;
+import static org.onap.aaf.auth.layer.Result.ERR_Denied;
+import static org.onap.aaf.auth.layer.Result.ERR_NotFound;
+import static org.onap.aaf.auth.layer.Result.ERR_NotImplemented;
+import static org.onap.aaf.auth.layer.Result.ERR_Policy;
+import static org.onap.aaf.auth.layer.Result.ERR_Security;
+import static org.onap.aaf.auth.layer.Result.OK;
+
+import java.io.IOException;
+import java.security.KeyStore;
+import java.security.KeyStoreException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.onap.aaf.auth.cm.AAF_CM;
+import org.onap.aaf.auth.cm.ca.CA;
+import org.onap.aaf.auth.cm.data.CertResp;
+import org.onap.aaf.auth.cm.mapper.Mapper;
+import org.onap.aaf.auth.cm.mapper.Mapper.API;
+import org.onap.aaf.auth.cm.service.CMService;
+import org.onap.aaf.auth.dao.cass.ArtiDAO;
+import org.onap.aaf.auth.dao.cass.Status;
+import org.onap.aaf.auth.env.AuthzEnv;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.layer.Result;
+import org.onap.aaf.cadi.aaf.AAFPermission;
+import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.cadi.cm.Factory;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Data;
+import org.onap.aaf.misc.env.Env;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.env.util.Split;
+import org.onap.aaf.misc.rosetta.env.RosettaDF;
+import org.onap.aaf.misc.rosetta.env.RosettaData;
+
+/**
+ * AuthzFacade
+ * 
+ * This Service Facade encapsulates the essence of the API Service can do, and provides
+ * a single created object for elements such as RosettaDF.
+ *
+ * The Responsibilities of this class are to:
+ * 1) Interact with the Service Implementation (which might be supported by various kinds of Backend Storage)
+ * 2) Validate incoming data (if applicable)
+ * 3) Convert the Service response into the right Format, and mark the Content Type
+ * 		a) In the future, we may support multiple Response Formats, aka JSON or XML, based on User Request.
+ * 4) Log Service info, warnings and exceptions as necessary
+ * 5) When asked by the API layer, this will create and write Error content to the OutputStream
+ * 
+ * Note: This Class does NOT set the HTTP Status Code.  That is up to the API layer, so that it can be 
+ * clearly coordinated with the API Documentation
+ * 
+ * @author Jonathan
+ *
+ */
+public abstract class FacadeImpl<REQ,CERT,ARTIFACTS,ERROR> extends org.onap.aaf.auth.layer.FacadeImpl implements Facade<REQ,CERT,ARTIFACTS,ERROR> 
+	{
+	private static final String TRUE = "TRUE";
+	private static final String REQUEST_CERT = "Request New Certificate";
+	private static final String RENEW_CERT = "Renew Certificate";
+	private static final String DROP_CERT = "Drop Certificate";
+	private static final String READ_CERTS_MECHID = "Read Certificates by MechID";
+	private static final String CREATE_ARTIFACTS = "Create Deployment Artifact";
+	private static final String READ_ARTIFACTS = "Read Deployment Artifact";
+	private static final String UPDATE_ARTIFACTS = "Update Deployment Artifact";
+	private static final String DELETE_ARTIFACTS = "Delete Deployment Artifact";
+
+	private CMService service;
+
+	private final RosettaDF<ERROR>	 	errDF;
+	private final RosettaDF<REQ> 		certRequestDF, certRenewDF, certDropDF;
+	private final RosettaDF<CERT>		certDF;
+	private final RosettaDF<ARTIFACTS>	artiDF;
+	private Mapper<REQ, CERT, ARTIFACTS, ERROR> 	mapper;
+//	private Slot sCertAuth;
+	private AAF_CM certman;
+	private final String voidResp;
+
+	public FacadeImpl(AAF_CM certman,
+					  CMService service, 
+					  Mapper<REQ,CERT,ARTIFACTS,ERROR> mapper, 
+					  Data.TYPE dataType) throws APIException {
+		this.service = service;
+		this.mapper = mapper;
+		this.certman = certman;
+		AuthzEnv env = certman.env;
+		//TODO: Gabe [JUnit] Static issue, talk to Jonathan
+		(errDF 				= env.newDataFactory(mapper.getClass(API.ERROR))).in(dataType).out(dataType);
+		(certRequestDF 		= env.newDataFactory(mapper.getClass(API.CERT_REQ))).in(dataType).out(dataType);
+		(certRenewDF 		= env.newDataFactory(mapper.getClass(API.CERT_RENEW))).in(dataType).out(dataType);
+		(certDropDF 		= env.newDataFactory(mapper.getClass(API.CERT_DROP))).in(dataType).out(dataType);
+		(certDF 			= env.newDataFactory(mapper.getClass(API.CERT))).in(dataType).out(dataType);
+		(artiDF 			= env.newDataFactory(mapper.getClass(API.ARTIFACTS))).in(dataType).out(dataType);
+//		sCertAuth = env.slot(API_Cert.CERT_AUTH);
+		if(artiDF.getOutType().name().contains("xml")) {
+			voidResp = "application/Void+xml;charset=utf-8;version=1.0,application/xml;version=1.0,*/*";
+		} else {
+			voidResp = "application/Void+json;charset=utf-8;version=1.0,application/json;version=1.0,*/*";
+		}
+	}
+	
+	public Mapper<REQ,CERT,ARTIFACTS,ERROR> mapper() {
+		return mapper;
+	}
+	
+	/* (non-Javadoc)
+	 * @see com.att.authz.facade.AuthzFacade#error(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletResponse, int)
+	 * 
+	 * Note: Conforms to AT&T TSS RESTful Error Structure
+	 */
+	@Override
+	public void error(AuthzTrans trans, HttpServletResponse response, Result<?> result) {
+		error(trans, response, result.status,
+				result.details==null?"":result.details.trim(),
+				result.variables==null?new String[0]:result.variables);
+	}
+		
+	@Override
+	public void error(AuthzTrans trans, HttpServletResponse response, int status, final String _msg, final String ... _detail) {
+		String msgId;
+		String prefix;
+		boolean hidemsg=false;
+		switch(status) {
+			case 202:
+			case ERR_ActionNotCompleted:
+				msgId = "SVC1202";
+				prefix = "Accepted, Action not complete";
+				response.setStatus(/*httpstatus=*/202);
+				break;
+
+			case 403:
+			case ERR_Policy:
+			case ERR_Security:
+			case ERR_Denied:
+				msgId = "SVC1403";
+				prefix = "Forbidden";
+				response.setStatus(/*httpstatus=*/403);
+				break;
+				
+			case 404:
+			case ERR_NotFound:
+				msgId = "SVC1404";
+				prefix = "Not Found";
+				response.setStatus(/*httpstatus=*/404);
+				break;
+
+			case 406:
+			case ERR_BadData:
+				msgId="SVC1406";
+				prefix = "Not Acceptable";
+				response.setStatus(/*httpstatus=*/406);
+				break;
+				
+			case 409:
+			case ERR_ConflictAlreadyExists:
+				msgId = "SVC1409";
+				prefix = "Conflict Already Exists";
+				response.setStatus(/*httpstatus=*/409);
+				break;
+			
+			case 501:
+			case ERR_NotImplemented:
+				msgId = "SVC1501";
+				prefix = "Not Implemented"; 
+				response.setStatus(/*httpstatus=*/501);
+				break;
+				
+
+			default:
+				msgId = "SVC1500";
+				prefix = "General Service Error";
+				response.setStatus(/*httpstatus=*/500);
+				hidemsg=true;
+				break;
+		}
+
+		try {
+			StringBuilder holder = new StringBuilder();
+			ERROR em = mapper().errorFromMessage(holder, msgId,prefix + ": " + _msg,_detail);
+			trans.checkpoint(
+					"ErrResp [" + 
+					msgId +
+					"] " +
+					holder.toString(),
+					Env.ALWAYS);
+			if(hidemsg) {
+				holder.setLength(0);
+				em = mapper().errorFromMessage(holder, msgId, "Server had an issue processing this request");
+			}
+			errDF.newData(trans).load(em).to(response.getOutputStream());
+			
+		} catch (Exception e) {
+			trans.error().log(e,"unable to send response for",_msg);
+		}
+	}
+
+	@Override
+	public Result<Void> check(AuthzTrans trans, HttpServletResponse resp, String perm) throws IOException {
+		String[] p = Split.split('|',perm);
+		if(p.length!=3) {
+			return Result.err(Result.ERR_BadData,"Invalid Perm String");
+		}
+		AAFPermission ap = new AAFPermission(p[0],p[1],p[2]);
+		if(certman.aafLurPerm.fish(trans.getUserPrincipal(), ap)) {
+			resp.setContentType(voidResp);
+			resp.getOutputStream().write(0);
+			return Result.ok();
+		} else {
+			return Result.err(Result.ERR_Denied,"%s does not have %s",trans.user(),ap.getKey());
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see com.att.auth.certman.facade.Facade#requestCert(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+	 */
+	@Override
+	public Result<Void> requestCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, CA ca) {
+		TimeTaken tt = trans.start(REQUEST_CERT, Env.SUB|Env.ALWAYS);
+		String wt;
+		boolean withTrust=(wt=req.getParameter("withTrust"))!=null || TRUE.equalsIgnoreCase(wt);
+		try {
+			REQ request;
+			try {
+				Data<REQ> rd = certRequestDF.newData().load(req.getInputStream());
+				request = rd.asObject();
+			} catch(APIException e) {
+				trans.error().log("Invalid Input",IN,REQUEST_CERT);
+				return Result.err(Result.ERR_BadData,"Invalid Input");
+			}
+			
+			Result<CertResp> rcr = service.requestCert(trans,mapper.toReq(trans,request), ca);
+			if(rcr.notOK()) {
+				return Result.err(rcr);
+			}
+			
+//			CA certAuth = trans.get(sCertAuth,null);
+			Result<CERT> rc = mapper.toCert(trans, rcr, withTrust);
+			switch(rc.status) {
+				case OK: 
+					RosettaData<CERT> data = certDF.newData(trans).load(rc.value);
+					data.to(resp.getOutputStream());
+	
+					setContentType(resp,certDF.getOutType());
+					return Result.ok();
+				default:
+					return Result.err(rc);
+			}
+
+		} catch (Exception e) {
+			trans.error().log(e,IN,REQUEST_CERT);
+			return Result.err(e);
+		} finally {
+			tt.done();
+		}
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.onap.aaf.auth.cm.facade.Facade#requestPersonalCert(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, boolean)
+	 */
+	@Override
+	public Result<Void> requestPersonalCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, CA ca) {
+		return Result.err(Result.ERR_NotImplemented,"not implemented yet");
+//		Result<CertResp> rcr = service.requestPersonalCert(trans,ca);
+//		if(rcr.notOK()) {
+//			return Result.err(rcr);
+//		} else {
+//			try {
+//				resp.setContentType("application/zip, application/octet-stream");
+//				ZipOutputStream zos = new ZipOutputStream(resp.getOutputStream());
+//				PrintStream ps = new PrintStream(zos);
+//				ZipEntry ze = new ZipEntry(trans.user()+".key");
+//				zos.putNextEntry(ze);
+//				ps.print(rcr.value.privateString());
+//				zos.closeEntry();
+//
+//				zos.putNextEntry(new ZipEntry(trans.user()+".crt"));
+//				ps.print(rcr.value.asCertString());
+//				zos.closeEntry();
+//				
+//				String wt;
+//				if((wt=req.getParameter("withTrust"))!=null || TRUE.equalsIgnoreCase(wt)) {
+//					zos.putNextEntry(new ZipEntry(trans.user()+".trustCrts"));
+//					for(String s : ca.getTrustChain()) {
+//						ps.println(s);
+//					}
+//					zos.closeEntry();
+//				}
+//				
+//				boolean withJKS = (wt=req.getParameter("withJKS"))!=null || TRUE.equalsIgnoreCase(wt);
+//				if(withJKS) {
+//					if(trans.getUserPrincipal() instanceof BasicPrincipal) {
+//						char[] cap = new String(((BasicPrincipal)trans.getUserPrincipal()).getCred()).toCharArray();
+//						KeyStore ks = keystore(trans, rcr.value, ca.getTrustChain(), trans.user(), cap);
+//						zos.putNextEntry(new ZipEntry(trans.user()+".jks"));
+//						ks.store(zos, cap);
+//						zos.closeEntry();
+//					}
+//				}
+//				
+//				zos.putNextEntry(new ZipEntry("cert_deploy.sh"));
+//				ps.println("# Deploy Certificate to ~/.aaf");
+//				ps.println("if [ \"$1\" = \"\" ]; then echo \"sh deploy.sh <zipfile>\";exit; else chmod 700 $HOME/.aaf; fi");
+//				ps.println("chmod 600 $1");
+//				ps.println("if [ ! -e $HOME/.aaf ]; then mkdir -m 700 $HOME/.aaf; fi");
+//				ps.println("THE_PWD=`pwd`");
+//				ps.println("cd $HOME/.aaf");
+//				ps.println("echo \"Deploying to `pwd`\"");
+//				ps.println("jar -xvf $THE_PWD/$1 " + trans.user());
+//				ps.println("chmod 600 " + trans.user() + ".key");
+//				if(withJKS) {
+//					ps.println("chmod 600 " + trans.user() + ".jks");
+//				}
+//				ps.println("cd $THE_PWD");
+//				ps.println("rm cert_deploy.sh");
+//				zos.closeEntry();
+//				
+//
+//				zos.close();
+//				
+//			} catch (IOException | KeyStoreException | CertificateException | APIException | CertException | NoSuchAlgorithmException e) {
+//				return Result.err(e);
+//			}
+//		}
+//
+//		return Result.ok();
+	}
+
+	private KeyStore keystore(AuthzTrans trans, CertResp cr, String[] trustChain, String name, char[] cap) throws KeyStoreException, CertificateException, APIException, IOException, CertException, NoSuchAlgorithmException {
+		KeyStore jks = KeyStore.getInstance("jks");
+		jks.load(null, cap);
+		
+		// Get the Cert(s)... Might include Trust store
+		List<String> lcerts = new ArrayList<String>();
+		lcerts.add(cr.asCertString());
+		for(String s : trustChain) {
+			lcerts.add(s);
+		}
+		
+		Collection<? extends Certificate> certColl = Factory.toX509Certificate(lcerts);
+		X509Certificate[] certs = new X509Certificate[certColl.size()];
+		certColl.toArray(certs);
+		KeyStore.ProtectionParameter protParam = new KeyStore.PasswordProtection(cap);
+		
+		PrivateKey pk = Factory.toPrivateKey(trans, cr.privateString());
+		KeyStore.PrivateKeyEntry pkEntry = 
+				new KeyStore.PrivateKeyEntry(pk, new Certificate[] {certs[0]});
+		jks.setEntry(name, pkEntry, protParam);
+		
+		int i=0;
+		for(X509Certificate x509 : certs) {
+			jks.setCertificateEntry("cert_"+ ++i, x509);
+		}
+		return jks;
+	}
+
+	@Override
+	public Result<Void> renewCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, boolean withTrust) {
+		TimeTaken tt = trans.start(RENEW_CERT, Env.SUB|Env.ALWAYS);
+		try {
+			REQ request;
+			try {
+				Data<REQ> rd = certRenewDF.newData().load(req.getInputStream());
+				request = rd.asObject();
+			} catch(APIException e) {
+				trans.error().log("Invalid Input",IN,RENEW_CERT);
+				return Result.err(Result.ERR_BadData,"Invalid Input");
+			}
+			
+//			String certAuth = trans.get(sCertAuth,null);
+			Result<CertResp> rcr = service.renewCert(trans,mapper.toRenew(trans,request));
+			Result<CERT> rc = mapper.toCert(trans, rcr, withTrust);
+
+			switch(rc.status) {
+				case OK: 
+					RosettaData<CERT> data = certDF.newData(trans).load(rc.value);
+					data.to(resp.getOutputStream());
+
+					setContentType(resp,certDF.getOutType());
+					return Result.ok();
+				default:
+					return Result.err(rc);
+			}
+		} catch (Exception e) {
+			trans.error().log(e,IN,RENEW_CERT);
+			return Result.err(e);
+		} finally {
+			tt.done();
+		}
+
+	}
+
+	@Override
+	public Result<Void> dropCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
+		TimeTaken tt = trans.start(DROP_CERT, Env.SUB|Env.ALWAYS);
+		try {
+			REQ request;
+			try {
+				Data<REQ> rd = certDropDF.newData().load(req.getInputStream());
+				request = rd.asObject();
+			} catch(APIException e) {
+				trans.error().log("Invalid Input",IN,DROP_CERT);
+				return Result.err(Result.ERR_BadData,"Invalid Input");
+			}
+			
+			Result<Void> rv = service.dropCert(trans,mapper.toDrop(trans, request));
+			switch(rv.status) {
+				case OK: 
+					setContentType(resp,certRequestDF.getOutType());
+					return Result.ok();
+				default:
+					return Result.err(rv);
+			}
+		} catch (Exception e) {
+			trans.error().log(e,IN,DROP_CERT);
+			return Result.err(e);
+		} finally {
+			tt.done();
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see org.onap.aaf.auth.cm.facade.Facade#readCertsByMechID(org.onap.aaf.auth.env.test.AuthzTrans, javax.servlet.http.HttpServletResponse, java.lang.String)
+	 */
+	@Override
+	public Result<Void> readCertsByMechID(AuthzTrans trans, HttpServletResponse resp, String mechID) {
+		TimeTaken tt = trans.start(READ_CERTS_MECHID, Env.SUB|Env.ALWAYS);
+		try {
+			Result<CERT> rc = mapper.toCert(trans, service.readCertsByMechID(trans,mechID));
+			switch(rc.status) {
+				case OK: 
+					RosettaData<CERT> data = certDF.newData(trans).load(rc.value);
+					data.to(resp.getOutputStream());
+	
+					setContentType(resp,certDF.getOutType());
+					return Result.ok();
+				default:
+					return Result.err(rc);
+			}
+		} catch (Exception e) {
+			trans.error().log(e,IN,READ_CERTS_MECHID);
+			return Result.err(e);
+		} finally {
+			tt.done();
+		}
+	}
+
+	////////////////////////////
+	// Artifacts
+	////////////////////////////
+	@Override
+	public Result<Void> createArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
+		TimeTaken tt = trans.start(CREATE_ARTIFACTS, Env.SUB);
+		try {
+			ARTIFACTS arti;
+			try {
+				Data<ARTIFACTS> rd = artiDF.newData().load(req.getInputStream());
+				arti = rd.asObject();
+			} catch(APIException e) {
+				trans.error().log("Invalid Input",IN,CREATE_ARTIFACTS);
+				return Result.err(Result.ERR_BadData,"Invalid Input");
+			}
+			
+			return service.createArtifact(trans,mapper.toArtifact(trans,arti));
+		} catch (Exception e) {
+
+			trans.error().log(e,IN,CREATE_ARTIFACTS);
+			return Result.err(e);
+		} finally {
+			tt.done();
+		}
+	}
+
+	@Override
+	public Result<Void> readArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
+		TimeTaken tt = trans.start(READ_ARTIFACTS, Env.SUB);
+		try {
+			String mechid = req.getParameter("mechid");
+			String machine = req.getParameter("machine");
+			String ns = req.getParameter("ns");
+			
+			Result<ARTIFACTS> ra;
+			if( machine !=null && mechid == null) {
+				ra = mapper.fromArtifacts(service.readArtifactsByMachine(trans, machine));
+			} else if(mechid!=null && machine==null) {
+				ra = mapper.fromArtifacts(service.readArtifactsByMechID(trans, mechid));
+			} else if(mechid!=null && machine!=null) {
+				ArtiDAO.Data add = new ArtiDAO.Data();
+				add.mechid = mechid;
+				add.machine = machine;
+				add.ns = ns;
+				ra = mapper.fromArtifacts(service.readArtifacts(trans,add));
+			} else if(ns!=null) {
+				ra = mapper.fromArtifacts(service.readArtifactsByNs(trans, ns));
+			} else {
+				ra = Result.err(Status.ERR_BadData,"Invalid request inputs");
+			}
+			
+			if(ra.isOK()) {
+				RosettaData<ARTIFACTS> data = artiDF.newData(trans).load(ra.value);
+				data.to(resp.getOutputStream());
+				setContentType(resp,artiDF.getOutType());
+				return Result.ok();
+			} else {
+				return Result.err(ra);
+			}
+
+		} catch (Exception e) {
+			trans.error().log(e,IN,READ_ARTIFACTS);
+			return Result.err(e);
+		} finally {
+			tt.done();
+		}
+	}
+
+	@Override
+	public Result<Void> readArtifacts(AuthzTrans trans, HttpServletResponse resp, String mechid, String machine) {
+		TimeTaken tt = trans.start(READ_ARTIFACTS, Env.SUB);
+		try {
+			ArtiDAO.Data add = new ArtiDAO.Data();
+			add.mechid = mechid;
+			add.machine = machine;
+			Result<ARTIFACTS> ra = mapper.fromArtifacts(service.readArtifacts(trans,add));
+			if(ra.isOK()) {
+				RosettaData<ARTIFACTS> data = artiDF.newData(trans).load(ra.value);
+				data.to(resp.getOutputStream());
+				setContentType(resp,artiDF.getOutType());
+				return Result.ok();
+			} else {
+				return Result.err(ra);
+			}
+		} catch (Exception e) {
+			trans.error().log(e,IN,READ_ARTIFACTS);
+			return Result.err(e);
+		} finally {
+			tt.done();
+		}
+	}
+
+
+	@Override
+	public Result<Void> updateArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
+		TimeTaken tt = trans.start(UPDATE_ARTIFACTS, Env.SUB);
+		try {
+			ARTIFACTS arti;
+			try {
+				Data<ARTIFACTS> rd = artiDF.newData().load(req.getInputStream());
+				arti = rd.asObject();
+			} catch(APIException e) {
+				trans.error().log("Invalid Input",IN,UPDATE_ARTIFACTS);
+				return Result.err(Result.ERR_BadData,"Invalid Input");
+			}
+			
+			return service.updateArtifact(trans,mapper.toArtifact(trans,arti));
+		} catch (Exception e) {
+			trans.error().log(e,IN,UPDATE_ARTIFACTS);
+			return Result.err(e);
+		} finally {
+			tt.done();
+		}
+	}
+
+	@Override
+	public Result<Void> deleteArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) {
+		TimeTaken tt = trans.start(DELETE_ARTIFACTS, Env.SUB);
+		try {
+			ARTIFACTS arti;
+			try {
+				Data<ARTIFACTS> rd = artiDF.newData().load(req.getInputStream());
+				arti = rd.asObject();
+			} catch(APIException e) {
+				trans.error().log("Invalid Input",IN,DELETE_ARTIFACTS);
+				return Result.err(Result.ERR_BadData,"Invalid Input");
+			}
+			
+			Result<Void> rv = service.deleteArtifact(trans,mapper.toArtifact(trans,arti));
+			switch(rv.status) {
+				case OK: 
+					setContentType(resp,artiDF.getOutType());
+			} 
+			return rv;
+		} catch (Exception e) {
+			trans.error().log(e,IN,DELETE_ARTIFACTS);
+			return Result.err(e);
+		} finally {
+			tt.done();
+		}
+	}
+
+	@Override
+	public Result<Void> deleteArtifacts(AuthzTrans trans, HttpServletResponse resp, String mechid, String machine) {
+		TimeTaken tt = trans.start(DELETE_ARTIFACTS, Env.SUB);
+		try {
+			Result<Void> rv = service.deleteArtifact(trans, mechid, machine);
+			switch(rv.status) {
+				case OK: 
+					setContentType(resp,artiDF.getOutType());
+			} 
+			return rv;
+		} catch (Exception e) {
+			trans.error().log(e,IN,DELETE_ARTIFACTS);
+			return Result.err(e);
+		} finally {
+			tt.done();
+		}
+	}
+
+
+}
\ No newline at end of file
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper.java
new file mode 100644
index 0000000..aadb665
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper.java
@@ -0,0 +1,54 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cm.mapper;
+
+import java.io.IOException;
+import java.util.List;
+
+import org.onap.aaf.auth.cm.data.CertDrop;
+import org.onap.aaf.auth.cm.data.CertRenew;
+import org.onap.aaf.auth.cm.data.CertReq;
+import org.onap.aaf.auth.cm.data.CertResp;
+import org.onap.aaf.auth.dao.cass.ArtiDAO;
+import org.onap.aaf.auth.dao.cass.CertDAO;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.layer.Result;
+
+public interface Mapper<REQ,CERT,ARTIFACTS,ERROR>
+{
+	public enum API{ERROR,VOID,CERT,CERT_REQ,CERT_RENEW,CERT_DROP,ARTIFACTS};
+	
+	public Class<?> getClass(API api);
+	public<A> A newInstance(API api);
+
+	public ERROR errorFromMessage(StringBuilder holder, String msgID, String text, String... detail);
+	
+	public Result<CERT> toCert(AuthzTrans trans, Result<CertResp> in, boolean withTrustChain) throws IOException;
+	public Result<CERT> toCert(AuthzTrans trans, Result<List<CertDAO.Data>> in);
+
+	public Result<CertReq> toReq(AuthzTrans trans, REQ req);
+	public Result<CertRenew> toRenew(AuthzTrans trans, REQ req);
+	public Result<CertDrop>  toDrop(AuthzTrans trans, REQ req);
+	
+	public List<ArtiDAO.Data> toArtifact(AuthzTrans trans, ARTIFACTS arti);
+	public Result<ARTIFACTS> fromArtifacts(Result<List<ArtiDAO.Data>> readArtifactsByMachine);
+}
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper1_0.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper1_0.java
new file mode 100644
index 0000000..3d865d3
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper1_0.java
@@ -0,0 +1,274 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cm.mapper;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.onap.aaf.auth.cm.data.CertDrop;
+import org.onap.aaf.auth.cm.data.CertRenew;
+import org.onap.aaf.auth.cm.data.CertReq;
+import org.onap.aaf.auth.cm.data.CertResp;
+import org.onap.aaf.auth.cm.validation.CertmanValidator;
+import org.onap.aaf.auth.dao.cass.ArtiDAO;
+import org.onap.aaf.auth.dao.cass.CertDAO;
+import org.onap.aaf.auth.dao.cass.ArtiDAO.Data;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.layer.Result;
+import org.onap.aaf.cadi.util.FQI;
+import org.onap.aaf.cadi.util.Vars;
+
+import aaf.v2_0.Error;
+import certman.v1_0.Artifacts;
+import certman.v1_0.Artifacts.Artifact;
+import certman.v1_0.BaseRequest;
+import certman.v1_0.CertInfo;
+import certman.v1_0.CertificateDrop;
+import certman.v1_0.CertificateRenew;
+import certman.v1_0.CertificateRequest;
+
+
+public class Mapper1_0 implements Mapper<BaseRequest,CertInfo,Artifacts,Error> {
+	
+	@Override
+	public Class<?> getClass(API api) {
+		switch(api) {
+			case CERT_REQ: return CertificateRequest.class;
+			case CERT_RENEW: return CertificateRenew.class;
+			case CERT_DROP: return CertificateDrop.class;
+			case CERT: return CertInfo.class;
+			case ARTIFACTS: return Artifacts.class;
+			case ERROR: return Error.class;
+			case VOID: return Void.class;
+		}
+		return null;
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public <A> A newInstance(API api) {
+		switch(api) {
+			case CERT_REQ: return (A) new CertificateRequest();
+			case CERT_RENEW: return (A) new CertificateRenew();
+			case CERT_DROP: return (A) new CertificateDrop();
+			case CERT: return (A) new CertInfo();
+			case ARTIFACTS: return (A) new Artifacts();
+			case ERROR: return (A)new Error();
+			case VOID: return null;
+		}
+		return null;
+	}
+
+	//////////////  Mapping Functions /////////////
+	@Override
+	public Error errorFromMessage(StringBuilder holder, String msgID, String text, String... var) {
+		Error err = new Error();
+		err.setMessageId(msgID);
+		// AT&T Restful Error Format requires numbers "%" placements
+		err.setText(Vars.convert(holder, text, var));
+		for(String s : var) {
+			err.getVariables().add(s);
+		}
+		return err;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.att.authz.certman.mapper.Mapper#toCert(org.onap.aaf.auth.env.test.AuthzTrans, org.onap.aaf.auth.layer.test.Result)
+	 */
+	@Override
+	public Result<CertInfo> toCert(AuthzTrans trans, Result<CertResp> in, boolean withTrustChain) throws IOException {
+		if(in.isOK()) {
+			CertResp cin = in.value;
+			CertInfo cout = newInstance(API.CERT);
+			cout.setPrivatekey(cin.privateString());
+			String value;
+			if((value=cin.challenge())!=null) {
+				cout.setChallenge(value);
+			}
+			cout.getCerts().add(cin.asCertString());
+			if(cin.trustChain()!=null) {
+				for(String c : cin.trustChain()) {
+					if(c!=null) {
+						cout.getCerts().add(c);
+					}
+				}
+			}
+			// Adding all the Certs in one response is a mistake.  Makes it very hard for Agent to setup 
+			// Certs in keystore versus Truststore.  Separate in Version 2_0
+			if(cin.trustCAs()!=null) {
+				for(String c : cin.trustCAs()) {
+					if(c!=null) {
+						cout.getCerts().add(c);
+					} 
+				}
+			}
+			if(cin.notes()!=null) {
+				boolean first = true;
+				StringBuilder sb = new StringBuilder();
+				for(String n : cin.notes()) {
+					if(first) {
+						first = false;
+					} else {
+						sb.append('\n');
+					}
+					sb.append(n);
+				}
+				cout.setNotes(sb.toString());
+			}
+			cout.getCaIssuerDNs().addAll(cin.caIssuerDNs());
+			cout.setEnv(cin.env());
+			return Result.ok(cout);
+		} else {
+			return Result.err(in);
+		}
+	}
+
+	@Override
+	public Result<CertInfo> toCert(AuthzTrans trans, Result<List<CertDAO.Data>> in) {
+		if(in.isOK()) {
+			CertInfo cout = newInstance(API.CERT);
+			List<String> certs = cout.getCerts();
+			for(CertDAO.Data cdd : in.value) {
+				certs.add(cdd.x509);
+			}
+			return Result.ok(cout);
+		} else {
+			return Result.err(in);
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see com.att.authz.certman.mapper.Mapper#toReq(org.onap.aaf.auth.env.test.AuthzTrans, java.lang.Object)
+	 */
+	@Override
+	public Result<CertReq> toReq(AuthzTrans trans, BaseRequest req) {
+		CertificateRequest in;
+		try {
+			in = (CertificateRequest)req;
+		} catch(ClassCastException e) {
+			return Result.err(Result.ERR_BadData,"Request is not a CertificateRequest");
+		}
+
+		CertReq out = new CertReq();
+		CertmanValidator v = new CertmanValidator();
+		v.isNull("CertRequest", req)
+			.nullOrBlank("MechID", out.mechid=in.getMechid());
+		v.nullBlankMin("FQDNs", out.fqdns=in.getFqdns(),1);
+		if(v.err()) {
+			return Result.err(Result.ERR_BadData, v.errs());
+		}
+		out.emails = in.getEmail();
+		out.sponsor=in.getSponsor();
+		out.start = in.getStart();
+		out.end = in.getEnd();
+		out.fqdns = in.getFqdns();
+		return Result.ok(out);
+	}
+
+	/* (non-Javadoc)
+	 * @see com.att.authz.certman.mapper.Mapper#toRenew(org.onap.aaf.auth.env.test.AuthzTrans, java.lang.Object)
+	 */
+	@Override
+	public Result<CertRenew> toRenew(AuthzTrans trans, BaseRequest req) {
+		return Result.err(Result.ERR_NotImplemented,"Not Implemented... yet");
+	}
+
+	/* (non-Javadoc)
+	 * @see com.att.authz.certman.mapper.Mapper#toDrop(org.onap.aaf.auth.env.test.AuthzTrans, java.lang.Object)
+	 */
+	@Override
+	public Result<CertDrop> toDrop(AuthzTrans trans, BaseRequest req) {
+		return Result.err(Result.ERR_NotImplemented,"Not Implemented... yet");
+	}
+
+	/* (non-Javadoc)
+	 * @see org.onap.aaf.auth.cm.mapper.Mapper#toArtifact(org.onap.aaf.auth.env.test.AuthzTrans, java.lang.Object)
+	 */
+	@Override
+	public List<ArtiDAO.Data> toArtifact(AuthzTrans trans, Artifacts artifacts) {
+		List<ArtiDAO.Data> ladd = new ArrayList<ArtiDAO.Data>();
+		for(Artifact arti : artifacts.getArtifact()) {
+			ArtiDAO.Data data = new ArtiDAO.Data();
+			data.mechid = arti.getMechid();
+			data.machine = arti.getMachine();
+			data.type(true).addAll(arti.getType());
+			data.ca = arti.getCa();
+			data.dir = arti.getDir();
+			data.os_user = arti.getOsUser();
+			// Optional (on way in)
+			data.ns = arti.getNs();
+			data.renewDays = arti.getRenewDays();
+			data.notify = arti.getNotification();
+			
+			// Ignored on way in for create/update
+			data.sponsor = arti.getSponsor();
+			data.expires = null;
+			
+			// Derive Optional Data from Machine (Domain) if exists
+			if(data.machine!=null) {
+				if(data.ca==null) {
+					if(data.machine.endsWith(".att.com")) {
+						data.ca = "aaf"; // default
+					}
+				}
+				if(data.ns==null ) {
+					data.ns=FQI.reverseDomain(data.machine);
+				}
+			}
+			data.sans(true).addAll(arti.getSans());
+			ladd.add(data);
+		}
+		return ladd;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.onap.aaf.auth.cm.mapper.Mapper#fromArtifacts(org.onap.aaf.auth.layer.test.Result)
+	 */
+	@Override
+	public Result<Artifacts> fromArtifacts(Result<List<Data>> lArtiDAO) {
+		if(lArtiDAO.isOK()) {
+			Artifacts artis = new Artifacts();
+			for(ArtiDAO.Data arti : lArtiDAO.value) {
+				Artifact a = new Artifact();
+				a.setMechid(arti.mechid);
+				a.setMachine(arti.machine);
+				a.setSponsor(arti.sponsor);
+				a.setNs(arti.ns);
+				a.setCa(arti.ca);
+				a.setDir(arti.dir);
+				a.getType().addAll(arti.type(false));
+				a.setOsUser(arti.os_user);
+				a.setRenewDays(arti.renewDays);
+				a.setNotification(arti.notify);
+				a.getSans().addAll(arti.sans(false));
+				artis.getArtifact().add(a);
+			}
+			return Result.ok(artis);
+		} else {
+			return Result.err(lArtiDAO);
+		}
+	}
+	
+	
+
+}
\ No newline at end of file
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper2_0.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper2_0.java
new file mode 100644
index 0000000..13123bd
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper2_0.java
@@ -0,0 +1,268 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cm.mapper;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.onap.aaf.auth.cm.data.CertDrop;
+import org.onap.aaf.auth.cm.data.CertRenew;
+import org.onap.aaf.auth.cm.data.CertReq;
+import org.onap.aaf.auth.cm.data.CertResp;
+import org.onap.aaf.auth.cm.validation.CertmanValidator;
+import org.onap.aaf.auth.dao.cass.ArtiDAO;
+import org.onap.aaf.auth.dao.cass.ArtiDAO.Data;
+import org.onap.aaf.auth.dao.cass.CertDAO;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.layer.Result;
+import org.onap.aaf.cadi.util.FQI;
+import org.onap.aaf.cadi.util.Vars;
+
+import aaf.v2_0.Error;
+import certman.v1_0.Artifacts;
+import certman.v1_0.Artifacts.Artifact;
+import certman.v1_0.BaseRequest;
+import certman.v1_0.CertInfo;
+import certman.v1_0.CertificateDrop;
+import certman.v1_0.CertificateRenew;
+import certman.v1_0.CertificateRequest;
+
+
+public class Mapper2_0 implements Mapper<BaseRequest,CertInfo,Artifacts,Error> {
+	
+	@Override
+	public Class<?> getClass(API api) {
+		switch(api) {
+			case CERT_REQ: return CertificateRequest.class;
+			case CERT_RENEW: return CertificateRenew.class;
+			case CERT_DROP: return CertificateDrop.class;
+			case CERT: return CertInfo.class;
+			case ARTIFACTS: return Artifacts.class;
+			case ERROR: return Error.class;
+			case VOID: return Void.class;
+		}
+		return null;
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	public <A> A newInstance(API api) {
+		switch(api) {
+			case CERT_REQ: return (A) new CertificateRequest();
+			case CERT_RENEW: return (A) new CertificateRenew();
+			case CERT_DROP: return (A) new CertificateDrop();
+			case CERT: return (A) new CertInfo();
+			case ARTIFACTS: return (A) new Artifacts();
+			case ERROR: return (A)new Error();
+			case VOID: return null;
+		}
+		return null;
+	}
+
+	//////////////  Mapping Functions /////////////
+	@Override
+	public Error errorFromMessage(StringBuilder holder, String msgID, String text, String... var) {
+		Error err = new Error();
+		err.setMessageId(msgID);
+		// AT&T Restful Error Format requires numbers "%" placements
+		err.setText(Vars.convert(holder, text, var));
+		for(String s : var) {
+			err.getVariables().add(s);
+		}
+		return err;
+	}
+
+	/* (non-Javadoc)
+	 * @see com.att.authz.certman.mapper.Mapper#toCert(org.onap.aaf.auth.env.test.AuthzTrans, org.onap.aaf.auth.layer.test.Result)
+	 */
+	/* (non-Javadoc)
+	 * @see com.att.authz.certman.mapper.Mapper#toCert(org.onap.aaf.auth.env.test.AuthzTrans, org.onap.aaf.auth.layer.test.Result)
+	 */
+	@Override
+	public Result<CertInfo> toCert(AuthzTrans trans, Result<CertResp> in, boolean withTrustChain) throws IOException {
+		if(in.isOK()) {
+			CertResp cin = in.value;
+			CertInfo cout = newInstance(API.CERT);
+			cout.setPrivatekey(cin.privateString());
+			String value;
+			if((value=cin.challenge())!=null) {
+				cout.setChallenge(value);
+			}
+			cout.getCerts().add(cin.asCertString());
+			if(cin.trustChain()!=null) {
+				for(String c : cin.trustChain()) {
+					cout.getCerts().add(c);
+				}
+			}
+			if(cin.notes()!=null) {
+				boolean first = true;
+				StringBuilder sb = new StringBuilder();
+				for(String n : cin.notes()) {
+					if(first) {
+						first = false;
+					} else {
+						sb.append('\n');
+					}
+					sb.append(n);
+				}
+				cout.setNotes(sb.toString());
+			}
+			cout.getCaIssuerDNs().addAll(cin.caIssuerDNs());
+			cout.setEnv(cin.env());
+			return Result.ok(cout);
+		} else {
+			return Result.err(in);
+		}
+	}
+
+
+	@Override
+	public Result<CertInfo> toCert(AuthzTrans trans, Result<List<CertDAO.Data>> in) {
+		if(in.isOK()) {
+			CertInfo cout = newInstance(API.CERT);
+			List<String> certs = cout.getCerts();
+			for(CertDAO.Data cdd : in.value) {
+				certs.add(cdd.x509);
+			}
+			return Result.ok(cout);
+		} else {
+			return Result.err(in);
+		}
+	}
+
+	/* (non-Javadoc)
+	 * @see com.att.authz.certman.mapper.Mapper#toReq(org.onap.aaf.auth.env.test.AuthzTrans, java.lang.Object)
+	 */
+	@Override
+	public Result<CertReq> toReq(AuthzTrans trans, BaseRequest req) {
+		CertificateRequest in;
+		try {
+			in = (CertificateRequest)req;
+		} catch(ClassCastException e) {
+			return Result.err(Result.ERR_BadData,"Request is not a CertificateRequest");
+		}
+
+		CertReq out = new CertReq();
+		CertmanValidator v = new CertmanValidator();
+		v.isNull("CertRequest", req)
+			.nullOrBlank("MechID", out.mechid=in.getMechid());
+		v.nullBlankMin("FQDNs", out.fqdns=in.getFqdns(),1);
+		if(v.err()) {
+			return Result.err(Result.ERR_BadData, v.errs());
+		}
+
+		out.emails = in.getEmail();
+		out.sponsor=in.getSponsor();
+		out.start = in.getStart();
+		out.end = in.getEnd();
+		out.fqdns = in.getFqdns();
+		return Result.ok(out);
+	}
+
+	/* (non-Javadoc)
+	 * @see com.att.authz.certman.mapper.Mapper#toRenew(org.onap.aaf.auth.env.test.AuthzTrans, java.lang.Object)
+	 */
+	@Override
+	public Result<CertRenew> toRenew(AuthzTrans trans, BaseRequest req) {
+		return Result.err(Result.ERR_NotImplemented,"Not Implemented... yet");
+	}
+
+	/* (non-Javadoc)
+	 * @see com.att.authz.certman.mapper.Mapper#toDrop(org.onap.aaf.auth.env.test.AuthzTrans, java.lang.Object)
+	 */
+	@Override
+	public Result<CertDrop> toDrop(AuthzTrans trans, BaseRequest req) {
+		return Result.err(Result.ERR_NotImplemented,"Not Implemented... yet");
+	}
+
+	/* (non-Javadoc)
+	 * @see org.onap.aaf.auth.cm.mapper.Mapper#toArtifact(org.onap.aaf.auth.env.test.AuthzTrans, java.lang.Object)
+	 */
+	@Override
+	public List<ArtiDAO.Data> toArtifact(AuthzTrans trans, Artifacts artifacts) {
+		List<ArtiDAO.Data> ladd = new ArrayList<ArtiDAO.Data>();
+		for(Artifact arti : artifacts.getArtifact()) {
+			ArtiDAO.Data data = new ArtiDAO.Data();
+			data.mechid = arti.getMechid();
+			data.machine = arti.getMachine();
+			data.type(true).addAll(arti.getType());
+			data.ca = arti.getCa();
+			data.dir = arti.getDir();
+			data.os_user = arti.getOsUser();
+			// Optional (on way in)
+			data.ns = arti.getNs();
+			data.renewDays = arti.getRenewDays();
+			data.notify = arti.getNotification();
+			
+			// Ignored on way in for create/update
+			data.sponsor = arti.getSponsor();
+			data.expires = null;
+			
+			// Derive Optional Data from Machine (Domain) if exists
+			if(data.machine!=null) {
+				if(data.ca==null) {
+					if(data.machine.endsWith(".att.com")) {
+						data.ca = "aaf"; // default
+					}
+				}
+				if(data.ns==null ) {
+					data.ns=FQI.reverseDomain(data.machine);
+				}
+			}
+			data.sans(true).addAll(arti.getSans());
+			ladd.add(data);
+		}
+		return ladd;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.onap.aaf.auth.cm.mapper.Mapper#fromArtifacts(org.onap.aaf.auth.layer.test.Result)
+	 */
+	@Override
+	public Result<Artifacts> fromArtifacts(Result<List<Data>> lArtiDAO) {
+		if(lArtiDAO.isOK()) {
+			Artifacts artis = new Artifacts();
+			for(ArtiDAO.Data arti : lArtiDAO.value) {
+				Artifact a = new Artifact();
+				a.setMechid(arti.mechid);
+				a.setMachine(arti.machine);
+				a.setSponsor(arti.sponsor);
+				a.setNs(arti.ns);
+				a.setCa(arti.ca);
+				a.setDir(arti.dir);
+				a.getType().addAll(arti.type(false));
+				a.setOsUser(arti.os_user);
+				a.setRenewDays(arti.renewDays);
+				a.setNotification(arti.notify);
+				a.getSans().addAll(arti.sans(false));
+				artis.getArtifact().add(a);
+			}
+			return Result.ok(artis);
+		} else {
+			return Result.err(lArtiDAO);
+		}
+	}
+	
+	
+
+}
\ No newline at end of file
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/service/CMService.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/service/CMService.java
new file mode 100644
index 0000000..f6407d9
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/service/CMService.java
@@ -0,0 +1,693 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cm.service;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.ByteBuffer;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.onap.aaf.auth.cm.AAF_CM;
+import org.onap.aaf.auth.cm.ca.CA;
+import org.onap.aaf.auth.cm.ca.X509andChain;
+import org.onap.aaf.auth.cm.cert.BCFactory;
+import org.onap.aaf.auth.cm.cert.CSRMeta;
+import org.onap.aaf.auth.cm.data.CertDrop;
+import org.onap.aaf.auth.cm.data.CertRenew;
+import org.onap.aaf.auth.cm.data.CertReq;
+import org.onap.aaf.auth.cm.data.CertResp;
+import org.onap.aaf.auth.cm.validation.CertmanValidator;
+import org.onap.aaf.auth.dao.CassAccess;
+import org.onap.aaf.auth.dao.cass.ArtiDAO;
+import org.onap.aaf.auth.dao.cass.CacheInfoDAO;
+import org.onap.aaf.auth.dao.cass.CertDAO;
+import org.onap.aaf.auth.dao.cass.CertDAO.Data;
+import org.onap.aaf.auth.dao.cass.CredDAO;
+import org.onap.aaf.auth.dao.cass.HistoryDAO;
+import org.onap.aaf.auth.dao.cass.Status;
+import org.onap.aaf.auth.dao.hl.Question;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.layer.Result;
+import org.onap.aaf.auth.org.Organization;
+import org.onap.aaf.auth.org.Organization.Identity;
+import org.onap.aaf.auth.org.OrganizationException;
+import org.onap.aaf.cadi.Hash;
+import org.onap.aaf.cadi.aaf.AAFPermission;
+import org.onap.aaf.cadi.cm.Factory;
+import org.onap.aaf.cadi.util.FQI;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.util.Chrono;
+
+
+public class CMService {
+	// If we add more CAs, may want to parameterize
+	private static final int STD_RENEWAL = 30;
+	private static final int MAX_RENEWAL = 60;
+	private static final int MIN_RENEWAL = 10;
+	
+	public static final String REQUEST = "request";
+	public static final String RENEW = "renew";
+	public static final String DROP = "drop";
+//	public static final String SANS = "san";
+	public static final String IPS = "ips";
+	public static final String DOMAIN = "domain";
+	
+	private static final String[] NO_NOTES = new String[0];
+	private final CertDAO certDAO;
+	private final CredDAO credDAO;
+	private final ArtiDAO artiDAO;
+//	private DAO<AuthzTrans, ?>[] daos;
+	private AAF_CM certman;
+
+//	@SuppressWarnings("unchecked")
+	public CMService(final AuthzTrans trans, AAF_CM certman) throws APIException, IOException {
+		// Jonathan 4/2015 SessionFilter unneeded... DataStax already deals with Multithreading well
+		
+		HistoryDAO hd = new HistoryDAO(trans,  certman.cluster, CassAccess.KEYSPACE);
+		CacheInfoDAO cid = new CacheInfoDAO(trans, hd);
+		certDAO = new CertDAO(trans, hd, cid);
+		credDAO = new CredDAO(trans, hd, cid);
+		artiDAO = new ArtiDAO(trans, hd, cid);
+		
+//		daos =(DAO<AuthzTrans, ?>[]) new DAO<?,?>[] {
+//				hd,cid,certDAO,credDAO,artiDAO
+//		};
+//
+		this.certman = certman;
+	}
+	
+	public Result<CertResp> requestCert(final AuthzTrans trans,final Result<CertReq> req, final CA ca) {
+		if(req.isOK()) {
+
+			if(req.value.fqdns.isEmpty()) {
+				return Result.err(Result.ERR_BadData,"No Machines passed in Request");
+			}
+			
+			String key = req.value.fqdns.get(0);
+			
+			// Policy 6: Requester must be granted Change permission in Namespace requested
+			String mechNS = FQI.reverseDomain(req.value.mechid);
+			if(mechNS==null) {
+				return Result.err(Status.ERR_Denied, "%s does not reflect a valid AAF Namespace",req.value.mechid);
+			}
+			
+
+			// Disallow non-AAF CA without special permission
+			if(!ca.getName().equals("aaf") && !trans.fish( new AAFPermission(mechNS+".certman", ca.getName(), REQUEST))) {
+				return Result.err(Status.ERR_Denied, "'%s' does not have permission to request Certificates from Certificate Authority '%s'", 
+						trans.user(),ca.getName());
+			}
+
+			List<String> notes = null;
+			List<String> fqdns = new ArrayList<String>(req.value.fqdns);
+			
+			
+			String email = null;
+
+			try {
+				Organization org = trans.org();
+				
+				InetAddress primary = null;
+				// Organize incoming information to get to appropriate Artifact
+				if(fqdns.size()>=1) {
+					// Accept domain wild cards, but turn into real machines
+					// Need *domain.com:real.machine.domain.com:san.machine.domain.com:...
+					if(fqdns.get(0).startsWith("*")) { // Domain set
+						if(!trans.fish(new AAFPermission(ca.getPermType(), ca.getName(), DOMAIN))) {
+							return Result.err(Result.ERR_Denied, "Domain based Authorizations (" + fqdns.get(0) + ") requires Exception");
+						}
+						
+						//TODO check for Permission in Add Artifact?
+						String domain = fqdns.get(0).substring(1);
+						fqdns.remove(0);
+						if(fqdns.size()>=1) {
+							InetAddress ia = InetAddress.getByName(fqdns.get(0));
+							if(ia==null) {
+								return Result.err(Result.ERR_Denied, "Request not made from matching IP matching domain");
+							} else if(ia.getHostName().endsWith(domain)) {
+								primary = ia;
+							}
+						} else {
+							return Result.err(Result.ERR_Denied, "Requests using domain require machine declaration");
+						}
+					
+	 				} else {
+						for(String cn : req.value.fqdns) {
+							try {
+								InetAddress[] ias = InetAddress.getAllByName(cn);
+								Set<String> potentialSanNames = new HashSet<String>();
+								for(InetAddress ia1 : ias) {
+									InetAddress ia2 = InetAddress.getByAddress(ia1.getAddress());
+									if(primary==null && ias.length==1 && trans.ip().equals(ia1.getHostAddress())) {
+										primary = ia1;
+									} else if(!cn.equals(ia1.getHostName()) && !ia2.getHostName().equals(ia2.getHostAddress())) {
+										potentialSanNames.add(ia1.getHostName());
+									}
+								}
+							} catch (UnknownHostException e1) {
+								return Result.err(Result.ERR_BadData,"There is no DNS lookup for %s",cn);
+							}
+						
+						}
+					}
+				}
+				
+				if(primary==null) {
+					return Result.err(Result.ERR_Denied, "Request not made from matching IP (%s)",trans.ip());
+//					return Result.err(Result.ERR_BadData,"Calling Machine does not match DNS lookup for %s",req.value.fqdns.get(0));
+				}
+				
+				ArtiDAO.Data add = null;
+				Result<List<ArtiDAO.Data>> ra = artiDAO.read(trans, req.value.mechid,primary.getHostAddress());
+				if(ra.isOKhasData()) {
+					if(add==null) {
+						add = ra.value.get(0); // single key
+					}
+				} else {
+					 ra = artiDAO.read(trans, req.value.mechid,key);
+					 if(ra.isOKhasData()) { // is the Template available?
+						 add = ra.value.get(0);
+						 add.machine=primary.getHostName();
+						 for(String s : fqdns) {
+							  if(!s.equals(add.machine)) {
+								  add.sans(true).add(s);
+							  }
+						 }
+						 Result<ArtiDAO.Data> rc = artiDAO.create(trans, add); // Create new Artifact from Template
+						 if(rc.notOK()) {
+							 return Result.err(rc);
+						 }
+					 } else {
+						 add = ra.value.get(0);
+					 }
+				}
+				
+				// Add Artifact listed FQDNs
+				if(add.sans!=null) {
+					for(String s : add.sans) {
+						if(!fqdns.contains(s)) {
+							fqdns.add(s);
+						}
+					}
+				}
+
+				// Policy 2: If Config marked as Expired, do not create or renew
+				Date now = new Date();
+				if(add.expires!=null && now.after(add.expires)) {
+					return Result.err(Result.ERR_Policy,"Configuration for %s %s is expired %s",add.mechid,add.machine,Chrono.dateFmt.format(add.expires));
+				}
+				
+				// Policy 3: MechID must be current
+				Identity muser = org.getIdentity(trans, add.mechid);
+				if(muser == null) {
+					return Result.err(Result.ERR_Policy,"MechID must exist in %s",org.getName());
+				}
+				
+				// Policy 4: Sponsor must be current
+				Identity ouser = muser.responsibleTo();
+				if(ouser==null) {
+					return Result.err(Result.ERR_Policy,"%s does not have a current sponsor at %s",add.mechid,org.getName());
+				} else if(!ouser.isFound() || ouser.mayOwn()!=null) {
+					return Result.err(Result.ERR_Policy,"%s reports that %s cannot be responsible for %s",org.getName(),trans.user());
+				}
+				
+				// Set Email from most current Sponsor
+				email = ouser.email();
+				
+				// Policy 5: keep Artifact data current
+				if(!ouser.fullID().equals(add.sponsor)) {
+					add.sponsor = ouser.fullID();
+					artiDAO.update(trans, add);
+				}
+		
+				// Policy 7: Caller must be the MechID or have specifically delegated permissions
+				if(!(trans.user().equals(req.value.mechid) || trans.fish(new AAFPermission(mechNS + ".certman", ca.getName() , "request")))) {
+					return Result.err(Status.ERR_Denied, "%s must have access to modify x509 certs in NS %s",trans.user(),mechNS);
+				}
+				
+				// Policy 8: SANs only allowed by Exception... need permission
+				// 7/25/2017 - SAN Permission no longer required. CSO
+//				if(fqdns.size()>1 && !certman.aafLurPerm.fish(
+//						new Principal() {
+//							@Override
+//							public String getName() {
+//								return req.value.mechid;
+//							}
+//						},
+//						new AAFPermission(ca.getPermType(), ca.getName(), SANS))) {
+//					if(notes==null) {notes = new ArrayList<String>();}
+//					notes.add("Warning: Subject Alternative Names only allowed by Permission: Get CSO Exception.");
+//					return Result.err(Status.ERR_Denied, "%s must have a CSO Exception to work with SAN",trans.user());
+//				}
+				
+				// Make sure Primary is the first in fqdns
+				if(fqdns.size()>1) {
+					for(int i=0;i<fqdns.size();++i) {
+						if(fqdns.get(i).equals(primary.getHostName())) {
+							if(i!=0) {
+								String tmp = fqdns.get(0);
+								fqdns.set(0, primary.getHostName());
+								fqdns.set(i, tmp);
+							}
+						}
+					}
+				}
+			} catch (Exception e) {
+				trans.error().log(e);
+				return Result.err(Status.ERR_Denied,"MechID Sponsorship cannot be determined at this time.  Try later");
+			}
+			
+			CSRMeta csrMeta;
+			try {
+				csrMeta = BCFactory.createCSRMeta(
+						ca, 
+						req.value.mechid, 
+						email, 
+						fqdns);
+				X509andChain x509ac = ca.sign(trans, csrMeta);
+				if(x509ac==null) {
+					return Result.err(Result.ERR_ActionNotCompleted,"x509 Certificate not signed by CA");
+				}
+				trans.info().printf("X509 Subject: %s", x509ac.getX509().getSubjectDN());
+//				for(String s: x509ac.getTrustChain()) {
+//					trans.warn().printf("Trust Cert: \n%s", s);
+//				}
+				
+				X509Certificate x509 = x509ac.getX509();
+				CertDAO.Data cdd = new CertDAO.Data();
+				cdd.ca=ca.getName();
+				cdd.serial=x509.getSerialNumber();
+				cdd.id=req.value.mechid;
+				cdd.x500=x509.getSubjectDN().getName();
+				cdd.x509=Factory.toString(trans, x509);
+				certDAO.create(trans, cdd);
+				
+				CredDAO.Data crdd = new CredDAO.Data();
+				crdd.other = Question.random.nextInt();
+				crdd.cred=getChallenge256SaltedHash(csrMeta.challenge(),crdd.other);
+				crdd.expires = x509.getNotAfter();
+				crdd.id = req.value.mechid;
+				crdd.ns = Question.domain2ns(crdd.id);
+				crdd.type = CredDAO.CERT_SHA256_RSA;
+				credDAO.create(trans, crdd);
+				
+				CertResp cr = new CertResp(trans, ca, x509, csrMeta, x509ac.getTrustChain(), ca.getTrustedCAs(), compileNotes(notes));
+				return Result.ok(cr);
+			} catch (Exception e) {
+				trans.error().log(e);
+				return Result.err(Result.ERR_ActionNotCompleted,e.getMessage());
+			}
+		} else {
+			return Result.err(req);
+		}
+	}
+
+    public Result<CertResp> renewCert(AuthzTrans trans, Result<CertRenew> renew) {
+		if(renew.isOK()) {
+			return Result.err(Result.ERR_NotImplemented,"Not implemented yet");
+		} else {
+			return Result.err(renew);
+		}	
+	}
+
+	public Result<Void> dropCert(AuthzTrans trans, Result<CertDrop> drop) {
+		if(drop.isOK()) {
+			return Result.err(Result.ERR_NotImplemented,"Not implemented yet");
+		} else {
+			return Result.err(drop);
+		}	
+	}
+
+	public Result<List<Data>> readCertsByMechID(AuthzTrans trans, String mechID) {
+		// Policy 1: To Read, must have NS Read or is Sponsor
+		String ns = Question.domain2ns(mechID);
+		try {
+			if( trans.user().equals(mechID)
+					|| trans.fish(new AAFPermission(ns + ".access", "*", "read"))
+					|| (trans.org().validate(trans,Organization.Policy.OWNS_MECHID,null,mechID))==null) {
+				return certDAO.readID(trans, mechID);
+			} else {
+				return Result.err(Result.ERR_Denied,"%s is not the ID, Sponsor or NS Owner/Admin for %s at %s",
+						trans.user(),mechID,trans.org().getName());
+			}
+		} catch(OrganizationException e) {
+			return Result.err(e);
+		}
+	}
+
+	public Result<CertResp> requestPersonalCert(AuthzTrans trans, CA ca) {
+		if(ca.inPersonalDomains(trans.getUserPrincipal())) {
+			Organization org = trans.org();
+				
+			// Policy 1: MechID must be current
+			Identity ouser;
+			try {
+				ouser = org.getIdentity(trans, trans.user());
+			} catch (OrganizationException e1) {
+				trans.error().log(e1);
+				ouser = null;
+			}
+			if(ouser == null) {
+				return Result.err(Result.ERR_Policy,"Requesting User must exist in %s",org.getName());
+			}
+				
+			// Set Email from most current Sponsor
+				
+			CSRMeta csrMeta;
+			try {
+				csrMeta = BCFactory.createPersonalCSRMeta(
+						ca, 
+						trans.user(), 
+						ouser.email());
+				X509andChain x509ac = ca.sign(trans, csrMeta);
+				if(x509ac==null) {
+					return Result.err(Result.ERR_ActionNotCompleted,"x509 Certificate not signed by CA");
+				}
+				X509Certificate x509 = x509ac.getX509();
+				CertDAO.Data cdd = new CertDAO.Data();
+				cdd.ca=ca.getName();
+				cdd.serial=x509.getSerialNumber();
+				cdd.id=trans.user();
+				cdd.x500=x509.getSubjectDN().getName();
+				cdd.x509=Factory.toString(trans, x509);
+				certDAO.create(trans, cdd);
+				
+				CertResp cr = new CertResp(trans, ca, x509, csrMeta, x509ac.getTrustChain(), ca.getTrustedCAs(), compileNotes(null));
+				return Result.ok(cr);
+			} catch (Exception e) {
+				trans.error().log(e);
+				return Result.err(Result.ERR_ActionNotCompleted,e.getMessage());
+			}
+		} else {
+			return Result.err(Result.ERR_Denied,trans.user()," not supported for CA",ca.getName());
+		}
+	}
+
+	///////////////
+	// Artifact
+	//////////////
+	public Result<Void> createArtifact(AuthzTrans trans, List<ArtiDAO.Data> list) {
+		CertmanValidator v = new CertmanValidator().artisRequired(list, 1);
+		if(v.err()) {
+			return Result.err(Result.ERR_BadData,v.errs());
+		}
+		for(ArtiDAO.Data add : list) {
+			try {
+				// Policy 1: MechID must exist in Org
+				Identity muser = trans.org().getIdentity(trans, add.mechid);
+				if(muser == null) {
+					return Result.err(Result.ERR_Denied,"%s is not valid for %s", add.mechid,trans.org().getName());
+				}
+				
+				// Policy 2: MechID must have valid Organization Owner
+				Identity ouser = muser.responsibleTo();
+				if(ouser == null) {
+					return Result.err(Result.ERR_Denied,"%s is not a valid Sponsor for %s at %s",
+							trans.user(),add.mechid,trans.org().getName());
+				}
+				
+				// Policy 3: Calling ID must be MechID Owner
+				if(!trans.user().equals(ouser.fullID())) {
+					return Result.err(Result.ERR_Denied,"%s is not the Sponsor for %s at %s",
+							trans.user(),add.mechid,trans.org().getName());
+				}
+
+				// Policy 4: Renewal Days are between 10 and 60 (constants, may be parameterized)
+				if(add.renewDays<MIN_RENEWAL) {
+					add.renewDays = STD_RENEWAL;
+				} else if(add.renewDays>MAX_RENEWAL) {
+					add.renewDays = MAX_RENEWAL;
+				}
+				
+				// Policy 5: If Notify is blank, set to Owner's Email
+				if(add.notify==null || add.notify.length()==0) {
+					add.notify = "mailto:"+ouser.email();
+				}
+				
+				// Policy 6: Only do Domain by Exception
+				if(add.machine.startsWith("*")) { // Domain set
+					CA ca = certman.getCA(add.ca);
+
+
+					if(!trans.fish(new AAFPermission(ca.getPermType(), add.ca, DOMAIN))) {
+						return Result.err(Result.ERR_Denied,"Domain Artifacts (%s) requires specific Permission",
+							add.machine);
+					}
+				}
+
+				// Set Sponsor from Golden Source
+				add.sponsor = ouser.fullID();
+				
+				
+			} catch (OrganizationException e) {
+				return Result.err(e);
+			}
+			// Add to DB
+			Result<ArtiDAO.Data> rv = artiDAO.create(trans, add);
+			// TODO come up with Partial Reporting Scheme, or allow only one at a time.
+			if(rv.notOK()) {
+				return Result.err(rv);
+			}
+		}
+		return Result.ok();
+	}
+
+	public Result<List<ArtiDAO.Data>> readArtifacts(AuthzTrans trans, ArtiDAO.Data add) throws OrganizationException {
+		CertmanValidator v = new CertmanValidator().keys(add);
+		if(v.err()) {
+			return Result.err(Result.ERR_BadData,v.errs());
+		}
+		Result<List<ArtiDAO.Data>> data = artiDAO.read(trans, add);
+		if(data.notOKorIsEmpty()) {
+			return data;
+		}
+		add = data.value.get(0);
+		if( trans.user().equals(add.mechid)
+			|| trans.fish(new AAFPermission(add.ns + ".access", "*", "read"))
+			|| trans.fish(new AAFPermission(add.ns+".certman",add.ca,"read"))
+			|| trans.fish(new AAFPermission(add.ns+".certman",add.ca,"request"))
+			|| (trans.org().validate(trans,Organization.Policy.OWNS_MECHID,null,add.mechid))==null) {
+			return data;
+		} else {
+			return Result.err(Result.ERR_Denied,"%s is not %s, is not the sponsor, and doesn't have delegated permission.",trans.user(),add.mechid,add.ns+".certman|"+add.ca+"|read or ...|request"); // note: reason is set by 2nd case, if 1st case misses
+		}
+
+	}
+
+	public Result<List<ArtiDAO.Data>> readArtifactsByMechID(AuthzTrans trans, String mechid) throws OrganizationException {
+		CertmanValidator v = new CertmanValidator();
+		v.nullOrBlank("mechid", mechid);
+		if(v.err()) {
+			return Result.err(Result.ERR_BadData,v.errs());
+		}
+		String ns = FQI.reverseDomain(mechid);
+		
+		String reason;
+		if(trans.fish(new AAFPermission(ns + ".access", "*", "read"))
+			|| (reason=trans.org().validate(trans,Organization.Policy.OWNS_MECHID,null,mechid))==null) {
+			return artiDAO.readByMechID(trans, mechid);
+		} else {
+			return Result.err(Result.ERR_Denied,reason); // note: reason is set by 2nd case, if 1st case misses
+		}
+
+	}
+
+	public Result<List<ArtiDAO.Data>> readArtifactsByMachine(AuthzTrans trans, String machine) {
+		CertmanValidator v = new CertmanValidator();
+		v.nullOrBlank("machine", machine);
+		if(v.err()) {
+			return Result.err(Result.ERR_BadData,v.errs());
+		}
+		
+		// TODO do some checks?
+
+		Result<List<ArtiDAO.Data>> rv = artiDAO.readByMachine(trans, machine);
+		return rv;
+	}
+
+	public Result<List<ArtiDAO.Data>> readArtifactsByNs(AuthzTrans trans, String ns) {
+		CertmanValidator v = new CertmanValidator();
+		v.nullOrBlank("ns", ns);
+		if(v.err()) {
+			return Result.err(Result.ERR_BadData,v.errs());
+		}
+		
+		// TODO do some checks?
+
+		Result<List<ArtiDAO.Data>> rv = artiDAO.readByNs(trans, ns);
+		return rv;
+	}
+
+
+	public Result<Void> updateArtifact(AuthzTrans trans, List<ArtiDAO.Data> list) throws OrganizationException {
+		CertmanValidator v = new CertmanValidator();
+		v.artisRequired(list, 1);
+		if(v.err()) {
+			return Result.err(Result.ERR_BadData,v.errs());
+		}
+		
+		// Check if requesting User is Sponsor
+		//TODO - Shall we do one, or multiples?
+		for(ArtiDAO.Data add : list) {
+			// Policy 1: MechID must exist in Org
+			Identity muser = trans.org().getIdentity(trans, add.mechid);
+			if(muser == null) {
+				return Result.err(Result.ERR_Denied,"%s is not valid for %s", add.mechid,trans.org().getName());
+			}
+			
+			// Policy 2: MechID must have valid Organization Owner
+			Identity ouser = muser.responsibleTo();
+			if(ouser == null) {
+				return Result.err(Result.ERR_Denied,"%s is not a valid Sponsor for %s at %s",
+						trans.user(),add.mechid,trans.org().getName());
+			}
+
+			// Policy 3: Renewal Days are between 10 and 60 (constants, may be parameterized)
+			if(add.renewDays<MIN_RENEWAL) {
+				add.renewDays = STD_RENEWAL;
+			} else if(add.renewDays>MAX_RENEWAL) {
+				add.renewDays = MAX_RENEWAL;
+			}
+
+			// Policy 4: Data is always updated with the latest Sponsor
+			// Add to Sponsor, to make sure we are always up to date.
+			add.sponsor = ouser.fullID();
+
+			// Policy 5: If Notify is blank, set to Owner's Email
+			if(add.notify==null || add.notify.length()==0) {
+				add.notify = "mailto:"+ouser.email();
+			}
+			// Policy 6: Only do Domain by Exception
+			if(add.machine.startsWith("*")) { // Domain set
+				CA ca = certman.getCA(add.ca);
+				if(ca==null) {
+					return Result.err(Result.ERR_BadData, "CA is required in Artifact");
+				}
+				if(!trans.fish(new AAFPermission(ca.getPermType(), add.ca, DOMAIN))) {
+					return Result.err(Result.ERR_Denied,"Domain Artifacts (%s) requires specific Permission",
+						add.machine);
+				}
+			}
+
+			// Policy 7: only Owner may update info
+			if(trans.user().equals(add.sponsor)) {
+				return artiDAO.update(trans, add);
+			} else {
+				return Result.err(Result.ERR_Denied,"%s may not update info for %s",trans.user(),muser.fullID());
+			}
+		}
+		return Result.err(Result.ERR_BadData,"No Artifacts to update");
+	}
+	
+	public Result<Void> deleteArtifact(AuthzTrans trans, String mechid, String machine) throws OrganizationException {
+		CertmanValidator v = new CertmanValidator();
+		v.nullOrBlank("mechid", mechid)
+		 .nullOrBlank("machine", machine);
+		if(v.err()) {
+			return Result.err(Result.ERR_BadData,v.errs());
+		}
+
+		Result<List<ArtiDAO.Data>> rlad = artiDAO.read(trans, mechid, machine);
+		if(rlad.notOKorIsEmpty()) {
+			return Result.err(Result.ERR_NotFound,"Artifact for %s %s does not exist.",mechid,machine);
+		}
+		
+		return deleteArtifact(trans,rlad.value.get(0));
+	}
+		
+	private Result<Void> deleteArtifact(AuthzTrans trans, ArtiDAO.Data add) throws OrganizationException {
+		// Policy 1: Record should be delete able only by Existing Sponsor.  
+		String sponsor=null;
+		Identity muser = trans.org().getIdentity(trans, add.mechid);
+		if(muser != null) {
+			Identity ouser = muser.responsibleTo();
+			if(ouser!=null) {
+				sponsor = ouser.fullID();
+			}
+		}
+		// Policy 1.a: If Sponsorship is deleted in system of Record, then 
+		// accept deletion by sponsor in Artifact Table
+		if(sponsor==null) {
+			sponsor = add.sponsor;
+		}
+		
+		String ns = FQI.reverseDomain(add.mechid);
+
+		if(trans.fish(new AAFPermission(ns + ".access", "*", "write"))
+				|| trans.user().equals(sponsor)) {
+			return artiDAO.delete(trans, add, false);
+		}
+		return null;
+	}
+
+	public Result<Void> deleteArtifact(AuthzTrans trans, List<ArtiDAO.Data> list) {
+		CertmanValidator v = new CertmanValidator().artisRequired(list, 1);
+		if(v.err()) {
+			return Result.err(Result.ERR_BadData,v.errs());
+		}
+
+		try {
+			boolean partial = false;
+			Result<Void> result=null;
+			for(ArtiDAO.Data add : list) {
+				result = deleteArtifact(trans, add);
+				if(result.notOK()) {
+					partial = true;
+				}
+			}
+			if(result == null) {
+				result = Result.err(Result.ERR_BadData,"No Artifacts to delete"); 
+			} else if(partial) {
+				result.partialContent(true);
+			}
+			return result;
+		} catch(Exception e) {
+			return Result.err(e);
+		}
+	}
+
+	private String[] compileNotes(List<String> notes) {
+		String[] rv;
+		if(notes==null) {
+			rv = NO_NOTES;
+		} else {
+			rv = new String[notes.size()];
+			notes.toArray(rv);
+		}
+		return rv;
+	}
+
+	private ByteBuffer getChallenge256SaltedHash(String challenge, int salt) throws NoSuchAlgorithmException {
+		ByteBuffer bb = ByteBuffer.allocate(Integer.SIZE + challenge.length());
+		bb.putInt(salt);
+		bb.put(challenge.getBytes());
+		byte[] hash = Hash.hashSHA256(bb.array());
+		return ByteBuffer.wrap(hash);
+	}
+}
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/service/Code.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/service/Code.java
new file mode 100644
index 0000000..ce2ca06
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/service/Code.java
@@ -0,0 +1,45 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cm.service;
+
+import org.onap.aaf.auth.cm.AAF_CM;
+import org.onap.aaf.auth.cm.facade.Facade1_0;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.rserv.HttpCode;
+
+public abstract class Code extends HttpCode<AuthzTrans,Facade1_0> implements Cloneable {
+
+	public Code(AAF_CM cma, String description, String ... roles) {
+		super(cma.facade1_0, description, roles);
+		// Note, the first "Code" will be created with default Facade, "JSON".
+		// use clone for another Code with XML
+	}
+	
+
+	public <D extends Code> D clone(Facade1_0 facade) throws Exception {
+		@SuppressWarnings("unchecked")
+		D d = (D)clone();
+		d.context = facade;
+		return d;
+	}
+
+}
diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/validation/CertmanValidator.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/validation/CertmanValidator.java
new file mode 100644
index 0000000..d3ce0ac
--- /dev/null
+++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/validation/CertmanValidator.java
@@ -0,0 +1,121 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cm.validation;
+
+import java.util.List;
+
+import org.onap.aaf.auth.dao.cass.ArtiDAO;
+import org.onap.aaf.auth.dao.cass.ArtiDAO.Data;
+import org.onap.aaf.auth.validation.Validator;
+
+/**
+ * Validator
+ * Consistently apply content rules for content (incoming)
+ * 
+ * Note: We restrict content for usability in URLs (because RESTful service), and avoid 
+ * issues with Regular Expressions, and other enabling technologies. 
+ * @author Jonathan
+ *
+ */
+public class CertmanValidator extends Validator{
+	// Repeated Msg fragments
+	private static final String MECHID = "mechid";
+	private static final String MACHINE = "machine";
+	private static final String ARTIFACT_LIST_IS_NULL = "Artifact List is null.";
+	private static final String Y = "y.";
+	private static final String IES = "ies.";
+	private static final String ENTR = " entr";
+	private static final String MUST_HAVE_AT_LEAST = " must have at least ";
+	private static final String IS_NULL = " is null.";
+	private static final String ARTIFACTS_MUST_HAVE_AT_LEAST = "Artifacts must have at least ";
+
+	public CertmanValidator nullBlankMin(String name, List<String> list, int min) {
+		if(list==null) {
+			msg(name + IS_NULL);
+		} else {
+			if(list.size()<min) {
+				msg(name + MUST_HAVE_AT_LEAST + min + ENTR + (min==1?Y:IES));
+			} else {
+				for(String s : list) {
+					nullOrBlank("List Item",s);
+				}
+			}
+		}
+		return this;
+	}
+
+	public CertmanValidator artisRequired(List<ArtiDAO.Data> list, int min) {
+		if(list==null) {
+			msg(ARTIFACT_LIST_IS_NULL);
+		} else {
+			if(list.size()<min) {
+				msg(ARTIFACTS_MUST_HAVE_AT_LEAST + min + ENTR + (min==1?Y:IES));
+			} else {
+				for(ArtiDAO.Data a : list) {
+					allRequired(a);
+				}
+			}
+		}
+		return this;
+	}
+
+	public CertmanValidator artisKeys(List<ArtiDAO.Data> list, int min) {
+		if(list==null) {
+			msg(ARTIFACT_LIST_IS_NULL);
+		} else {
+			if(list.size()<min) {
+				msg(ARTIFACTS_MUST_HAVE_AT_LEAST + min + ENTR + (min==1?Y:IES));
+			} else {
+				for(ArtiDAO.Data a : list) {
+					keys(a);
+				}
+			}
+		}
+		return this;
+	}
+
+
+	public CertmanValidator keys(ArtiDAO.Data add) {
+		if(add==null) {
+			msg("Artifact is null.");
+		} else {
+			nullOrBlank(MECHID, add.mechid);
+			nullOrBlank(MACHINE, add.machine);
+		}
+		return this;
+	}
+	
+	private CertmanValidator allRequired(Data a) {
+		if(a==null) {
+			msg("Artifact is null.");
+		} else {
+			nullOrBlank(MECHID, a.mechid);
+			nullOrBlank(MACHINE, a.machine);
+			nullOrBlank("ca",a.ca);
+			nullOrBlank("dir",a.dir);
+			nullOrBlank("os_user",a.os_user);
+			// Note: AppName, Notify & Sponsor are currently not required
+		}
+		return this;
+	}
+
+}
diff --git a/auth/auth-certman/src/test/.gitignore b/auth/auth-certman/src/test/.gitignore
new file mode 100644
index 0000000..e224b1f
--- /dev/null
+++ b/auth/auth-certman/src/test/.gitignore
@@ -0,0 +1 @@
+/cmd/
diff --git a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/api/JU_API_Artifact.java b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/api/JU_API_Artifact.java
new file mode 100644
index 0000000..f50190d
--- /dev/null
+++ b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/api/JU_API_Artifact.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aaf
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * ===========================================================================
+ * * Licensed under the Apache License, Version 2.0 (the "License");
+ * * you may not use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * * 
+ *  *      http://www.apache.org/licenses/LICENSE-2.0
+ * * 
+ *  * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ * * ============LICENSE_END====================================================
+ * *
+ * *
+ ******************************************************************************/
+package org.onap.aaf.auth.cm.api;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.onap.aaf.auth.cm.AAF_CM;
+import org.onap.aaf.auth.cm.api.API_Artifact;
+import org.onap.aaf.auth.env.AuthzTrans;
+;
+
+@RunWith(MockitoJUnitRunner.class)
+public class JU_API_Artifact {
+	
+	@Mock
+	private static API_Artifact api;
+	
+	@Mock
+	private static AAF_CM certManApi;
+	
+	private static AAF_CM noMockAPI;
+	private static API_Artifact api_1;
+	
+	private static HttpServletRequest req;
+	private static HttpServletResponse res;
+	
+	@BeforeClass
+	public static void setUp() {
+		AuthzTrans trans = mock(AuthzTrans.class);
+		req = mock(HttpServletRequest.class);
+		trans.setProperty("testTag", "UserValue");
+		trans.set(req);
+	}
+	
+	@Rule
+    public ExpectedException thrown= ExpectedException.none();
+	
+	@Test
+	public void init_bothValued() {
+		try {
+			api.init(certManApi);
+		} catch (Exception e) {
+			thrown.expect(NullPointerException.class);
+			e.printStackTrace();
+		}
+	}
+	
+	@Test
+	public void init_Null_() {
+		try {
+			api.init(null);
+		} catch (Exception e) {
+			//thrown.expect(Exception.class);
+			e.printStackTrace();
+		}
+	}
+	
+	@Test
+	public void init_NMC_Null() {
+		try {
+			api_1.init(null);
+		} catch (Exception e) {
+			//thrown.expect(NullPointerException.class);
+			e.printStackTrace();
+		}
+	}
+	
+	@Test
+	public void init_NMC() {
+		try {
+			api_1.init(noMockAPI);
+		} catch (Exception e) {
+			//thrown.expect(NullPointerException.class);
+			e.printStackTrace();
+		}
+	}
+}
diff --git a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/api/JU_API_Cert.java b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/api/JU_API_Cert.java
new file mode 100644
index 0000000..dbd66e4
--- /dev/null
+++ b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/api/JU_API_Cert.java
@@ -0,0 +1,107 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aaf
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * ===========================================================================
+ * * Licensed under the Apache License, Version 2.0 (the "License");
+ * * you may not use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * * 
+ *  *      http://www.apache.org/licenses/LICENSE-2.0
+ * * 
+ *  * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ * * ============LICENSE_END====================================================
+ * *
+ * *
+ ******************************************************************************/
+package org.onap.aaf.auth.cm.api;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.onap.aaf.auth.cm.AAF_CM;
+import org.onap.aaf.auth.cm.api.API_Cert;
+import org.onap.aaf.auth.env.AuthzTrans;
+;
+
+@RunWith(MockitoJUnitRunner.class)
+public class JU_API_Cert {
+	
+	@Mock
+	private static API_Cert api;
+	
+	@Mock
+	private static AAF_CM certManApi;
+	
+	private static AAF_CM noMockAPI;
+	private static API_Cert api_1;
+	
+	private static HttpServletRequest req;
+	private static HttpServletResponse res;
+	
+	@BeforeClass
+	public static void setUp() {
+		AuthzTrans trans = mock(AuthzTrans.class);
+		req = mock(HttpServletRequest.class);
+		trans.setProperty("testTag", "UserValue");
+		trans.set(req);
+	}
+	
+	@Rule
+    public ExpectedException thrown= ExpectedException.none();
+	
+	@Test
+	public void init_bothValued() {
+		try {
+			api.init(certManApi);
+		} catch (Exception e) {
+			//thrown.expect(NullPointerException.class);
+			e.printStackTrace();
+		}
+	}
+	
+	@Test
+	public void init_Null_() {
+		try {
+			api.init(null);
+		} catch (Exception e) {
+			//thrown.expect(Exception.class);
+			e.printStackTrace();
+		}
+	}
+	
+	@Test
+	public void init_NMC_Null() {
+		try {
+			api_1.init(null);
+		} catch (Exception e) {
+			//thrown.expect(NullPointerException.class);
+			e.printStackTrace();
+		}
+	}
+	
+	@Test
+	public void init_NMC() {
+		try {
+			api_1.init(noMockAPI);
+		} catch (Exception e) {
+			//thrown.expect(NullPointerException.class);
+			e.printStackTrace();
+		}
+	}
+}
diff --git a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/ca/JU_AppCA.java b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/ca/JU_AppCA.java
new file mode 100644
index 0000000..f6d5cab
--- /dev/null
+++ b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/ca/JU_AppCA.java
@@ -0,0 +1,283 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aaf
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * ===========================================================================
+ * * Licensed under the Apache License, Version 2.0 (the "License");
+ * * you may not use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * * 
+ *  *      http://www.apache.org/licenses/LICENSE-2.0
+ * * 
+ *  * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ * * ============LICENSE_END====================================================
+ * *
+ * *
+ ******************************************************************************/
+package org.onap.aaf.auth.cm.ca;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Principal;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Set;
+
+import javax.security.auth.x500.X500Principal;
+import javax.servlet.http.HttpServletRequest;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.onap.aaf.auth.cm.ca.CA;
+import org.onap.aaf.auth.cm.cert.CSRMeta;
+import org.onap.aaf.auth.dao.cached.CachedCertDAO;
+import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.misc.env.Trans;
+
+//TODO: Gabe [JUnit] Import does not exist
+@RunWith(MockitoJUnitRunner.class)
+public class JU_AppCA {
+	
+	@Mock
+	private static CachedCertDAO certDAO;
+	
+	@Mock
+	private static HttpServletRequest req;
+	
+	@Mock
+	private static CSRMeta csrMeta;
+	
+	static Trans trans;
+	
+	static X509andChain cert1;
+	static byte [] name = {1,23,4,54,6,56};
+	
+	private static LocalCA localCA;
+	
+	@BeforeClass
+	public static void setUp() throws CertificateException, CertException, IOException {
+		String str = "core java api";
+        byte[] b = str.getBytes();
+		Principal prc = new X500Principal("CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US");
+		req = mock(HttpServletRequest.class);
+		localCA = mock(LocalCA.class);
+		X509Certificate cert = new X509Certificate() {
+			
+			@Override
+			public boolean hasUnsupportedCriticalExtension() {
+				return false;
+			}
+			
+			@Override
+			public Set<String> getNonCriticalExtensionOIDs() {
+				 
+				return null;
+			}
+			
+			@Override
+			public byte[] getExtensionValue(String oid) {
+				 
+				return null;
+			}
+			
+			@Override
+			public Set<String> getCriticalExtensionOIDs() {
+				 
+				return null;
+			}
+			
+			@Override
+			public void verify(PublicKey key, String sigProvider) throws CertificateException, NoSuchAlgorithmException,
+					InvalidKeyException, NoSuchProviderException, SignatureException {
+				 
+				
+			}
+			
+			@Override
+			public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException,
+					NoSuchProviderException, SignatureException {
+				 
+				
+			}
+			
+			@Override
+			public String toString() {
+				 
+				return null;
+			}
+			
+			@Override
+			public PublicKey getPublicKey() {
+				 
+				return null;
+			}
+			
+			@Override
+			public byte[] getEncoded() throws CertificateEncodingException {
+				 
+				return null;
+			}
+			
+			@Override
+			public int getVersion() {
+				 
+				return 0;
+			}
+			
+			@Override
+			public byte[] getTBSCertificate() throws CertificateEncodingException {
+				 
+				return null;
+			}
+			
+			@Override
+			public boolean[] getSubjectUniqueID() {
+				 
+				return null;
+			}
+			
+			@Override
+			public Principal getSubjectDN() {
+				 
+				return null;
+			}
+			
+			@Override
+			public byte[] getSignature() {
+				 
+				return null;
+			}
+			
+			@Override
+			public byte[] getSigAlgParams() {
+				 
+				return null;
+			}
+			
+			@Override
+			public String getSigAlgOID() {
+				 
+				return null;
+			}
+			
+			@Override
+			public String getSigAlgName() {
+				 
+				return null;
+			}
+			
+			@Override
+			public BigInteger getSerialNumber() {
+				 
+				return null;
+			}
+			
+			@Override
+			public Date getNotBefore() {
+				 
+				return null;
+			}
+			
+			@Override
+			public Date getNotAfter() {
+				 
+				return null;
+			}
+			
+			@Override
+			public boolean[] getKeyUsage() {
+				 
+				return null;
+			}
+			
+			@Override
+			public boolean[] getIssuerUniqueID() {
+				 
+				return null;
+			}
+			
+			@Override
+			public Principal getIssuerDN() {
+				 
+				return null;
+			}
+			
+			@Override
+			public int getBasicConstraints() {
+				 
+				return 0;
+			}
+			
+			@Override
+			public void checkValidity(Date date) throws CertificateExpiredException, CertificateNotYetValidException {
+				 
+				
+			}
+			
+			@Override
+			public void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException {
+				
+			}
+		};
+		X509andChain xac = new X509andChain(cert, new ArrayList<String>());
+		when(localCA.sign(Mockito.any(Trans.class), Mockito.any(CSRMeta.class))).thenReturn(xac);
+		certDAO = mock(CachedCertDAO.class, CALLS_REAL_METHODS);
+	}
+	
+	@Test
+	public void identity_True() throws CertificateException, IOException, CertException {
+		assertNotNull(localCA.sign(trans, csrMeta));
+	}
+	
+	
+	@Test
+	public void identityNull() throws CertificateException {
+		try {
+			assertNotNull(localCA.sign(null, csrMeta));
+		} catch (IOException e) {
+		
+			e.printStackTrace();
+		} catch (CertException e) {
+			
+			e.printStackTrace();
+		}
+	}
+	
+	@Test
+	public void identityBothNull() throws CertificateException {
+		try {
+			assertNotNull(localCA.sign(null, null));
+		} catch (IOException e) {
+		
+			e.printStackTrace();
+		} catch (CertException e) {
+			
+			e.printStackTrace();
+		}
+	}
+
+}
diff --git a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/ca/JU_DevlCA.java b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/ca/JU_DevlCA.java
new file mode 100644
index 0000000..13bf610
--- /dev/null
+++ b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/ca/JU_DevlCA.java
@@ -0,0 +1,280 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aaf
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * ===========================================================================
+ * * Licensed under the Apache License, Version 2.0 (the "License");
+ * * you may not use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * * 
+ *  *      http://www.apache.org/licenses/LICENSE-2.0
+ * * 
+ *  * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ * * ============LICENSE_END====================================================
+ * *
+ * *
+ ******************************************************************************/
+package org.onap.aaf.auth.cm.ca;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.Principal;
+import java.security.PublicKey;
+import java.security.SignatureException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateExpiredException;
+import java.security.cert.CertificateNotYetValidException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import java.util.Set;
+
+import javax.security.auth.x500.X500Principal;
+import javax.servlet.http.HttpServletRequest;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.onap.aaf.auth.cm.cert.CSRMeta;
+import org.onap.aaf.auth.dao.cached.CachedCertDAO;
+import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.misc.env.Trans;
+
+//TODO: Gabe [JUnit] Missing class
+@RunWith(MockitoJUnitRunner.class)
+public class JU_DevlCA {
+	
+	@Mock
+	private static CachedCertDAO certDAO;
+	
+	@Mock
+	private static HttpServletRequest req;
+	
+	@Mock
+	private static CSRMeta csrMeta;
+	
+	static Trans trans;
+	
+	static X509andChain cert1;
+	static byte [] name = {1,23,4,54,6,56};
+	
+	private static CA devICA;
+	
+	@BeforeClass
+	public static void setUp() throws CertificateException, CertException, IOException {
+		String str = "core java api";
+        byte[] b = str.getBytes();
+		Principal prc = new X500Principal("CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US");
+		req = mock(HttpServletRequest.class);
+		devICA = mock(CA.class);
+		X509Certificate cert = new X509Certificate() {
+			
+			@Override
+			public boolean hasUnsupportedCriticalExtension() {
+				return false;
+			}
+			
+			@Override
+			public Set<String> getNonCriticalExtensionOIDs() {
+				 
+				return null;
+			}
+			
+			@Override
+			public byte[] getExtensionValue(String oid) {
+				 
+				return null;
+			}
+			
+			@Override
+			public Set<String> getCriticalExtensionOIDs() {
+				 
+				return null;
+			}
+			
+			@Override
+			public void verify(PublicKey key, String sigProvider) throws CertificateException, NoSuchAlgorithmException,
+					InvalidKeyException, NoSuchProviderException, SignatureException {
+				 
+				
+			}
+			
+			@Override
+			public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException,
+					NoSuchProviderException, SignatureException {
+				 
+				
+			}
+			
+			@Override
+			public String toString() {
+				 
+				return null;
+			}
+			
+			@Override
+			public PublicKey getPublicKey() {
+				 
+				return null;
+			}
+			
+			@Override
+			public byte[] getEncoded() throws CertificateEncodingException {
+				 
+				return null;
+			}
+			
+			@Override
+			public int getVersion() {
+				 
+				return 0;
+			}
+			
+			@Override
+			public byte[] getTBSCertificate() throws CertificateEncodingException {
+				 
+				return null;
+			}
+			
+			@Override
+			public boolean[] getSubjectUniqueID() {
+				 
+				return null;
+			}
+			
+			@Override
+			public Principal getSubjectDN() {
+				 
+				return null;
+			}
+			
+			@Override
+			public byte[] getSignature() {
+				 
+				return null;
+			}
+			
+			@Override
+			public byte[] getSigAlgParams() {
+				 
+				return null;
+			}
+			
+			@Override
+			public String getSigAlgOID() {
+				 
+				return null;
+			}
+			
+			@Override
+			public String getSigAlgName() {
+				 
+				return null;
+			}
+			
+			@Override
+			public BigInteger getSerialNumber() {
+				 
+				return null;
+			}
+			
+			@Override
+			public Date getNotBefore() {
+				 
+				return null;
+			}
+			
+			@Override
+			public Date getNotAfter() {
+				 
+				return null;
+			}
+			
+			@Override
+			public boolean[] getKeyUsage() {
+				 
+				return null;
+			}
+			
+			@Override
+			public boolean[] getIssuerUniqueID() {
+				 
+				return null;
+			}
+			
+			@Override
+			public Principal getIssuerDN() {
+				 
+				return null;
+			}
+			
+			@Override
+			public int getBasicConstraints() {
+				 
+				return 0;
+			}
+			
+			@Override
+			public void checkValidity(Date date) throws CertificateExpiredException, CertificateNotYetValidException {
+				 
+				
+			}
+			
+			@Override
+			public void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException {
+				
+			}
+		};
+		when(devICA.sign(Mockito.any(Trans.class), Mockito.any(CSRMeta.class))).thenReturn(cert1);
+		certDAO = mock(CachedCertDAO.class, CALLS_REAL_METHODS);
+	}
+	
+	@Test
+	public void identity_True() throws CertificateException, IOException, CertException {
+		assertNotNull(devICA.sign(trans, csrMeta));
+	}
+	
+	
+	@Test
+	public void identityNull() throws CertificateException {
+		try {
+			assertNotNull(devICA.sign(null, csrMeta));
+		} catch (IOException e) {
+		
+			e.printStackTrace();
+		} catch (CertException e) {
+			
+			e.printStackTrace();
+		}
+	}
+	
+	@Test
+	public void identityBothNull() throws CertificateException {
+		try {
+			assertNotNull(devICA.sign(null, null));
+		} catch (IOException e) {
+		
+			e.printStackTrace();
+		} catch (CertException e) {
+			
+			e.printStackTrace();
+		}
+	}
+
+}
diff --git a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/cert/JU_BCFactory.java b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/cert/JU_BCFactory.java
new file mode 100644
index 0000000..856d09c
--- /dev/null
+++ b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/cert/JU_BCFactory.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aaf
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * ===========================================================================
+ * * Licensed under the Apache License, Version 2.0 (the "License");
+ * * you may not use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * * 
+ *  *      http://www.apache.org/licenses/LICENSE-2.0
+ * * 
+ *  * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ * * ============LICENSE_END====================================================
+ * *
+ * *
+ ******************************************************************************/
+package org.onap.aaf.auth.cm.cert;
+
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.pkcs.PKCS10CertificationRequest;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.env.Trans;
+
+@RunWith(MockitoJUnitRunner.class)
+public class JU_BCFactory {
+	
+	private static BCFactory bcFactory = new BCFactory();
+	
+	private static BCFactory bcFact;
+	
+	private static PrivateKey pk;
+	
+	
+	private static Trans trans;
+	
+	
+	private static PKCS10CertificationRequest req;
+	
+	@BeforeClass
+	public static void setUp() throws IOException {
+		pk = new XYZKey();
+		trans = mock(Trans.class);
+		req = mock(PKCS10CertificationRequest.class);
+		when(req.getEncoded()).thenReturn(new byte[1]);
+		when(trans.start(Mockito.anyString(), Mockito.anyInt())).thenReturn(new TimeTaken(null, 0) {
+			
+			@Override
+			public void output(StringBuilder sb) {
+				// TODO Auto-generated method stub
+				
+			}
+		});
+		bcFact = mock(BCFactory.class);
+	}
+	
+	@Test
+	public void toStrin() throws OperatorCreationException, IOException, CertException {
+		assertNotNull(bcFactory.toString(req));
+	}
+	
+	@Test
+	public void toStrinMoc() throws OperatorCreationException, IOException, CertException {
+		assertNotNull(bcFact.toString(req));
+	}
+	
+	@Rule
+    public ExpectedException thrown= ExpectedException.none();
+	
+	@Test
+	public void toCSR()  {
+		try {
+			assertNotNull(bcFactory.toCSR(trans, new File("/random/path")));
+			thrown.expect(FileNotFoundException.class);
+		} catch (IOException e) {
+			
+			e.printStackTrace();
+		}
+	}
+	
+}
+
+class XYZKey implements Key, PublicKey, PrivateKey {
+	
+	int rotValue;
+	public XYZKey() {
+		rotValue = 1200213;
+	}
+	public String getAlgorithm() {
+		return "XYZ";
+	}
+
+	public String getFormat() {
+		return "XYZ Special Format";
+	}
+
+	public byte[] getEncoded() {
+		byte b[] = new byte[4];
+		b[3] = (byte) ((rotValue << 24) & 0xff);
+		b[2] = (byte) ((rotValue << 16) & 0xff);
+		b[1] = (byte) ((rotValue << 8) & 0xff);
+		b[0] = (byte) ((rotValue << 0) & 0xff);
+		return b;
+	}
+}
diff --git a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/cert/JU_CSRMeta.java b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/cert/JU_CSRMeta.java
new file mode 100644
index 0000000..acf028c
--- /dev/null
+++ b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/cert/JU_CSRMeta.java
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aaf
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * ===========================================================================
+ * * Licensed under the Apache License, Version 2.0 (the "License");
+ * * you may not use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * * 
+ *  *      http://www.apache.org/licenses/LICENSE-2.0
+ * * 
+ *  * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ * * ============LICENSE_END====================================================
+ * *
+ * *
+ ******************************************************************************/
+package org.onap.aaf.auth.cm.cert;
+
+import static org.mockito.Mockito.mock;
+
+import java.util.List;
+
+import org.bouncycastle.pkcs.PKCS10CertificationRequest;
+import org.junit.BeforeClass;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.runner.RunWith;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.misc.env.Trans;
+
+import junit.framework.Assert;
+
+@RunWith(MockitoJUnitRunner.class)
+public class JU_CSRMeta {
+	
+	private static CSRMeta csrmeta;
+	private static Trans trans;
+	private static PKCS10CertificationRequest req;
+	
+	@BeforeClass
+	public static void setUp() throws CertException {
+		trans = mock(Trans.class);
+		List<RDN> lrdn = RDN.parse('/',"o=ATT Services, Inc/l=St Louis/st=Missouri/c=US");
+		
+		csrmeta = new CSRMeta(lrdn);
+	}
+	
+//	@Test
+//	public void x500Name() throws IOException {
+//		
+//		X500Name x500 = csrmeta.x500Name();
+//		assertEquals(x500.toString(),"CN=CN,E=pupleti@ht.com,OU=HAKJH787,O=O,L=L,ST=ST,C=C");
+//	}
+//	
+//	@Test
+//	public void initialConversationCert() throws CertificateException, OperatorCreationException, IOException {
+//		X509Certificate cert = csrmeta.initialConversationCert(trans);
+//		assertEquals(cert.getBasicConstraints(),-1);
+//	}
+//	
+//	@Test
+//	public void generateCSR() throws IOException, CertException {
+//		req = csrmeta.generateCSR(trans);
+//		assertNotNull(req);
+//	}
+	
+	@Rule
+    public ExpectedException thrown= ExpectedException.none();
+	
+//	@Test
+//	public void dump() throws IOException, CertException {
+//		req = csrmeta.generateCSR(trans);
+//		csrmeta.dump(req);
+//	}
+	
+	@Test						//TODO: Temporary fix AAF-111
+	public void netYetTested() {
+		Assert.fail("Tests not yet implemented");
+	}
+	
+}
diff --git a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/data/JU_CertReq.java b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/data/JU_CertReq.java
new file mode 100644
index 0000000..f54e36e
--- /dev/null
+++ b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/data/JU_CertReq.java
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aaf
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * ===========================================================================
+ * * Licensed under the Apache License, Version 2.0 (the "License");
+ * * you may not use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * * 
+ *  *      http://www.apache.org/licenses/LICENSE-2.0
+ * * 
+ *  * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ * * ============LICENSE_END====================================================
+ * *
+ * *
+ ******************************************************************************/
+package org.onap.aaf.auth.cm.data;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.onap.aaf.auth.cm.ca.CA;
+import org.onap.aaf.auth.cm.ca.X509andChain;
+import org.onap.aaf.auth.cm.cert.BCFactory;
+import org.onap.aaf.auth.cm.cert.CSRMeta;
+import org.onap.aaf.auth.cm.data.CertReq;
+import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.misc.env.Trans;
+
+@RunWith(MockitoJUnitRunner.class)
+public class JU_CertReq {
+	
+	private static BCFactory bcFact;
+	
+	private static CSRMeta value;
+	
+	private static CertReq req;
+	
+	@BeforeClass
+	public static void setUp() {
+		bcFact = mock(BCFactory.class);
+		value = mock(CSRMeta.class);
+		req = mock(CertReq.class);
+		
+	}
+	
+//	@Test
+//	public void getCSRMeta() throws CertException, IOException {
+//		//req = new CertReq();
+//		req.mechid = "1213";
+//		List<String> fqdnsas = new ArrayList<String>();
+//		fqdnsas.add("String1");
+//		List<String> emails = new ArrayList<String>();
+//		emails.add("pupleti@hotmail.com");
+//		req.emails = emails;
+//		req.fqdns = fqdnsas;
+//		req.certAuthority = new CA(null, "testName", "ALL") {
+//			//TODO: Gabe [JUnit] REREVIEW
+//			@Override
+//			public X509andChain sign(Trans trans, CSRMeta csrmeta) throws IOException, CertException {
+//	
+//				return null;
+//			}
+//		};
+//		req.sponsor = "asa@df.co";
+//		assertNull(req.getCSRMeta());
+//	}
+	
+	@Test						//TODO: Temporary fix AAF-111
+	public void netYetTested() {
+		fail("Tests not yet implemented");
+	}
+}
diff --git a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/facade/JU_FacadeImpl.java b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/facade/JU_FacadeImpl.java
new file mode 100644
index 0000000..dbfaaee
--- /dev/null
+++ b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/facade/JU_FacadeImpl.java
@@ -0,0 +1,193 @@
+/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aaf
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * ===========================================================================
+ * * Licensed under the Apache License, Version 2.0 (the "License");
+ * * you may not use this file except in compliance with the License.
+ * * You may obtain a copy of the License at
+ * * 
+ *  *      http://www.apache.org/licenses/LICENSE-2.0
+ * * 
+ *  * Unless required by applicable law or agreed to in writing, software
+ * * distributed under the License is distributed on an "AS IS" BASIS,
+ * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * * See the License for the specific language governing permissions and
+ * * limitations under the License.
+ * * ============LICENSE_END====================================================
+ * *
+ * *
+ ******************************************************************************/
+package org.onap.aaf.auth.cm.facade;
+
+import static org.junit.Assert.*;
+import static org.mockito.Mockito.CALLS_REAL_METHODS;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.io.IOException;
+
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.namespace.QName;
+import javax.xml.validation.Schema;
+
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+import org.mockito.runners.MockitoJUnitRunner;
+import org.onap.aaf.auth.cm.AAF_CM;
+import org.onap.aaf.auth.cm.facade.FacadeImpl;
+import org.onap.aaf.auth.cm.mapper.Mapper;
+import org.onap.aaf.auth.cm.service.CMService;
+import org.onap.aaf.auth.env.AuthzEnv;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.auth.layer.Result;
+import org.onap.aaf.cadi.aaf.AAFPermission;
+import org.onap.aaf.cadi.aaf.v2_0.AAFLurPerm;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Data;
+import org.onap.aaf.misc.env.LogTarget;
+import org.onap.aaf.misc.env.TimeTaken;
+import org.onap.aaf.misc.env.Trans;
+import org.onap.aaf.misc.rosetta.env.RosettaDF;
+import org.onap.aaf.misc.rosetta.env.RosettaData;
+
+
+@RunWith(MockitoJUnitRunner.class)
+public class JU_FacadeImpl<REQ,CERT,ARTIFACTS,ERROR> {
+	
+	private static AuthzTrans trans;
+	private static HttpServletResponse resp;
+	private static AAF_CM certman;
+	private static FacadeImpl hImpl;
+	private static CMService service;
+	private Mapper<REQ,CERT,ARTIFACTS,ERROR> mapper;
+	private Data.TYPE dataType;
+	private static AuthzEnv env;
+	
+	private static FacadeImpl fImpl;
+	private static HttpServletRequest req;
+	
+	@Before
+	public void setUp() throws APIException, IOException {
+		fImpl = mock(FacadeImpl.class);
+		env = mock(AuthzEnv.class);
+		resp = mock(HttpServletResponse.class);
+		req = mock(HttpServletRequest.class);
+		hImpl = mock(FacadeImpl.class, CALLS_REAL_METHODS);
+		Result<Void> rvd = (Result) mock(Result.class);
+		trans = mock(AuthzTrans.class);
+		when(trans.error()).thenReturn(new LogTarget() {
+			
+			@Override
+			public void printf(String fmt, Object... vars) {}
+			
+			@Override
+			public void log(Throwable e, Object... msgs) {
+				e.getMessage();
+				e.printStackTrace();
+				msgs.toString();
+				
+			}
+			
+			@Override
+			public void log(Object... msgs) {
+			}
+			
+			@Override
+			public boolean isLoggable() {
+				
+				return false;
+			}
+		});
+		when(trans.start(Mockito.anyString(), Mockito.anyInt())).thenReturn(new TimeTaken("Now", 1) {
+			
+			@Override
+			public void output(StringBuilder sb) {
+				
+			}
+		});
+		when(fImpl.check(Mockito.any(AuthzTrans.class), Mockito.any(HttpServletResponse.class), Mockito.anyString())).thenReturn(rvd);
+		when(resp.getOutputStream()).thenReturn(new ServletOutputStream() {
+			
+			@Override
+			public void write(int b) throws IOException {
+				
+				
+			}
+		});
+		
+	}
+	
+	@Test
+	public void check() throws IOException {
+		AAFPermission ap = new AAFPermission("str1","str3","str2");
+		String perms = ap.getInstance();
+		assertNotNull(hImpl.check(trans, resp, perms));
+	}
+	
+	@Test
+	public void checkNull() throws IOException {
+		AAFPermission ap = new AAFPermission(null,"Str3","str2");
+		String perms = ap.getInstance();
+		assertNotNull(hImpl.check(trans, resp, perms));
+	}
+	
+	@Test
+	public void checkTwoNull() throws IOException {
+		AAFPermission ap = new AAFPermission(null,null,"str2");
+		String perms = ap.getInstance();
+		assertNotNull(fImpl.check(trans, resp, perms));
+	}
+	
+	@Test
+	public void checkAllNull() throws IOException {
+		AAFPermission ap = new AAFPermission(null,null,null);
+		String perms = ap.getInstance();
+		assertNotNull(fImpl.check(trans, resp, perms));
+	}
+	
+	@Test
+	public void checkTrans_null() throws IOException {
+		AAFPermission ap = new AAFPermission("str1","str3","str2");
+		String perms = ap.getInstance();
+		assertNotNull(hImpl.check(null, resp, perms));
+	}
+	
+	@Test
+	public void checkRespNull() throws IOException {
+		AAFPermission ap = new AAFPermission("str1","str3","str2");
+		String perms = ap.getInstance();
+		assertNotNull(hImpl.check(trans, null, perms));
+	}
+	
+	@Test
+	public void requestCert() {		
+		assertNotNull(hImpl.requestCert(trans, req, resp, null));
+	}
+	
+	@Test
+	public void renewCert() {		
+		assertNotNull(hImpl.renewCert(trans, req, resp, true));
+	}
+	
+	@Test
+	public void dropCert() {		
+		assertNotNull(hImpl.renewCert(trans, req, resp, true));
+	}
+	
+	@Test
+	public void createArtifacts() {		
+		assertNotNull(hImpl.createArtifacts(trans, req, resp));
+	}
+	
+	@Test
+	public void readArtifacts() {		
+		assertNotNull(hImpl.readArtifacts(trans, req, resp));
+	}
+}
diff --git a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/test/CertmanTest.java b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/test/CertmanTest.java
new file mode 100644
index 0000000..3faa5bb
--- /dev/null
+++ b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/test/CertmanTest.java
@@ -0,0 +1,170 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+package org.onap.aaf.auth.cm.test;
+
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.InetAddress;
+import java.net.URI;
+import java.security.cert.CertificateException;
+
+import javax.security.auth.x500.X500Principal;
+
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import static org.junit.Assert.*;
+import org.onap.aaf.auth.env.AuthzEnv;
+import org.onap.aaf.cadi.CadiException;
+import org.onap.aaf.cadi.Locator;
+import org.onap.aaf.cadi.Locator.Item;
+import org.onap.aaf.cadi.client.Future;
+import org.onap.aaf.cadi.client.Rcli;
+import org.onap.aaf.cadi.client.Retryable;
+import org.onap.aaf.cadi.cm.Factory;
+import org.onap.aaf.cadi.config.SecurityInfoC;
+import org.onap.aaf.cadi.http.HBasicAuthSS;
+import org.onap.aaf.cadi.http.HMangr;
+import org.onap.aaf.cadi.locator.DNSLocator;
+import org.onap.aaf.misc.env.APIException;
+import org.onap.aaf.misc.env.Data;
+import org.onap.aaf.misc.env.Data.TYPE;
+import org.onap.aaf.misc.env.util.Chrono;
+import org.onap.aaf.misc.rosetta.env.RosettaDF;
+
+import certman.v1_0.CertInfo;
+import certman.v1_0.CertificateRequest;
+import junit.framework.Assert;
+
+public class CertmanTest {
+
+	private static HMangr hman;
+	private static AuthzEnv env;
+	private static HBasicAuthSS ss;
+	private static RosettaDF<CertificateRequest> reqDF;
+	private static RosettaDF<CertInfo> certDF;
+
+	@BeforeClass
+	public static void setUpBeforeClass() throws Exception {
+		env = new AuthzEnv();
+//		InputStream ris = env.classLoader().getResource("certman.props").openStream();
+//		try {
+//			env.load(ris);
+//		} finally {
+//			ris.close();
+//		}
+//
+//		Locator<URI> loc = new DNSLocator(env, "https", "aaf.it.att.com", "8150");
+//		for(Item item = loc.first(); item!=null; item=loc.next(item)) {
+//			System.out.println(loc.get(item));
+//		}
+//		
+//		
+//		SecurityInfoC<HttpURLConnection> si = SecurityInfoC.instance(env, HttpURLConnection.class);
+//		ss = new HBasicAuthSS(si,"m12345@aaf.att.com", 
+//				env.decrypt("enc:gvptdJyo0iKdVZw2rzMb0woxa7YKMdqLuhfQ4OQfZ8k",false));
+//				env.decrypt("enc:jFfAnO3mOKb9Gzm2OFysslmXpbnyuAxuoNJK",false), si);
+//					SecuritySetter<HttpURLConnection> ss = new X509SS(si, "aaf");
+		
+//		hman = new HMangr(env,loc);
+//
+//		reqDF = env.newDataFactory(CertificateRequest.class);
+//		reqDF.out(TYPE.JSON);
+//		certDF = env.newDataFactory(CertInfo.class);
+	}
+
+//	@AfterClass
+//	public static void tearDownAfterClass() throws Exception {
+//		hman.close();
+//	}
+
+	@Before
+	public void setUp() throws Exception {
+
+	}
+
+	@After
+	public void tearDown() throws Exception {
+	}
+
+//	@Test
+//	public void testX500Name() throws Exception {
+//		
+//		for( InetAddress ia : InetAddress.getAllByName("aaf.dev.att.com")) {
+//			System.out.printf("%s - %s\n", ia.getHostName(), ia.getHostAddress());
+//			InetAddress ia1 = InetAddress.getByName(ia.getHostAddress());
+//			System.out.printf("%s - %s\n", ia1.getHostName(), ia1.getHostAddress());
+//		}
+//		
+//		hman.best(ss, new Retryable<Void>() {
+//			@Override
+//			public Void code(Rcli<?> client) throws APIException, CadiException {
+//				CertificateRequest cr = new CertificateRequest();
+//				cr.setMechid("m12345@aaf.att.com");
+//				cr.setSponsor("jg1555");
+//				cr.getFqdns().add("mithrilcsp.sbc.com");
+//				cr.getFqdns().add("zld01907.vci.att.com");
+//				cr.getFqdns().add("aaftest.test.att.com");
+//				
+//				String path = "/cert/local"; // Local Test
+////				String path = "/cert/aaf"; // Official CA
+//				long end=0,start = System.nanoTime();
+//				try {
+//					System.out.println(reqDF.newData().option(Data.PRETTY).load(cr).asString());
+//					Future<String> f = client.updateRespondString(path, reqDF, cr);
+//					if(f.get(10000)) {
+//						end = System.nanoTime();
+//						System.out.println(f.body());
+//						CertInfo capi = certDF.newData().in(Data.TYPE.JSON).load(f.body()).asObject();
+//						for(String c :capi.getCerts()) {
+//							for( java.security.cert.Certificate x509 : Factory.toX509Certificate(c)) {
+//								System.out.println(x509.toString());
+//							}
+//						}
+//					} else {
+//						end = System.nanoTime();
+//						String msg = "Client returned " + f.code() + ": " + f.body();
+//						System.out.println(msg);
+//						Assert.fail(msg);
+//					}
+//				} catch (CertificateException e) {
+//					throw new CadiException(e);
+//				} finally {
+//					System.out.println(Chrono.millisFromNanos(start,end) + " ms");
+//				}
+//				return null;
+//			}
+//		});
+//		
+//		
+//	}
+//
+//	public X500Principal ephemeral() {
+//		return null;
+//	}
+	
+	@Test						//TODO: Temporary fix AAF-111
+	public void netYetTested() {
+		fail("Tests not yet implemented");
+	}
+}
diff --git a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/test/JU_KeyMarshaling.java b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/test/JU_KeyMarshaling.java
new file mode 100644
index 0000000..7b69d28
--- /dev/null
+++ b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/test/JU_KeyMarshaling.java
@@ -0,0 +1,80 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cm.test;
+
+import java.io.IOException;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+import org.junit.AfterClass;
+import org.junit.Test;
+import org.onap.aaf.auth.env.AuthzEnv;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.cadi.cm.CertException;
+import org.onap.aaf.cadi.cm.Factory;
+
+import junit.framework.Assert;
+
+public class JU_KeyMarshaling {
+
+	@AfterClass
+	public static void tearDownAfterClass() throws Exception {
+	}
+
+	@Test
+	public void test() {
+		AuthzEnv env = new AuthzEnv();
+		AuthzTrans trans = env.newTrans();
+		try {
+			KeyPair kpair = Factory.generateKeyPair(trans);
+			String privateString = Factory.toString(trans, kpair.getPrivate());
+			System.out.println("Private as base64 encoded as PKCS8 Spec");
+			System.out.println(privateString);
+			
+			// Take String, and create Private Key
+			PrivateKey pk = Factory.toPrivateKey(trans, privateString);
+			Assert.assertEquals(kpair.getPrivate().getAlgorithm(), pk.getAlgorithm());
+			Assert.assertEquals(kpair.getPrivate().getFormat(), pk.getFormat());
+			Assert.assertEquals(kpair.getPrivate().getEncoded(), pk.getEncoded());
+		
+			
+			String s = Factory.toString(trans, kpair.getPublic());
+			System.out.println("Public as base64 encoded x509 Spec");
+			System.out.println(s);
+			
+			PublicKey pub = Factory.toPublicKey(trans, s);
+			Assert.assertEquals(kpair.getPublic().toString(), pub.toString());
+			
+			
+		} catch (IOException e) {
+			e.printStackTrace();
+		} catch (CertException e) {
+			e.printStackTrace();
+		} finally {
+			StringBuilder sb = new StringBuilder("=== Timings ===\n");
+			trans.auditTrail(1, sb);
+			System.out.println(sb);
+		}
+	}
+
+}
diff --git a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/test/JU_SignTest.java b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/test/JU_SignTest.java
new file mode 100644
index 0000000..93013d3
--- /dev/null
+++ b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/test/JU_SignTest.java
@@ -0,0 +1,109 @@
+/**
+ * ============LICENSE_START====================================================
+ * org.onap.aaf
+ * ===========================================================================
+ * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
+ * ===========================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ * ============LICENSE_END====================================================
+ *
+ */
+
+package org.onap.aaf.auth.cm.test;
+
+import java.io.File;
+import java.math.BigInteger;
+import java.security.KeyPair;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.util.Collection;
+
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Test;
+import static org.junit.Assert.fail;
+import org.onap.aaf.auth.env.AuthzEnv;
+import org.onap.aaf.auth.env.AuthzTrans;
+import org.onap.aaf.cadi.cm.Factory;
+
+public class JU_SignTest {
+
+	@AfterClass
+	public static void tearDownAfterClass() throws Exception {
+	}
+
+	@Test
+	public void test() throws Exception {
+		AuthzEnv env = new AuthzEnv();
+		AuthzTrans trans = env.newTrans();
+		KeyPair kpair = Factory.generateKeyPair(trans);
+		PrivateKey privateKey = kpair.getPrivate();
+		String privateString = Factory.toString(trans, privateKey);
+		System.out.println("Private as base64 encoded as PKCS8 Spec");
+		System.out.println(privateString);
+		
+		PublicKey publicKey = kpair.getPublic();
+		String publicString = Factory.toString(trans, publicKey); 
+		System.out.println("public as base64 encoded as PKCS8 Spec");
+		System.out.println(publicString);
+		
+		byte data[] = "Sign this please.".getBytes();
+		byte sig[] = Factory.sign(trans, data, privateKey);
+		System.out.println("Signature");
+		System.out.println(Factory.toSignatureString(sig));
+		
+		Assert.assertTrue(Factory.verify(trans, data, sig, publicKey));
+	}
+	
+//	@Test
+//	public void test2() throws Exception {
+//		AuthzEnv env = new AuthzEnv();
+//		AuthzTrans trans = env.newTrans();
+//		File key = new File("/opt/app/aaf/common/com.att.aaf.key");
+//		PrivateKey privKey = Factory.toPrivateKey(trans, key);
+//		RSAPrivateKey rPrivKey = (RSAPrivateKey)privKey;
+//		BigInteger privMod, pubMod;
+//		System.out.println((privMod = rPrivKey.getModulus()).toString(16));
+//		
+//		byte data[] = "Sign this please.".getBytes();
+//		byte sig[] = Factory.sign(trans, data, privKey);
+//		System.out.println("Signature");
+//		System.out.println(Factory.toSignatureString(sig));
+//
+//		
+//		File crt = new File("/opt/app/aaf/common/com.att.aaf.crt");
+//		Collection<? extends Certificate> x509s = Factory.toX509Certificate(trans, crt);
+//		X509Certificate cert = null;
+//		for(Certificate c : x509s) {
+//			cert = (X509Certificate)c;
+//			break;
+//		}
+//		PublicKey pubKey = cert.getPublicKey();
+//		RSAPublicKey rPubKey = (RSAPublicKey)pubKey;
+//	
+//		System.out.println((pubMod = rPubKey.getModulus()).toString(16));
+//
+//		Assert.assertTrue(Factory.verify(trans, data, sig, pubKey));
+//		Assert.assertEquals(privMod,pubMod);
+//		
+//	}
+
+	@Test						//TODO: Temporary fix AAF-111
+	public void netYetTested() {
+		fail("Tests not yet implemented");
+	}
+}