diff options
author | sg481n <sg481n@att.com> | 2017-08-03 17:27:34 -0400 |
---|---|---|
committer | sg481n <sg481n@att.com> | 2017-08-03 17:27:34 -0400 |
commit | 43854a9e3310ff7a92257d16c4fc0a8321eaec68 (patch) | |
tree | 46af936c5da4f9c60d7d63dade5c61a8fd5ef9f4 /authz-certman/src/main | |
parent | f691a8b8dfc9eea4c6b3bfa45ea60f07ad347e69 (diff) |
 [AAF-21] Initial code import
Change-Id: I63d7d499bbd46f500b5f5a4db966166f613f327a
Signed-off-by: sg481n <sg481n@att.com>
Diffstat (limited to 'authz-certman/src/main')
25 files changed, 3844 insertions, 0 deletions
diff --git a/authz-certman/src/main/config/certman.props b/authz-certman/src/main/config/certman.props new file mode 100644 index 00000000..496d8c37 --- /dev/null +++ b/authz-certman/src/main/config/certman.props @@ -0,0 +1,25 @@ +## +## 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_ + +# Turn on both AAF TAF & LUR 2.0 +aaf_url=https://DME2RESOLVE/service=com.att.authz.AuthorizationService/version=_MAJOR_VER_._MINOR_VER_/envContext=_ENV_CONTEXT_/routeOffer=_ROUTE_OFFER_ + + + diff --git a/authz-certman/src/main/config/log4j.properties b/authz-certman/src/main/config/log4j.properties new file mode 100644 index 00000000..ad853f54 --- /dev/null +++ b/authz-certman/src/main/config/log4j.properties @@ -0,0 +1,79 @@ +#-------------------------------------------------------------------------------
+# ============LICENSE_START====================================================
+# * org.onap.aai
+# * ===========================================================================
+# * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+# * Copyright © 2017 Amdocs
+# * ===========================================================================
+# * 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====================================================
+# *
+# * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+# *
+#-------------------------------------------------------------------------------
+###############################################################################
+# Copyright (c) 2016 AT&T Intellectual Property. All rights reserved.
+###############################################################################
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+#
+log4j.appender.INIT=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.INIT.File=_LOG_DIR_/${LOG4J_FILENAME_init}
+log4j.appender.INIT.DatePattern='.'yyyy-MM-dd
+#log4j.appender.INIT.MaxFileSize=_MAX_LOG_FILE_SIZE_
+#log4j.appender.INIT.MaxBackupIndex=_MAX_LOG_FILE_BACKUP_COUNT_
+log4j.appender.INIT.layout=org.apache.log4j.PatternLayout
+log4j.appender.INIT.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSSZ} %m %n
+
+
+log4j.appender.CM=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.CM.File=_LOG_DIR_/${LOG4J_FILENAME_cm}
+log4j.appender.CM.DatePattern='.'yyyy-MM-dd
+#log4j.appender.CM.MaxFileSize=_MAX_LOG_FILE_SIZE_
+#log4j.appender.CM.MaxBackupIndex=_MAX_LOG_FILE_BACKUP_COUNT_
+log4j.appender.CM.layout=org.apache.log4j.PatternLayout
+log4j.appender.CM.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSSZ} %p [%c] %m %n
+
+log4j.appender.AUDIT=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.AUDIT.File=_LOG_DIR_/${LOG4J_FILENAME_audit}
+log4j.appender.AUDIT.DatePattern='.'yyyy-MM-dd
+#log4j.appender.AUDIT.MaxFileSize=_MAX_LOG_FILE_SIZE_
+#log4j.appender.AUDIT.MaxBackupIndex=_MAX_LOG_FILE_BACKUP_COUNT_
+log4j.appender.AUDIT.layout=org.apache.log4j.PatternLayout
+log4j.appender.AUDIT.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSSZ} %m %n
+
+
+# General Apache libraries
+log4j.rootLogger=INFO,CM
+log4j.logger.org.apache=WARN,INIT
+log4j.logger.dme2=WARN,INIT
+log4j.logger.init=INFO,INIT
+log4j.logger.authz=_LOG4J_LEVEL_,CM
+log4j.logger.audit=INFO,AUDIT
+log4j.category.org.jscep=INFO
+
diff --git a/authz-certman/src/main/config/lrm-authz-certman.xml b/authz-certman/src/main/config/lrm-authz-certman.xml new file mode 100644 index 00000000..689c2db3 --- /dev/null +++ b/authz-certman/src/main/config/lrm-authz-certman.xml @@ -0,0 +1,83 @@ +<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<!--
+ ============LICENSE_START====================================================
+ * org.onap.aai
+ * ===========================================================================
+ * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * Copyright © 2017 Amdocs
+ * ===========================================================================
+ * 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====================================================
+ *
+ * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ *
+-->
+<ns2:ManagedResourceList xmlns:ns2="http://scld.att.com/lrm/util" xmlns="http://scld.att.com/lrm/commontypes" xmlns:ns3="http://scld.att.com/lrm/types">
+ <ns2:ManagedResource>
+ <ResourceDescriptor>
+ <ResourceName>com.att.authz._ARTIFACT_ID_</ResourceName>
+ <ResourceVersion>
+ <Major>_MAJOR_VER_</Major>
+ <Minor>_MINOR_VER_</Minor>
+ <Patch>_PATCH_VER_</Patch>
+ </ResourceVersion>
+ <RouteOffer>_ROUTE_OFFER_</RouteOffer>
+ </ResourceDescriptor>
+ <ResourceType>Java</ResourceType>
+ <ResourcePath>com.att.authz.cm.service.CertManAPI</ResourcePath>
+ <ResourceProps>
+ <Tag>process.workdir</Tag>
+ <Value>_ROOT_DIR_</Value>
+ </ResourceProps>
+ <ResourceProps>
+ <Tag>jvm.version</Tag>
+ <Value>1.8</Value>
+ </ResourceProps>
+ <ResourceProps>
+ <Tag>jvm.args</Tag>
+ <Value>-DAFT_LATITUDE=_AFT_LATITUDE_ -DAFT_LONGITUDE=_AFT_LONGITUDE_ -DAFT_ENVIRONMENT=_AFT_ENVIRONMENT_ -Dplatform=_SCLD_PLATFORM_ -Dcom.sun.jndi.ldap.connect.pool.maxsize=20 -Dcom.sun.jndi.ldap.connect.pool.prefsize=10 -Dcom.sun.jndi.ldap.connect.pool.timeout=3000 </Value>
+ </ResourceProps>
+ <ResourceProps>
+ <Tag>jvm.classpath</Tag>
+ <Value>_ROOT_DIR_/etc:_ROOT_DIR_/lib/*:</Value>
+ </ResourceProps>
+ <ResourceProps>
+ <Tag>jvm.heap.min</Tag>
+ <Value>1024m</Value>
+ </ResourceProps>
+ <ResourceProps>
+ <Tag>jvm.heap.max</Tag>
+ <Value>2048m</Value>
+ </ResourceProps>
+ <ResourceProps>
+ <Tag>start.class</Tag>
+ <Value>com.att.authz.cm.service.CertManAPI</Value>
+ </ResourceProps>
+ <ResourceProps>
+ <Tag>stdout.redirect</Tag>
+ <Value>_ROOT_DIR_/logs/SystemOut.log</Value>
+ </ResourceProps>
+ <ResourceProps>
+ <Tag>stderr.redirect</Tag>
+ <Value>_ROOT_DIR_/logs/SystemErr.log</Value>
+ </ResourceProps>
+ <ResourceOSID>aft</ResourceOSID>
+ <ResourceStartType>AUTO</ResourceStartType>
+ <ResourceStartPriority>2</ResourceStartPriority>
+ <ResourceMinCount>_RESOURCE_MIN_COUNT_</ResourceMinCount>
+ <ResourceMaxCount>_RESOURCE_MAX_COUNT_</ResourceMaxCount>
+ <ResourceRegistration>_RESOURCE_REGISTRATION_</ResourceRegistration>
+ <ResourceSWMComponent>com.att.authz:_ARTIFACT_ID_</ResourceSWMComponent>
+ <ResourceSWMComponentVersion>_ARTIFACT_VERSION_</ResourceSWMComponentVersion>
+ </ns2:ManagedResource>
+</ns2:ManagedResourceList>
diff --git a/authz-certman/src/main/java/com/att/authz/cm/api/API_Artifact.java b/authz-certman/src/main/java/com/att/authz/cm/api/API_Artifact.java new file mode 100644 index 00000000..be417515 --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/api/API_Artifact.java @@ -0,0 +1,130 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.api;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.att.aft.dme2.internal.jetty.http.HttpStatus;
+import com.att.authz.cm.mapper.Mapper.API;
+import com.att.authz.cm.service.CertManAPI;
+import com.att.authz.cm.service.Code;
+import com.att.authz.env.AuthzTrans;
+import com.att.authz.layer.Result;
+import com.att.cssa.rserv.HttpMethods;
+
+/**
+ * API Deployment Artifact Apis.. using Redirect for mechanism
+ *
+ *
+ */
+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 CertManAPI 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);
+ }
+ }
+ });
+
+ 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.CREATED_201);
+ } else {
+ context.error(trans,resp,r);
+ }
+ }
+ });
+
+ 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.CREATED_201);
+ } 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/authz-certman/src/main/java/com/att/authz/cm/api/API_Cert.java b/authz-certman/src/main/java/com/att/authz/cm/api/API_Cert.java new file mode 100644 index 00000000..3a7bbe16 --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/api/API_Cert.java @@ -0,0 +1,100 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.api;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.att.aft.dme2.internal.jetty.http.HttpStatus;
+import com.att.authz.cm.ca.CA;
+import com.att.authz.cm.mapper.Mapper.API;
+import com.att.authz.cm.service.CertManAPI;
+import com.att.authz.cm.service.Code;
+import com.att.authz.env.AuthzTrans;
+import com.att.authz.layer.Result;
+import com.att.cssa.rserv.HttpMethods;
+import com.att.inno.env.Slot;
+import com.att.inno.env.TransStore;
+
+/**
+ * API Apis.. using Redirect for mechanism
+ *
+ *
+ */
+public class API_Cert {
+ public static final String CERT_AUTH = "CertAuthority";
+ private static Slot sCertAuth;
+
+ /**
+ * Normal Init level APIs
+ *
+ * @param cmAPI
+ * @param facade
+ * @throws Exception
+ */
+ public static void init(final CertManAPI cmAPI) throws Exception {
+ // Check for Created Certificate Authorities in TRANS
+ sCertAuth = ((TransStore) cmAPI.env).slot(CERT_AUTH);
+
+ ////////
+ // Overall APIs
+ ///////
+ cmAPI.route(HttpMethods.PUT,"/cert/:ca",API.CERT_REQ,new Code(cmAPI,"Request Certificate") {
+ @Override
+ public void handle(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) throws Exception {
+ String key = pathParam(req, ":ca");
+ CA ca;
+ if((ca = cmAPI.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, req.getParameter("withTrust")!=null);
+ if(r.isOK()) {
+ resp.setStatus(HttpStatus.OK_200);
+ } else {
+ context.error(trans,resp,r);
+ }
+ }
+ }
+ });
+
+ /**
+ *
+ */
+ cmAPI.route(HttpMethods.GET, "/cert/may/:perm", API.VOID, new Code(cmAPI,"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()));
+ }
+ }
+ });
+
+ }
+}
diff --git a/authz-certman/src/main/java/com/att/authz/cm/ca/AppCA.java b/authz-certman/src/main/java/com/att/authz/cm/ca/AppCA.java new file mode 100644 index 00000000..761867d7 --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/ca/AppCA.java @@ -0,0 +1,357 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.ca;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.Authenticator;
+import java.net.MalformedURLException;
+import java.net.PasswordAuthentication;
+import java.net.URL;
+import java.security.cert.CertStore;
+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.Collection;
+import java.util.Date;
+import java.util.Iterator;
+import java.util.List;
+
+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 com.att.authz.cm.cert.BCFactory;
+import com.att.authz.cm.cert.CSRMeta;
+import com.att.authz.cm.cert.StandardFields;
+import com.att.authz.common.Define;
+import com.att.cadi.cm.CertException;
+import com.att.cadi.cm.Factory;
+import com.att.cadi.config.Config;
+import com.att.cadi.routing.GreatCircle;
+import com.att.inno.env.Env;
+import com.att.inno.env.TimeTaken;
+import com.att.inno.env.Trans;
+import com.att.inno.env.util.Split;
+
+public class AppCA extends CA {
+ public static final String CA_PERM_TYPE = Define.ROOT_NS+".ca"; // Permission Type for validation
+ private static final String AAF_DATA_DIR = "aaf_data_dir";
+ private static final String CA_PREFIX = "http://";
+ private static final String CA_POSTFIX="/certsrv/mscep_admin/mscep.dll";
+
+ private final static String MS_PROFILE="1";
+ private static final String CM_TRUST_CAS = "cm_trust_cas";
+ private Clients clients;
+
+ private static class AAFStdFields implements StandardFields {
+ private final String env;
+ public AAFStdFields(Trans trans) throws CertException {
+ env = trans.getProperty(Config.AAF_ENV);
+ if(env==null) {
+ throw new CertException(Config.AAF_ENV + " must be set to create Certificates");
+ }
+ }
+ @Override
+ public void set(CSRMeta csr) {
+ // Environment
+ csr.environment(env);
+ // Standard Fields
+ csr.o("ATT Services,Inc.");
+ csr.l("St Louis");
+ csr.st("Missouri");
+ csr.c("US");
+ }
+ }
+
+ public AppCA(final Trans trans, final String name, final String urlstr, final String id, final String pw) throws IOException, CertificateException, CertException {
+ super(name,new AAFStdFields(trans), CA_PERM_TYPE);
+
+ clients = new Clients(trans,urlstr);
+
+
+ // Set this for NTLM password Microsoft
+ Authenticator.setDefault(new Authenticator() {
+ public PasswordAuthentication getPasswordAuthentication () {
+ return new PasswordAuthentication (
+ id,
+ trans.decryptor().decrypt(pw).toCharArray());
+ }
+ });
+
+
+
+ try {
+ StringBuilder sb = new StringBuilder("CA Reported Trusted Certificates");
+ List<X509Certificate> trustCerts = new ArrayList<X509Certificate>();
+ for(Client client : clients) {
+ CertStore cs = client.getCaCertificate(MS_PROFILE);
+
+ Collection<? extends Certificate> cc = cs.getCertificates(null);
+ for(Certificate c : cc) {
+ X509Certificate xc = (X509Certificate)c;
+ // Avoid duplicate Certificates from multiple servers
+ X509Certificate match = null;
+ for(X509Certificate t : trustCerts) {
+ if(t.getSerialNumber().equals(xc.getSerialNumber())) {
+ match = xc;
+ break;
+ }
+ }
+ if(match==null && xc.getSubjectDN().getName().startsWith("CN=ATT ")) {
+ sb.append("\n\t");
+ sb.append(xc.getSubjectDN());
+ sb.append("\n\t\tSerial Number: ");
+ String bi = xc.getSerialNumber().toString(16);
+ for(int i=0;i<bi.length();++i) {
+ if(i>1 && i%2==0) {
+ sb.append(':');
+ }
+ sb.append(bi.charAt(i));
+ }
+ sb.append("\n\t\tIssuer: ");
+ sb.append(xc.getIssuerDN());
+ sb.append("\n\t\tNot Before: ");
+ sb.append(xc.getNotBefore());
+ sb.append("\n\t\tNot After: ");
+ sb.append(xc.getNotAfter());
+ sb.append("\n\t\tSigAlgorithm: ");
+ sb.append(xc.getSigAlgName());
+ sb.append("\n\t\tType: ");
+ sb.append(xc.getType());
+ sb.append("\n\t\tVersion: ");
+ sb.append(xc.getVersion());
+
+ trustCerts.add(xc);
+ }
+ }
+ }
+ trans.init().log(sb);
+ // Add Additional ones from Property
+ String data_dir = trans.getProperty(AAF_DATA_DIR);
+ if(data_dir!=null) {
+ File data = new File(data_dir);
+ if(data.exists()) {
+ String trust_cas = trans.getProperty(CM_TRUST_CAS);
+ byte[] bytes;
+ if(trust_cas!=null) {
+ for(String fname : Split.split(';', trust_cas)) {
+ File crt = new File(data,fname);
+ if(crt.exists()) {
+ bytes = Factory.decode(crt);
+ try {
+ Collection<? extends Certificate> cc = Factory.toX509Certificate(bytes);
+ for(Certificate c : cc) {
+ trustCerts.add((X509Certificate)c);
+ }
+ } catch (CertificateException e) {
+ throw new CertException(e);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ String[] trustChain = new String[trustCerts.size()];
+ int i=-1;
+ for( Certificate cert : trustCerts) {
+ trustChain[++i]=BCFactory.toString(trans,cert);
+ }
+
+ setTrustChain(trustChain);
+ } catch (ClientException | CertStoreException e) {
+ // Note: Cannot validly start without all Clients, because we need to read all Issuing Certificates
+ // This is acceptable risk for most things, as we're not real time in general
+ throw new CertException(e);
+ }
+ }
+
+
+ @Override
+ public X509Certificate 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(trans, csr));
+ }
+ if(trans.info().isLoggable()) {
+ trans.info().log(csr);
+ }
+ } finally {
+ tt.done();
+ }
+
+ tt = trans.start("Enroll CSR", Env.SUB);
+ Client client = null;
+ try {
+ client = clients.best();
+ 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()) {
+ for( Certificate cert : er.getCertStore().getCertificates(null)) {
+ return (X509Certificate)cert;
+ }
+ break;
+ } else if (er.isPending()) {
+ trans.checkpoint("Polling, waiting on CA to complete");
+ Thread.sleep(3000);
+ } else if (er.isFailure()) {
+ throw new CertException(er.getFailInfo().toString());
+ }
+ }
+ } catch (ClientException e) {
+ trans.error().log(e,"SCEP Client Error, Temporarily Invalidating Client");
+ if(client!=null) {
+ clients.invalidate(client);
+ }
+ } catch (InterruptedException|TransactionException|CertificateException|OperatorCreationException | CertStoreException e) {
+ trans.error().log(e);
+ } finally {
+ tt.done();
+ }
+
+ return null;
+ }
+
+
+ private class Clients implements Iterable<Client>{
+ /**
+ * CSO Servers are in Dallas and St Louis
+ * GEO_LOCATION LATITUDE LONGITUDE ZIPCODE TIMEZONE
+ * ------------ -------- --------- ------- --------
+ * DLLSTXCF 32.779295 -96.800014 75202 America/Chicago
+ * STLSMORC 38.627345 -90.193774 63101 America/Chicago
+ *
+ * The online production issuing CA servers are:
+ * AAF - CADI Issuing CA 01 135.41.45.152 MOSTLS1AAFXXA02
+ * AAF - CADI Issuing CA 02 135.31.72.154 TXDLLS2AAFXXA02
+ */
+
+ private final Client[] client;
+ private final Date[] failure;
+ private int preferred;
+
+ public Clients(Trans trans, String urlstr) throws MalformedURLException {
+ String[] urlstrs = Split.split(',', urlstr);
+ client = new Client[urlstrs.length];
+ failure = new Date[urlstrs.length];
+ double distance = Double.MAX_VALUE;
+ String localLat = trans.getProperty("AFT_LATITUDE","39.833333"); //Note: Defaulting to GEO center of US
+ String localLong = trans.getProperty("AFT_LONGITUDE","-98.583333");
+ for(int i=0;i<urlstrs.length;++i) {
+ String[] info = Split.split('/', urlstrs[i]);
+ if(info.length<3) {
+ throw new MalformedURLException("Configuration needs LAT and LONG, i.e. ip:port/lat/long");
+ }
+ client[i] = new Client(new URL(CA_PREFIX + info[0] + CA_POSTFIX),
+ new CertificateVerifier() {
+ @Override
+ public boolean verify(X509Certificate cert) {
+ return true;
+ }
+ }
+ );
+ double d = GreatCircle.calc(info[1],info[2],localLat,localLong);
+ if(d<distance) {
+ preferred = i;
+ distance=d;
+ }
+ }
+ trans.init().printf("Preferred Certificate Authority is %s",urlstrs[preferred]);
+ for(int i=0;i<urlstrs.length;++i) {
+ if(i!=preferred) {
+ trans.init().printf("Alternate Certificate Authority is %s",urlstrs[i]);
+ }
+ }
+ }
+ private Client best() throws ClientException {
+ if(failure[preferred]==null) {
+ return client[preferred];
+ } else {
+ Client c=null;
+ // See if Alternate available
+ for(int i=0;i<failure.length;++i) {
+ if(failure[i]==null) {
+ c=client[i];
+ }
+ }
+
+ // If not, see if any expirations can be cleared
+ Date now = new Date();
+ for(int i=0;i<failure.length;++i) {
+ if(now.after(failure[i])) {
+ failure[i]=null;
+ if(c==null) {
+ c=client[i];
+ }
+ }
+ }
+
+ // if still nothing found, then throw.
+ if(c==null) {
+ throw new ClientException("No available machines to call");
+ }
+ return c;
+ }
+ }
+
+ public void invalidate(Client clt) {
+ for(int i=0;i<client.length;++i) {
+ if(client[i].equals(clt)) {
+ failure[i]=new Date(System.currentTimeMillis()+180000 /* 3 mins */);
+ }
+ }
+ }
+
+ @Override
+ public Iterator<Client> iterator() {
+ return new Iterator<Client>() {
+ private int iter = 0;
+ @Override
+ public boolean hasNext() {
+ return iter < Clients.this.client.length;
+ }
+
+ @Override
+ public Client next() {
+ return Clients.this.client[iter++];
+ }
+
+ };
+ }
+ }
+}
diff --git a/authz-certman/src/main/java/com/att/authz/cm/ca/CA.java b/authz-certman/src/main/java/com/att/authz/cm/ca/CA.java new file mode 100644 index 00000000..fab89941 --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/ca/CA.java @@ -0,0 +1,84 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.ca;
+
+import java.io.IOException;
+import java.security.MessageDigest;
+import java.security.cert.X509Certificate;
+
+import com.att.authz.cm.cert.CSRMeta;
+import com.att.authz.cm.cert.StandardFields;
+import com.att.cadi.cm.CertException;
+import com.att.inno.env.Trans;
+
+public abstract class CA {
+ private final String name;
+ private String[] trustChain;
+ private final StandardFields stdFields;
+ private MessageDigest messageDigest;
+ private final String permType;
+
+ protected CA(String name, StandardFields sf, String permType) {
+ this.name = name;
+ stdFields = sf;
+ this.permType = permType;
+ }
+
+ /*
+ * NOTE: These two functions must be called in Protected Constructors during their Construction.
+ */
+ protected void setTrustChain(String[] trustChain) {
+ this.trustChain = trustChain;
+ }
+
+ protected void setMessageDigest(MessageDigest md) {
+ messageDigest = md;
+ }
+
+ /*
+ * End Required Constructor calls
+ */
+
+ public String getName() {
+ return name;
+ }
+
+ public String[] getTrustChain() {
+ return trustChain;
+ }
+
+ public String getPermType() {
+ return permType;
+ }
+
+ public StandardFields stdFields() {
+ return stdFields;
+ }
+
+ public abstract X509Certificate sign(Trans trans, CSRMeta csrmeta) throws IOException, CertException;
+
+ public MessageDigest messageDigest() {
+ return messageDigest;
+ }
+}
diff --git a/authz-certman/src/main/java/com/att/authz/cm/ca/DevlCA.java b/authz-certman/src/main/java/com/att/authz/cm/ca/DevlCA.java new file mode 100644 index 00000000..bc999f29 --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/ca/DevlCA.java @@ -0,0 +1,227 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.ca;
+
+import java.io.File;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyFactory;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.X509Certificate;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.security.SecureRandom;
+
+import org.bouncycastle.asn1.ASN1Sequence;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x500.X500NameBuilder;
+import org.bouncycastle.asn1.x500.style.BCStyle;
+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.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.cert.jcajce.JcaX509ExtensionUtils;
+import org.bouncycastle.operator.OperatorCreationException;
+
+import com.att.authz.cm.cert.BCFactory;
+import com.att.authz.cm.cert.CSRMeta;
+import com.att.authz.cm.cert.StandardFields;
+import com.att.authz.common.Define;
+import com.att.cadi.cm.CertException;
+import com.att.cadi.cm.Factory;
+import com.att.inno.env.Env;
+import com.att.inno.env.TimeTaken;
+import com.att.inno.env.Trans;
+
+public class DevlCA extends CA {
+
+ // Extensions
+ private static final KeyPurposeId[] ASN_WebUsage = new KeyPurposeId[] {
+ KeyPurposeId.id_kp_serverAuth, // WebServer
+ KeyPurposeId.id_kp_clientAuth};// WebClient
+
+ private X509Certificate caCert;
+ private final RSAPrivateKey caKey;
+ private final X500Name issuer;
+ private final SecureRandom random = new SecureRandom();
+ private byte[] serialish = new byte[24];
+
+ public DevlCA(Trans trans, String name, String dirString) throws IOException, CertException {
+ super(name, new StandardFields() {
+ @Override
+ public void set(CSRMeta csr) {
+ // Standard Fields
+ csr.o("ATT Services, Inc.");
+ csr.l("St Louis");
+ csr.st("Missouri");
+ csr.c("US");
+ }
+ }, Define.ROOT_NS+".ca" // Permission Type for validation
+ );
+ File dir = new File(dirString);
+ if(!dir.exists()) {
+ throw new CertException(dirString + " does not exist");
+ }
+
+ File ca = new File(dir,"ca.crt");
+ if(ca.exists()) {
+ byte[] bytes = Factory.decode(ca);
+ Collection<? extends Certificate> certs;
+ try {
+ certs = Factory.toX509Certificate(bytes);
+ } catch (CertificateException e) {
+ throw new CertException(e);
+ }
+ List<String> lTrust = new ArrayList<String>();
+ caCert=null;
+ for(Certificate c : certs) {
+ if(caCert==null) {
+ caCert = (X509Certificate)c;
+ } else {
+ lTrust.add(Factory.toString(trans,c));
+ }
+ break;
+ }
+ }
+
+ this.setTrustChain(new String[]{Factory.toString(trans,caCert)});
+
+ /*
+ * Private key needs to be converted to "DER" format, with no password.
+ * Use chmod 400 on key
+ *
+ * openssl pkcs8 -topk8 -outform DER -nocrypt -in ca.key -out ca.der
+ *
+ */
+ ca = new File(dir,"ca.der");
+ if(ca.exists()) {
+ byte[] bytes = Factory.binary(ca);
+
+// EncryptedPrivateKeyInfo ekey=new EncryptedPrivateKeyInfo(bytes);
+// Cipher cip=Cipher.getInstance(ekey.getAlgName());
+// PBEKeySpec pspec=new PBEKeySpec("password".toCharArray());
+// SecretKeyFactory skfac=SecretKeyFactory.getInstance(ekey.getAlgName());
+// Key pbeKey=skfac.generateSecret(pspec);
+// AlgorithmParameters algParams=ekey.getAlgParameters();
+// cip.init(Cipher.DECRYPT_MODE,pbeKey,algParams);
+
+ KeyFactory keyFactory;
+ try {
+ keyFactory = KeyFactory.getInstance("RSA");
+ PKCS8EncodedKeySpec privSpec = new PKCS8EncodedKeySpec(bytes);
+
+ caKey = (RSAPrivateKey) keyFactory.generatePrivate(privSpec);
+ } catch (GeneralSecurityException e) {
+ throw new CertException(e);
+ }
+
+ X500NameBuilder xnb = new X500NameBuilder();
+ xnb.addRDN(BCStyle.C,"US");
+ xnb.addRDN(BCStyle.ST,"Missouri");
+ xnb.addRDN(BCStyle.L,"Arnold");
+ xnb.addRDN(BCStyle.O,"ATT Services, Inc.");
+ xnb.addRDN(BCStyle.OU,"AAF");
+ xnb.addRDN(BCStyle.CN,"aaf.att.com");
+ xnb.addRDN(BCStyle.EmailAddress,"DL-aaf-support@att.com");
+ issuer = xnb.build();
+ } else {
+ throw new CertException(ca.getPath() + " does not exist");
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see com.att.authz.cm.service.CA#sign(org.bouncycastle.pkcs.PKCS10CertificationRequest)
+ */
+ @Override
+ public X509Certificate sign(Trans trans, CSRMeta csrmeta) throws IOException, CertException {
+ GregorianCalendar gc = new GregorianCalendar();
+ Date start = gc.getTime();
+ gc.add(GregorianCalendar.DAY_OF_MONTH, 1);
+ 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);
+ }
+
+ X509v3CertificateBuilder xcb = new X509v3CertificateBuilder(
+ issuer,
+ bi, // replace with Serialnumber scheme
+ start,
+ end,
+ csrmeta.x500Name(),
+// SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(caCert.getPublicKey().getEn)
+ 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(caCert))
+ .addExtension(Extension.subjectKeyIdentifier,
+ false, extUtils.createSubjectKeyIdentifier(caCert.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 x509;
+ }
+
+}
diff --git a/authz-certman/src/main/java/com/att/authz/cm/cert/BCFactory.java b/authz-certman/src/main/java/com/att/authz/cm/cert/BCFactory.java new file mode 100644 index 00000000..52621e54 --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/cert/BCFactory.java @@ -0,0 +1,169 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.cert;
+
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+import java.lang.reflect.Field;
+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 com.att.authz.cm.ca.CA;
+import com.att.authz.cm.validation.Validator;
+import com.att.cadi.Symm;
+import com.att.cadi.cm.CertException;
+import com.att.cadi.cm.Factory;
+import com.att.inno.env.Env;
+import com.att.inno.env.TimeTaken;
+import com.att.inno.env.Trans;
+
+
+/**
+ * Additional Factory mechanisms for CSRs, and BouncyCastle. The main Factory
+ * utilizes only Java abstractions, and is useful in Client code.
+ *
+
+ *
+ */
+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(Trans trans, PKCS10CertificationRequest csr) throws IOException, CertException {
+ TimeTaken tt = trans.start("CSR to String", Env.SUB);
+ try {
+ if(csr==null) {
+ throw new CertException("x509 Certificate Request not built");
+ }
+ return textBuilder("CERTIFICATE REQUEST",csr.getEncoded());
+ }finally {
+ tt.done();
+ }
+ }
+
+ 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,final String args[]) throws IllegalArgumentException, IllegalAccessException, CertException {
+ CSRMeta csr = new CSRMeta();
+ ca.stdFields().set(csr);
+ //TODO should we checkDigest?
+// digest = ca.messageDigest();
+
+ Field[] fld = CSRMeta.class.getDeclaredFields();
+ for(int i=0;i+1<args.length;++i) {
+ if(args[i].charAt(0)=='-') {
+ for(int j=0;j<fld.length;++j) {
+ if(fld[j].getType().equals(String.class) && args[i].substring(1).equals(fld[j].getName())) {
+ fld[j].set(csr,args[++i]);
+ break;
+ }
+ }
+ }
+ }
+ String errs = validate(csr);
+ if(errs!=null) {
+ throw new CertException(errs);
+ }
+ return csr;
+ }
+
+
+ public static CSRMeta createCSRMeta(CA ca, String mechid, String sponsorEmail, List<String> fqdns) throws CertException {
+ CSRMeta csr = new CSRMeta();
+ boolean first = true;
+ // Set CN (and SAN)
+ for(String fqdn : fqdns) {
+ if(first) {
+ first = false;
+ csr.cn(fqdn);
+ } else {
+ csr.san(fqdn);
+ }
+ }
+
+ csr.challenge(new String(Symm.randomGen(24)));
+ ca.stdFields().set(csr);
+ csr.mechID(mechid);
+ csr.email(sponsorEmail);
+ String errs = validate(csr);
+ if(errs!=null) {
+ throw new CertException(errs);
+ }
+ return csr;
+ }
+
+ private static String validate(CSRMeta csr) {
+ Validator v = new Validator();
+ if(v.nullOrBlank("cn", csr.cn())
+ .nullOrBlank("mechID", csr.mechID())
+ .nullOrBlank("email", csr.email())
+ .nullOrBlank("o",csr.o())
+ .nullOrBlank("l",csr.l())
+ .nullOrBlank("st",csr.st())
+ .nullOrBlank("c",csr.c())
+ .err()) {
+ return v.errs();
+ } else {
+ return null;
+ }
+ }
+
+
+}
diff --git a/authz-certman/src/main/java/com/att/authz/cm/cert/CSRMeta.java b/authz-certman/src/main/java/com/att/authz/cm/cert/CSRMeta.java new file mode 100644 index 00000000..91168dc9 --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/cert/CSRMeta.java @@ -0,0 +1,330 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.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 com.att.cadi.cm.CertException;
+import com.att.cadi.cm.Factory;
+import com.att.inno.env.Trans;
+
+public class CSRMeta {
+ private String environment;
+ private String cn;
+ private String mechID;
+ private String email;
+ private String o;
+ private String l;
+ private String st;
+ private String c;
+ private String challenge;
+
+ 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(environment==null) {
+ xnb.addRDN(BCStyle.OU,mechID);
+ } else {
+ xnb.addRDN(BCStyle.OU,mechID+':'+environment);
+ }
+ xnb.addRDN(BCStyle.O,o);
+ xnb.addRDN(BCStyle.L,l);
+ xnb.addRDN(BCStyle.ST,st);
+ xnb.addRDN(BCStyle.C,c);
+ 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);
+ }
+
+ if(sanList.size()>0) {
+ GeneralName[] gna = new GeneralName[sanList.size()];
+ int i=-1;
+ for(String s : sanList) {
+ gna[++i]=new GeneralName(GeneralName.dNSName,s);
+ }
+
+ builder.addAttribute(
+ PKCSObjectIdentifiers.pkcs_9_at_extensionRequest,
+ new Extensions(new Extension[] {
+ new Extension(Extension.subjectAlternativeName,false,new GeneralNames(gna).getEncoded())
+ })
+ );
+ }
+// builder.addAttribute(Extension.basicConstraints,new BasicConstraints(false))
+// .addAttribute(Extension.keyUsage, new KeyUsage(KeyUsage.digitalSignature
+// | KeyUsage.keyEncipherment));
+ 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));
+// Extension ext = extensions.getExtension(Extension.subjectAlternativeName);
+ 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";
+ }
+ 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(),
+// SubjectPublicKeyInfoFactory.createSubjectPublicKeyInfo(caCert.getPublicKey().getEn)
+ 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 o
+ */
+ public String o() {
+ return o;
+ }
+
+
+ /**
+ * @param o the o to set
+ */
+ public void o(String o) {
+ this.o = o;
+ }
+
+ /**
+ *
+ * @return the l
+ */
+ public String l() {
+ return l;
+ }
+
+ /**
+ * @param l the l to set
+ */
+ public void l(String l) {
+ this.l=l;
+ }
+
+ /**
+ * @return the st
+ */
+ public String st() {
+ return st;
+ }
+
+
+ /**
+ * @param st the st to set
+ */
+ public void st(String st) {
+ this.st = st;
+ }
+
+
+ /**
+ * @return the c
+ */
+ public String c() {
+ return c;
+ }
+
+
+ /**
+ * @param c the c to set
+ */
+ public void c(String c) {
+ this.c = c;
+ }
+
+
+ /**
+ * @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/authz-certman/src/main/java/com/att/authz/cm/cert/StandardFields.java b/authz-certman/src/main/java/com/att/authz/cm/cert/StandardFields.java new file mode 100644 index 00000000..e9c2457a --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/cert/StandardFields.java @@ -0,0 +1,30 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.cert;
+
+import com.att.cadi.cm.CertException;
+
+public interface StandardFields {
+ public void set(CSRMeta csr) throws CertException;
+}
diff --git a/authz-certman/src/main/java/com/att/authz/cm/data/CertDrop.java b/authz-certman/src/main/java/com/att/authz/cm/data/CertDrop.java new file mode 100644 index 00000000..c0a219db --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/data/CertDrop.java @@ -0,0 +1,28 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.data;
+
+public class CertDrop {
+
+}
diff --git a/authz-certman/src/main/java/com/att/authz/cm/data/CertRenew.java b/authz-certman/src/main/java/com/att/authz/cm/data/CertRenew.java new file mode 100644 index 00000000..4c13ab40 --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/data/CertRenew.java @@ -0,0 +1,28 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.data;
+
+public class CertRenew {
+
+}
diff --git a/authz-certman/src/main/java/com/att/authz/cm/data/CertReq.java b/authz-certman/src/main/java/com/att/authz/cm/data/CertReq.java new file mode 100644 index 00000000..6806a588 --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/data/CertReq.java @@ -0,0 +1,51 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.data;
+
+import java.util.List;
+
+import javax.xml.datatype.XMLGregorianCalendar;
+
+import com.att.authz.cm.ca.CA;
+import com.att.authz.cm.cert.BCFactory;
+import com.att.authz.cm.cert.CSRMeta;
+import com.att.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/authz-certman/src/main/java/com/att/authz/cm/data/CertResp.java b/authz-certman/src/main/java/com/att/authz/cm/data/CertResp.java new file mode 100644 index 00000000..8257e5cf --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/data/CertResp.java @@ -0,0 +1,66 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.data;
+
+import java.io.IOException;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.cert.X509Certificate;
+
+import com.att.authz.cm.cert.CSRMeta;
+import com.att.cadi.cm.CertException;
+import com.att.cadi.cm.Factory;
+import com.att.inno.env.Trans;
+
+public class CertResp {
+ public CertResp(Trans trans, X509Certificate x509, CSRMeta csrMeta, 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.notes = notes;
+ }
+ private KeyPair keyPair;
+ private String challenge;
+
+ private String privateKey, certString;
+ private String[] notes;
+
+
+ public String asCertString() {
+ return certString;
+ }
+
+ public String privateString() throws IOException {
+ return privateKey;
+ }
+
+ public String challenge() {
+ return challenge==null?"":challenge;
+ }
+
+ public String[] notes() {
+ return notes;
+ }
+}
diff --git a/authz-certman/src/main/java/com/att/authz/cm/facade/Facade.java b/authz-certman/src/main/java/com/att/authz/cm/facade/Facade.java new file mode 100644 index 00000000..249f218e --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/facade/Facade.java @@ -0,0 +1,162 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.facade;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.att.authz.cm.mapper.Mapper;
+import com.att.authz.env.AuthzTrans;
+import com.att.authz.layer.Result;
+
+
+/**
+ *
+ *
+ */
+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, boolean withTrust);
+
+ /**
+ *
+ * @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 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);
+
+
+
+}
diff --git a/authz-certman/src/main/java/com/att/authz/cm/facade/Facade1_0.java b/authz-certman/src/main/java/com/att/authz/cm/facade/Facade1_0.java new file mode 100644 index 00000000..6dd012dd --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/facade/Facade1_0.java @@ -0,0 +1,47 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.facade;
+
+import com.att.authz.cm.mapper.Mapper;
+import com.att.authz.cm.service.CMService;
+import com.att.authz.cm.service.CertManAPI;
+import com.att.inno.env.APIException;
+import com.att.inno.env.Data;
+
+import aaf.v2_0.Error;
+import certman.v1_0.Artifacts;
+import certman.v1_0.BaseRequest;
+import certman.v1_0.CertInfo;
+
+/**
+ *
+ */
+public class Facade1_0 extends FacadeImpl<BaseRequest,CertInfo, Artifacts, Error> {
+ public Facade1_0(CertManAPI certman,
+ CMService service,
+ Mapper<BaseRequest,CertInfo,Artifacts,Error> mapper,
+ Data.TYPE type) throws APIException {
+ super(certman, service, mapper, type);
+ }
+}
diff --git a/authz-certman/src/main/java/com/att/authz/cm/facade/FacadeFactory.java b/authz-certman/src/main/java/com/att/authz/cm/facade/FacadeFactory.java new file mode 100644 index 00000000..e9e5d54a --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/facade/FacadeFactory.java @@ -0,0 +1,43 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.facade;
+
+import com.att.authz.cm.mapper.Mapper1_0;
+import com.att.authz.cm.service.CertManAPI;
+import com.att.authz.cm.service.CMService;
+import com.att.authz.env.AuthzTrans;
+import com.att.inno.env.APIException;
+import com.att.inno.env.Data;
+
+
+public class FacadeFactory {
+ public static Facade1_0 v1_0(CertManAPI certman, AuthzTrans trans, CMService service, Data.TYPE type) throws APIException {
+ return new Facade1_0(
+ certman,
+ service,
+ new Mapper1_0(),
+ type);
+ }
+
+}
diff --git a/authz-certman/src/main/java/com/att/authz/cm/facade/FacadeImpl.java b/authz-certman/src/main/java/com/att/authz/cm/facade/FacadeImpl.java new file mode 100644 index 00000000..22421442 --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/facade/FacadeImpl.java @@ -0,0 +1,493 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.facade;
+
+import static com.att.authz.layer.Result.ERR_ActionNotCompleted;
+import static com.att.authz.layer.Result.ERR_BadData;
+import static com.att.authz.layer.Result.ERR_ConflictAlreadyExists;
+import static com.att.authz.layer.Result.ERR_Denied;
+import static com.att.authz.layer.Result.ERR_NotFound;
+import static com.att.authz.layer.Result.ERR_NotImplemented;
+import static com.att.authz.layer.Result.ERR_Policy;
+import static com.att.authz.layer.Result.ERR_Security;
+import static com.att.authz.layer.Result.OK;
+
+import java.io.IOException;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import com.att.authz.cm.api.API_Cert;
+import com.att.authz.cm.ca.CA;
+import com.att.authz.cm.data.CertResp;
+import com.att.authz.cm.mapper.Mapper;
+import com.att.authz.cm.mapper.Mapper.API;
+import com.att.authz.cm.service.CMService;
+import com.att.authz.cm.service.CertManAPI;
+import com.att.authz.env.AuthzEnv;
+import com.att.authz.env.AuthzTrans;
+import com.att.authz.layer.Result;
+import com.att.cadi.aaf.AAFPermission;
+import com.att.dao.aaf.cass.ArtiDAO;
+import com.att.dao.aaf.cass.Status;
+import com.att.inno.env.APIException;
+import com.att.inno.env.Data;
+import com.att.inno.env.Env;
+import com.att.inno.env.Slot;
+import com.att.inno.env.TimeTaken;
+import com.att.inno.env.util.Split;
+import com.att.rosetta.env.RosettaDF;
+import com.att.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
+ *
+ *
+ */
+public abstract class FacadeImpl<REQ,CERT,ARTIFACTS,ERROR> extends com.att.authz.layer.FacadeImpl implements Facade<REQ,CERT,ARTIFACTS,ERROR>
+ {
+ 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 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 CertManAPI certman;
+ private final String voidResp;
+
+ public FacadeImpl(CertManAPI 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;
+ (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(com.att.authz.env.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;
+ 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);
+ break;
+ }
+
+ try {
+ StringBuilder holder = new StringBuilder();
+ errDF.newData(trans).load(
+ mapper().errorFromMessage(holder, msgId,prefix + ": " + _msg,_detail)).to(response.getOutputStream());
+
+ holder.append(']');
+ trans.checkpoint(
+ "ErrResp [" +
+ holder,
+ Env.ALWAYS);
+ } 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(com.att.authz.env.AuthzTrans, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ */
+ @Override
+ public Result<Void> requestCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, boolean withTrust) {
+ TimeTaken tt = trans.start(REQUEST_CERT, Env.SUB|Env.ALWAYS);
+ 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));
+ if(rcr.notOK()) {
+ return Result.err(rcr);
+ }
+
+ CA certAuth = trans.get(sCertAuth,null);
+ Result<CERT> rc = mapper.toCert(trans, rcr, withTrust?certAuth.getTrustChain():null);
+ 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();
+ }
+ }
+
+ @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, certman.getTrustChain(certAuth));
+
+ 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();
+ }
+ }
+
+ ////////////////////////////
+ // 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");
+
+ 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;
+ ra = mapper.fromArtifacts(service.readArtifacts(trans,add));
+ } 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();
+ }
+ }
+
+
+}
diff --git a/authz-certman/src/main/java/com/att/authz/cm/mapper/Mapper.java b/authz-certman/src/main/java/com/att/authz/cm/mapper/Mapper.java new file mode 100644 index 00000000..7218b150 --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/mapper/Mapper.java @@ -0,0 +1,53 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.mapper;
+
+import java.io.IOException;
+import java.util.List;
+
+import com.att.authz.cm.data.CertDrop;
+import com.att.authz.cm.data.CertRenew;
+import com.att.authz.cm.data.CertReq;
+import com.att.authz.cm.data.CertResp;
+import com.att.authz.env.AuthzTrans;
+import com.att.authz.layer.Result;
+import com.att.dao.aaf.cass.ArtiDAO;
+
+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, String[] trustChain) throws IOException;
+ 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/authz-certman/src/main/java/com/att/authz/cm/mapper/Mapper1_0.java b/authz-certman/src/main/java/com/att/authz/cm/mapper/Mapper1_0.java new file mode 100644 index 00000000..63c4f6a9 --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/mapper/Mapper1_0.java @@ -0,0 +1,246 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.mapper;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+
+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;
+
+import com.att.authz.cm.data.CertDrop;
+import com.att.authz.cm.data.CertRenew;
+import com.att.authz.cm.data.CertReq;
+import com.att.authz.cm.data.CertResp;
+import com.att.authz.cm.validation.Validator;
+import com.att.authz.env.AuthzTrans;
+import com.att.authz.layer.Result;
+import com.att.cadi.aaf.v2_0.AAFCon;
+import com.att.cadi.util.Vars;
+import com.att.dao.aaf.cass.ArtiDAO;
+import com.att.dao.aaf.cass.ArtiDAO.Data;
+
+
+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(com.att.authz.env.AuthzTrans, com.att.authz.layer.Result)
+ */
+ @Override
+ public Result<CertInfo> toCert(AuthzTrans trans, Result<CertResp> in, String[] trustChain) 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(trustChain!=null) {
+ for(String c : 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());
+ }
+ return Result.ok(cout);
+ } else {
+ return Result.err(in);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see com.att.authz.certman.mapper.Mapper#toReq(com.att.authz.env.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();
+ Validator v = new Validator();
+ if(v.isNull("CertRequest", req)
+ .nullOrBlank("MechID", out.mechid=in.getMechid())
+ .nullBlankMin("FQDNs", out.fqdns=in.getFqdns(),1)
+ .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();
+ return Result.ok(out);
+ }
+
+ /* (non-Javadoc)
+ * @see com.att.authz.certman.mapper.Mapper#toRenew(com.att.authz.env.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(com.att.authz.env.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 com.att.authz.cm.mapper.Mapper#toArtifact(com.att.authz.env.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.appName = arti.getAppName();
+ 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.appName==null ) {
+ data.appName=AAFCon.reverseDomain(data.machine);
+ }
+ }
+
+ ladd.add(data);
+ }
+ return ladd;
+ }
+
+ /* (non-Javadoc)
+ * @see com.att.authz.cm.mapper.Mapper#fromArtifacts(com.att.authz.layer.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.setAppName(arti.appName);
+ 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);
+ artis.getArtifact().add(a);
+ }
+ return Result.ok(artis);
+ } else {
+ return Result.err(lArtiDAO);
+ }
+ }
+
+
+
+}
diff --git a/authz-certman/src/main/java/com/att/authz/cm/service/CMService.java b/authz-certman/src/main/java/com/att/authz/cm/service/CMService.java new file mode 100644 index 00000000..9e6d5fa9 --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/service/CMService.java @@ -0,0 +1,515 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.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.List;
+
+import com.att.authz.cm.api.API_Cert;
+import com.att.authz.cm.ca.CA;
+import com.att.authz.cm.cert.BCFactory;
+import com.att.authz.cm.cert.CSRMeta;
+import com.att.authz.cm.data.CertDrop;
+import com.att.authz.cm.data.CertRenew;
+import com.att.authz.cm.data.CertReq;
+import com.att.authz.cm.data.CertResp;
+import com.att.authz.cm.validation.Validator;
+import com.att.authz.env.AuthzTrans;
+import com.att.authz.layer.Result;
+import com.att.authz.org.Organization;
+import com.att.authz.org.Organization.Identity;
+import com.att.authz.org.OrganizationException;
+import com.att.cadi.Hash;
+import com.att.cadi.aaf.AAFPermission;
+import com.att.cadi.aaf.v2_0.AAFCon;
+import com.att.cadi.cm.Factory;
+import com.att.dao.CassAccess;
+import com.att.dao.DAO;
+import com.att.dao.aaf.cass.ArtiDAO;
+import com.att.dao.aaf.cass.CacheInfoDAO;
+import com.att.dao.aaf.cass.CertDAO;
+import com.att.dao.aaf.cass.CredDAO;
+import com.att.dao.aaf.cass.HistoryDAO;
+import com.att.dao.aaf.cass.Status;
+import com.att.dao.aaf.hl.Question;
+import com.att.inno.env.APIException;
+import com.att.inno.env.Slot;
+import com.att.inno.env.util.Chrono;
+import com.datastax.driver.core.Cluster;
+
+
+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";
+
+ private static final String[] NO_NOTES = new String[0];
+ private Slot sCertAuth;
+ private final CertDAO certDAO;
+ private final CredDAO credDAO;
+ private final ArtiDAO artiDAO;
+ private DAO<AuthzTrans, ?>[] daos;
+
+ @SuppressWarnings("unchecked")
+ public CMService(AuthzTrans trans, CertManAPI certman) throws APIException, IOException {
+
+ sCertAuth = certman.env.slot(API_Cert.CERT_AUTH);
+ Cluster cluster;
+ try {
+ cluster = com.att.dao.CassAccess.cluster(certman.env,null);
+ } catch (IOException e) {
+ throw new APIException(e);
+ }
+
+ // jg 4/2015 SessionFilter unneeded... DataStax already deals with Multithreading well
+
+ HistoryDAO hd = new HistoryDAO(trans, 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
+ };
+
+ // Setup Shutdown Hooks for Cluster and Pooled Sessions
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ for(DAO<AuthzTrans,?> dao : daos) {
+ dao.close(trans);
+ }
+
+// sessionFilter.destroy();
+ cluster.close();
+ }
+ });
+ }
+
+ public Result<CertResp> requestCert(AuthzTrans trans,Result<CertReq> req) {
+ if(req.isOK()) {
+ CA ca = trans.get(sCertAuth, null);
+ if(ca==null) {
+ return Result.err(Result.err(Result.ERR_BadData, "Invalid Cert Authority requested"));
+ }
+
+ // Allow only AAF CA without special permission
+ if(!ca.getName().equals("aaf") && !trans.fish( new AAFPermission(ca.getPermType(), 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;
+ String email = null;
+
+ try {
+ Organization org = trans.org();
+
+ // Policy 1: Requests are only by Pre-Authorized Configurations
+ ArtiDAO.Data add = null;
+ try {
+ for(InetAddress ia : InetAddress.getAllByName(trans.ip())) {
+ Result<List<ArtiDAO.Data>> ra = artiDAO.read(trans, req.value.mechid,ia.getHostName());
+ if(ra.isOKhasData()) {
+ add = ra.value.get(0);
+ break;
+ }
+ }
+ } catch (UnknownHostException e1) {
+ return Result.err(Result.ERR_BadData,"There is no host for %s",trans.ip());
+ }
+
+ if(add==null) {
+ return Result.err(Result.ERR_BadData,"There is no configuration for %s",req.value.mechid);
+ }
+
+ // 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.owner();
+ 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.isResponsible()) {
+ 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 6: Requester must be granted Change permission in Namespace requested
+ String mechNS = AAFCon.reverseDomain(req.value.mechid);
+ if(mechNS==null) {
+ return Result.err(Status.ERR_Denied, "%s does not reflect a valid AAF Namespace",req.value.mechid);
+ }
+
+ // 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
+ fqdns = new ArrayList<String>();
+ fqdns.add(add.machine); // machine is first
+ if(req.value.fqdns.size()>1 && !trans.fish(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. This Certificate will be created, but without SANs");
+ } else {
+ for(String m : req.value.fqdns) {
+ if(!add.machine.equals(m)) {
+ fqdns.add(m);
+ }
+ }
+ }
+
+ } 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);
+ X509Certificate x509 = ca.sign(trans, csrMeta);
+ if(x509==null) {
+ return Result.err(Result.ERR_ActionNotCompleted,"x509 Certificate not signed by CA");
+ }
+ 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,x509,csrMeta, 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);
+ }
+ }
+
+ ///////////////
+ // Artifact
+ //////////////
+ public Result<Void> createArtifact(AuthzTrans trans, List<ArtiDAO.Data> list) {
+ Validator v = new Validator().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.owner();
+ 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();
+ }
+
+ // 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 {
+ Validator v = new Validator().keys(add);
+ if(v.err()) {
+ return Result.err(Result.ERR_BadData,v.errs());
+ }
+ String ns = AAFCon.reverseDomain(add.mechid);
+
+ if( trans.user().equals(add.mechid)
+ || trans.fish(new AAFPermission(ns + ".access", "*", "read"))
+ || (trans.org().validate(trans,Organization.Policy.OWNS_MECHID,null,add.mechid))==null) {
+ return artiDAO.read(trans, add);
+ } 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); // note: reason is set by 2nd case, if 1st case misses
+ }
+
+ }
+
+ public Result<List<ArtiDAO.Data>> readArtifactsByMechID(AuthzTrans trans, String mechid) throws OrganizationException {
+ Validator v = new Validator().nullOrBlank("mechid", mechid);
+ if(v.err()) {
+ return Result.err(Result.ERR_BadData,v.errs());
+ }
+ String ns = AAFCon.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) {
+ Validator v = new Validator().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<Void> updateArtifact(AuthzTrans trans, List<ArtiDAO.Data> list) throws OrganizationException {
+ Validator v = new Validator().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.owner();
+ 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 4: 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 {
+ Validator v = new Validator()
+ .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.owner();
+ 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 = AAFCon.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) {
+ Validator v = new Validator().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/authz-certman/src/main/java/com/att/authz/cm/service/CertManAPI.java b/authz-certman/src/main/java/com/att/authz/cm/service/CertManAPI.java new file mode 100644 index 00000000..fa8ac6fd --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/service/CertManAPI.java @@ -0,0 +1,286 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.service;
+
+import java.lang.reflect.Constructor;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.TreeMap;
+
+import com.att.aft.dme2.api.DME2Exception;
+//import com.att.aft.dme2.api.DME2FilterHolder;
+//import com.att.aft.dme2.api.DME2FilterHolder.RequestDispatcherType;
+import com.att.aft.dme2.api.DME2Manager;
+import com.att.aft.dme2.api.DME2Server;
+import com.att.aft.dme2.api.DME2ServerProperties;
+import com.att.aft.dme2.api.DME2ServiceHolder;
+import com.att.aft.dme2.api.util.DME2FilterHolder;
+import com.att.aft.dme2.api.util.DME2FilterHolder.RequestDispatcherType;
+import com.att.aft.dme2.api.util.DME2ServletHolder;
+//import com.att.aft.dme2.api.DME2ServletHolder;
+import com.att.authz.cm.api.API_Artifact;
+import com.att.authz.cm.api.API_Cert;
+import com.att.authz.cm.ca.CA;
+import com.att.authz.cm.facade.Facade1_0;
+import com.att.authz.cm.facade.FacadeFactory;
+import com.att.authz.cm.mapper.Mapper.API;
+import com.att.authz.env.AuthzEnv;
+import com.att.authz.env.AuthzTrans;
+import com.att.authz.env.AuthzTransFilter;
+import com.att.authz.server.AbsServer;
+import com.att.cache.Cache;
+import com.att.cache.Cache.Dated;
+import com.att.cadi.Access;
+import com.att.cadi.Access.Level;
+import com.att.cadi.CadiException;
+import com.att.cadi.TrustChecker;
+import com.att.cadi.aaf.v2_0.AAFAuthn;
+import com.att.cadi.aaf.v2_0.AAFCon;
+import com.att.cadi.aaf.v2_0.AAFConHttp;
+import com.att.cadi.aaf.v2_0.AAFLurPerm;
+import com.att.cadi.aaf.v2_0.AAFTrustChecker;
+import com.att.cadi.config.Config;
+import com.att.cssa.rserv.HttpMethods;
+import com.att.inno.env.APIException;
+import com.att.inno.env.Data;
+import com.att.inno.env.Env;
+import com.att.inno.env.Trans;
+import com.att.inno.env.util.Split;
+
+public class CertManAPI extends AbsServer {
+
+ private static final String USER_PERMS = "userPerms";
+ private static final Map<String,CA> certAuths = new TreeMap<String,CA>();
+ private static final String AAF_CERTMAN_CA_PREFIX = null;
+ 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;
+
+ private String[] EMPTY;
+ private AAFCon<?> aafcon;
+
+ /**
+ * Construct AuthzAPI with all the Context Supporting Routes that Authz needs
+ *
+ * @param env
+ * @param si
+ * @param dm
+ * @param decryptor
+ * @throws APIException
+ */
+ public CertManAPI(AuthzEnv env) throws Exception {
+ super(env,"CertMan");
+ env.setLog4JNames("log4j.properties","authz","cm","audit","init","trace");
+
+ //aafcon = new AAFConHttp(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();
+
+ // Load Supported Certificate Authorities by property
+ for(String key : env.existingStaticSlotNames()) {
+ if(key.startsWith(AAF_CERTMAN_CA_PREFIX)) {
+ int idx = key.indexOf('.');
+ String[] params = Split.split(';', env.getProperty(key));
+ if(params.length>1) {
+ @SuppressWarnings("unchecked")
+ Class<CA> cac = (Class<CA>)Class.forName((String)params[0]);
+ Class<?> ptype[] = new Class<?>[params.length+1];
+ ptype[0]=Trans.class;
+ ptype[1]=String.class;
+ Object pinst[] = new Object[params.length+1];
+ pinst[0]=trans;
+ pinst[1]= key.substring(idx+1);
+ for(int i=1;i<params.length;++i) {
+ idx = i+1;
+ ptype[idx]=String.class;
+ pinst[idx]=params[i];
+ }
+ Constructor<CA> cons = cac.getConstructor(ptype);
+ 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);
+ Cache.addShutdownHook(); // Setup Shutdown Hook to close cache
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // 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);
+ }
+
+ public String[] getTrustChain(String key) {
+ CA ca = certAuths.get(key);
+ if(ca==null) {
+ return EMPTY;
+ } else {
+ return ca.getTrustChain();
+ }
+ }
+
+ /**
+ * 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
+ }
+
+
+ /**
+ * Start up AuthzAPI as DME2 Service
+ * @param env
+ * @param props
+ * @throws DME2Exception
+ * @throws CadiException
+ */
+ public void startDME2(Properties props) throws DME2Exception, CadiException {
+ DME2Manager dme2 = new DME2Manager("AAF Certman DME2Manager", props);
+
+
+ DME2ServiceHolder svcHolder;
+ List<DME2ServletHolder> slist = new ArrayList<DME2ServletHolder>();
+ svcHolder = new DME2ServiceHolder();
+ String serviceName = env.getProperty("DMEServiceName",null);
+ if(serviceName!=null) {
+ svcHolder.setServiceURI(serviceName);
+ svcHolder.setManager(dme2);
+ svcHolder.setContext("/");
+
+
+
+ DME2ServletHolder srvHolder = new DME2ServletHolder(this, new String[]{"/cert"});
+ srvHolder.setContextPath("/*");
+ slist.add(srvHolder);
+
+ EnumSet<RequestDispatcherType> edlist = EnumSet.of(
+ RequestDispatcherType.REQUEST,
+ RequestDispatcherType.FORWARD,
+ RequestDispatcherType.ASYNC
+ );
+
+ ///////////////////////
+ // Apply Filters
+ ///////////////////////
+ List<DME2FilterHolder> flist = new ArrayList<DME2FilterHolder>();
+
+ // Secure all GUI interactions with AuthzTransFilter
+ flist.add(new DME2FilterHolder(
+ new AuthzTransFilter(env,aafcon,TrustChecker.NOTRUST),
+ "/*", edlist));
+
+
+ svcHolder.setFilters(flist);
+ svcHolder.setServletHolders(slist);
+
+ DME2Server dme2svr = dme2.getServer();
+ DME2ServerProperties dsprops = dme2svr.getServerProperties();
+ dsprops.setGracefulShutdownTimeMs(1000);
+
+ env.init().log("Starting AAF Certman Jetty/DME2 server...");
+ dme2svr.start();
+ try {
+// if(env.getProperty("NO_REGISTER",null)!=null)
+ dme2.bindService(svcHolder);
+ env.init().log("DME2 is available as HTTP"+(dsprops.isSslEnable()?"/S":""),"on port:",dsprops.getPort());
+ while(true) { // Per DME2 Examples...
+ Thread.sleep(5000);
+ }
+ } catch(InterruptedException e) {
+ env.init().log("AAF Jetty Server interrupted!");
+ } catch(Exception e) { // Error binding service doesn't seem to stop DME2 or Process
+ env.init().log(e,"DME2 Initialization Error");
+ dme2svr.stop();
+ System.exit(1);
+ }
+ } else {
+ env.init().log("Properties must contain DMEServiceName");
+ }
+ }
+
+ public static void main(String[] args) {
+ setup(CertManAPI.class, "certman.props");
+
+ }
+
+}
diff --git a/authz-certman/src/main/java/com/att/authz/cm/service/Code.java b/authz-certman/src/main/java/com/att/authz/cm/service/Code.java new file mode 100644 index 00000000..c29404e2 --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/service/Code.java @@ -0,0 +1,46 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.service;
+
+import com.att.authz.cm.facade.Facade1_0;
+import com.att.authz.env.AuthzTrans;
+import com.att.cssa.rserv.HttpCode;
+
+public abstract class Code extends HttpCode<AuthzTrans,Facade1_0> implements Cloneable {
+
+ public Code(CertManAPI 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/authz-certman/src/main/java/com/att/authz/cm/validation/Validator.java b/authz-certman/src/main/java/com/att/authz/cm/validation/Validator.java new file mode 100644 index 00000000..85163f09 --- /dev/null +++ b/authz-certman/src/main/java/com/att/authz/cm/validation/Validator.java @@ -0,0 +1,166 @@ +/*******************************************************************************
+ * ============LICENSE_START====================================================
+ * * org.onap.aai
+ * * ===========================================================================
+ * * Copyright © 2017 AT&T Intellectual Property. All rights reserved.
+ * * Copyright © 2017 Amdocs
+ * * ===========================================================================
+ * * 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====================================================
+ * *
+ * * ECOMP is a trademark and service mark of AT&T Intellectual Property.
+ * *
+ ******************************************************************************/
+package com.att.authz.cm.validation;
+
+import java.util.List;
+
+import com.att.authz.layer.Result;
+import com.att.dao.aaf.cass.ArtiDAO;
+import com.att.dao.aaf.cass.ArtiDAO.Data;
+
+/**
+ * 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.
+ *
+ */
+public class 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 ";
+ private StringBuilder msgs;
+
+ public Validator nullOrBlank(String name, String str) {
+ if(str==null) {
+ msg(name + IS_NULL);
+ } else if(str.length()==0) {
+ msg(name + " is blank.");
+ }
+ return this;
+ }
+
+ private void msg(String ... strs) {
+ if(msgs==null) {
+ msgs=new StringBuilder();
+ }
+ for(String str : strs) {
+ msgs.append(str);
+ }
+ msgs.append('\n');
+ }
+
+ public boolean err() {
+ return msgs!=null;
+ }
+
+ public String errs() {
+ return msgs.toString();
+ }
+
+ public Validator notOK(Result<?> res) {
+ if(res==null) {
+ msgs.append("Result object is blank");
+ } else if(res.notOK()) {
+ msgs.append(res.getClass().getSimpleName() + " is not OK");
+ }
+ return this;
+ }
+
+ public Validator isNull(String name, Object obj) {
+ if(obj==null) {
+ msg(name + IS_NULL);
+ }
+ return this;
+ }
+
+ public Validator 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 Validator 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 Validator 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 Validator keys(ArtiDAO.Data add) {
+ if(add==null) {
+ msg("Artifact is null.");
+ } else {
+ nullOrBlank(MECHID, add.mechid);
+ nullOrBlank(MACHINE, add.machine);
+ }
+ return this;
+ }
+
+ private Validator 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;
+ }
+
+}
|