From bd890c575163e4d87ac24198b9c68a39cf4bbc4d Mon Sep 17 00:00:00 2001 From: sg481n Date: Mon, 28 Aug 2017 12:11:35 -0400 Subject: Update project structure to org.onap.aaf Update project structure of authz module in aaf from com.att to org.onap.aaf and add distribution management and repositories. Issue-id: AAF-21 Change-Id: Ia2486954e99f2bd60f18122ed60d32d5590781e9 Signed-off-by: sg481n --- authz-certman/pom.xml | 208 +++++++++ authz-certman/src/main/config/certman.props | 25 + authz-certman/src/main/config/log4j.properties | 78 ++++ .../src/main/config/lrm-authz-certman.xml | 82 ++++ .../org/onap/aaf/authz/cm/api/API_Artifact.java | 130 ++++++ .../java/org/onap/aaf/authz/cm/api/API_Cert.java | 100 ++++ .../main/java/org/onap/aaf/authz/cm/ca/AppCA.java | 356 ++++++++++++++ .../src/main/java/org/onap/aaf/authz/cm/ca/CA.java | 84 ++++ .../main/java/org/onap/aaf/authz/cm/ca/DevlCA.java | 226 +++++++++ .../java/org/onap/aaf/authz/cm/cert/BCFactory.java | 168 +++++++ .../java/org/onap/aaf/authz/cm/cert/CSRMeta.java | 329 +++++++++++++ .../org/onap/aaf/authz/cm/cert/StandardFields.java | 29 ++ .../java/org/onap/aaf/authz/cm/data/CertDrop.java | 27 ++ .../java/org/onap/aaf/authz/cm/data/CertRenew.java | 27 ++ .../java/org/onap/aaf/authz/cm/data/CertReq.java | 51 ++ .../java/org/onap/aaf/authz/cm/data/CertResp.java | 66 +++ .../java/org/onap/aaf/authz/cm/facade/Facade.java | 161 +++++++ .../org/onap/aaf/authz/cm/facade/Facade1_0.java | 47 ++ .../onap/aaf/authz/cm/facade/FacadeFactory.java | 43 ++ .../org/onap/aaf/authz/cm/facade/FacadeImpl.java | 493 ++++++++++++++++++++ .../java/org/onap/aaf/authz/cm/mapper/Mapper.java | 52 +++ .../org/onap/aaf/authz/cm/mapper/Mapper1_0.java | 246 ++++++++++ .../org/onap/aaf/authz/cm/service/CMService.java | 515 +++++++++++++++++++++ .../org/onap/aaf/authz/cm/service/CertManAPI.java | 285 ++++++++++++ .../java/org/onap/aaf/authz/cm/service/Code.java | 45 ++ .../onap/aaf/authz/cm/validation/Validator.java | 165 +++++++ .../org/onap/aaf/authz/cm/api/JU_API_Artifact.java | 108 +++++ .../org/onap/aaf/authz/cm/api/JU_API_Cert.java | 108 +++++ .../java/org/onap/aaf/authz/cm/ca/JU_AppCA.java | 287 ++++++++++++ .../java/org/onap/aaf/authz/cm/ca/JU_DevlCA.java | 287 ++++++++++++ .../org/onap/aaf/authz/cm/cert/JU_BCFactory.java | 132 ++++++ .../org/onap/aaf/authz/cm/cert/JU_CSRMeta.java | 96 ++++ .../org/onap/aaf/authz/cm/data/JU_CertReq.java | 88 ++++ .../onap/aaf/authz/cm/facade/JU_FacadeImpl.java | 195 ++++++++ .../onap/aaf/authz/cm/validation/JU_Validator.java | 100 ++++ 35 files changed, 5439 insertions(+) create mode 100644 authz-certman/pom.xml create mode 100644 authz-certman/src/main/config/certman.props create mode 100644 authz-certman/src/main/config/log4j.properties create mode 100644 authz-certman/src/main/config/lrm-authz-certman.xml create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/api/API_Artifact.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/api/API_Cert.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/ca/AppCA.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/ca/CA.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/ca/DevlCA.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/cert/BCFactory.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/cert/CSRMeta.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/cert/StandardFields.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/data/CertDrop.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/data/CertRenew.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/data/CertReq.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/data/CertResp.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/facade/Facade.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/facade/Facade1_0.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/facade/FacadeFactory.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/facade/FacadeImpl.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/mapper/Mapper.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/mapper/Mapper1_0.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/service/CMService.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/service/CertManAPI.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/service/Code.java create mode 100644 authz-certman/src/main/java/org/onap/aaf/authz/cm/validation/Validator.java create mode 100644 authz-certman/src/test/java/org/onap/aaf/authz/cm/api/JU_API_Artifact.java create mode 100644 authz-certman/src/test/java/org/onap/aaf/authz/cm/api/JU_API_Cert.java create mode 100644 authz-certman/src/test/java/org/onap/aaf/authz/cm/ca/JU_AppCA.java create mode 100644 authz-certman/src/test/java/org/onap/aaf/authz/cm/ca/JU_DevlCA.java create mode 100644 authz-certman/src/test/java/org/onap/aaf/authz/cm/cert/JU_BCFactory.java create mode 100644 authz-certman/src/test/java/org/onap/aaf/authz/cm/cert/JU_CSRMeta.java create mode 100644 authz-certman/src/test/java/org/onap/aaf/authz/cm/data/JU_CertReq.java create mode 100644 authz-certman/src/test/java/org/onap/aaf/authz/cm/facade/JU_FacadeImpl.java create mode 100644 authz-certman/src/test/java/org/onap/aaf/authz/cm/validation/JU_Validator.java (limited to 'authz-certman') diff --git a/authz-certman/pom.xml b/authz-certman/pom.xml new file mode 100644 index 00000000..3579e1b0 --- /dev/null +++ b/authz-certman/pom.xml @@ -0,0 +1,208 @@ + + + + 4.0.0 + + org.onap.aaf.authz + parent + 1.0.0-SNAPSHOT + ../pom.xml + + + authz-certman + AAF Certification Managmenent + Certificate Manager API + https://github.com/att/AAF + + + BSD License + + + + + + Jonathan Gathman + + ATT + + + + + + + 45 + UTF-8 + 1.0.0-SNAPSHOT + https://nexus.onap.org + /content/repositories/snapshots/ + /content/repositories/releases/ + /content/repositories/staging/ + /content/sites/site/${project.groupId}/${project.artifactId}/${project.version} + + + + + org.onap.aaf.authz + authz-core + + + + org.onap.aaf.authz + authz-cass + + + + + org.onap.aaf.cadi + cadi-aaf + + + + com.google.code.jscep + jscep + 2.4.0 + + + + org.slf4j + slf4j-log4j12 + + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + **/*.class + + + 2.3.1 + + + + + + org.apache.maven.plugins + maven-deploy-plugin + + true + + + + + org.apache.maven.plugins + maven-javadoc-plugin + + false + + + + attach-javadocs + + jar + + + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.7 + true + + ${nexusproxy} + 176c31dfe190a + ecomp-staging + + + + + + + + + + + ecomp-releases + AAF Release Repository + ${nexusproxy}${releaseNexusPath} + + + ecomp-snapshots + AAF Snapshot Repository + ${nexusproxy}${snapshotNexusPath} + + + ecomp-site + dav:${nexusproxy}${sitePath} + + + + + onap-plugin-snapshots + https://nexus.onap.org/content/repositories/snapshots/ + + + + + + central + Maven 2 repository 2 + http://repo2.maven.org/maven2/ + + + onap-jar-snapshots + https://nexus.onap.org/content/repositories/snapshots + + + spring-repo + Spring repo + https://artifacts.alfresco.com/nexus/content/repositories/public/ + + + repository.jboss.org-public + JBoss.org Maven repository + https://repository.jboss.org/nexus/content/groups/public + + + 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..ed7f1ca4 --- /dev/null +++ b/authz-certman/src/main/config/log4j.properties @@ -0,0 +1,78 @@ +#------------------------------------------------------------------------------- +# ============LICENSE_START==================================================== +# * org.onap.aaf +# * =========================================================================== +# * Copyright © 2017 AT&T Intellectual Property. All rights reserved. +# * =========================================================================== +# * Licensed under the Apache License, Version 2.0 (the "License"); +# * you may not use this file except in compliance with the License. +# * You may obtain a copy of the License at +# * +# * http://www.apache.org/licenses/LICENSE-2.0 +# * +# * Unless required by applicable law or agreed to in writing, software +# * distributed under the License is distributed on an "AS IS" BASIS, +# * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# * See the License for the specific language governing permissions and +# * limitations under the License. +# * ============LICENSE_END==================================================== +# * +# * 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..9fd99a3f --- /dev/null +++ b/authz-certman/src/main/config/lrm-authz-certman.xml @@ -0,0 +1,82 @@ + + + + + + com.att.authz._ARTIFACT_ID_ + + _MAJOR_VER_ + _MINOR_VER_ + _PATCH_VER_ + + _ROUTE_OFFER_ + + Java + com.att.authz.cm.service.CertManAPI + + process.workdir + _ROOT_DIR_ + + + jvm.version + 1.8 + + + jvm.args + -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 + + + jvm.classpath + _ROOT_DIR_/etc:_ROOT_DIR_/lib/*: + + + jvm.heap.min + 1024m + + + jvm.heap.max + 2048m + + + start.class + com.att.authz.cm.service.CertManAPI + + + stdout.redirect + _ROOT_DIR_/logs/SystemOut.log + + + stderr.redirect + _ROOT_DIR_/logs/SystemErr.log + + aft + AUTO + 2 + _RESOURCE_MIN_COUNT_ + _RESOURCE_MAX_COUNT_ + _RESOURCE_REGISTRATION_ + com.att.authz:_ARTIFACT_ID_ + _ARTIFACT_VERSION_ + + diff --git a/authz-certman/src/main/java/org/onap/aaf/authz/cm/api/API_Artifact.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/api/API_Artifact.java new file mode 100644 index 00000000..29362df9 --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/api/API_Artifact.java @@ -0,0 +1,130 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.api; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.onap.aaf.authz.cm.mapper.Mapper.API; +import org.onap.aaf.authz.cm.service.CertManAPI; +import org.onap.aaf.authz.cm.service.Code; +import org.onap.aaf.authz.env.AuthzTrans; +import org.onap.aaf.authz.layer.Result; +import org.onap.aaf.cssa.rserv.HttpMethods; + +import com.att.aft.dme2.internal.jetty.http.HttpStatus; + +/** + * 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 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 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 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 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 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 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/org/onap/aaf/authz/cm/api/API_Cert.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/api/API_Cert.java new file mode 100644 index 00000000..d8cdf26c --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/api/API_Cert.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.api; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.onap.aaf.authz.cm.ca.CA; +import org.onap.aaf.authz.cm.mapper.Mapper.API; +import org.onap.aaf.authz.cm.service.CertManAPI; +import org.onap.aaf.authz.cm.service.Code; +import org.onap.aaf.authz.env.AuthzTrans; +import org.onap.aaf.authz.layer.Result; +import org.onap.aaf.cssa.rserv.HttpMethods; + +import com.att.aft.dme2.internal.jetty.http.HttpStatus; +import org.onap.aaf.inno.env.Slot; +import org.onap.aaf.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 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 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/org/onap/aaf/authz/cm/ca/AppCA.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/ca/AppCA.java new file mode 100644 index 00000000..79e7fff2 --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/ca/AppCA.java @@ -0,0 +1,356 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.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 org.onap.aaf.authz.cm.cert.BCFactory; +import org.onap.aaf.authz.cm.cert.CSRMeta; +import org.onap.aaf.authz.cm.cert.StandardFields; +import org.onap.aaf.authz.common.Define; + +import org.onap.aaf.cadi.cm.CertException; +import org.onap.aaf.cadi.cm.Factory; +import org.onap.aaf.cadi.config.Config; +import org.onap.aaf.cadi.routing.GreatCircle; +import org.onap.aaf.inno.env.Env; +import org.onap.aaf.inno.env.TimeTaken; +import org.onap.aaf.inno.env.Trans; +import org.onap.aaf.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 trustCerts = new ArrayList(); + for(Client client : clients) { + CertStore cs = client.getCaCertificate(MS_PROFILE); + + Collection 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;i1 && 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 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{ + /** + * 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 iterator() { + return new Iterator() { + 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/org/onap/aaf/authz/cm/ca/CA.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/ca/CA.java new file mode 100644 index 00000000..97b8a7b4 --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/ca/CA.java @@ -0,0 +1,84 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.ca; + +import java.io.IOException; +import java.security.MessageDigest; +import java.security.cert.X509Certificate; + +import org.onap.aaf.authz.cm.cert.CSRMeta; +import org.onap.aaf.authz.cm.cert.StandardFields; + +import org.onap.aaf.cadi.cm.CertException; +import org.onap.aaf.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/org/onap/aaf/authz/cm/ca/DevlCA.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/ca/DevlCA.java new file mode 100644 index 00000000..8edd287e --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/ca/DevlCA.java @@ -0,0 +1,226 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.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 org.onap.aaf.authz.cm.cert.BCFactory; +import org.onap.aaf.authz.cm.cert.CSRMeta; +import org.onap.aaf.authz.cm.cert.StandardFields; +import org.onap.aaf.authz.common.Define; + +import org.onap.aaf.cadi.cm.CertException; +import org.onap.aaf.cadi.cm.Factory; +import org.onap.aaf.inno.env.Env; +import org.onap.aaf.inno.env.TimeTaken; +import org.onap.aaf.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 certs; + try { + certs = Factory.toX509Certificate(bytes); + } catch (CertificateException e) { + throw new CertException(e); + } + List lTrust = new ArrayList(); + 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 org.onap.aaf.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 lsan = new ArrayList(); + 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/org/onap/aaf/authz/cm/cert/BCFactory.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/cert/BCFactory.java new file mode 100644 index 00000000..54a71f4e --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/cert/BCFactory.java @@ -0,0 +1,168 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.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 org.onap.aaf.authz.cm.ca.CA; +import org.onap.aaf.authz.cm.validation.Validator; + +import org.onap.aaf.cadi.Symm; +import org.onap.aaf.cadi.cm.CertException; +import org.onap.aaf.cadi.cm.Factory; +import org.onap.aaf.inno.env.Env; +import org.onap.aaf.inno.env.TimeTaken; +import org.onap.aaf.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 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/org/onap/aaf/authz/cm/cert/CSRMeta.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/cert/CSRMeta.java new file mode 100644 index 00000000..f71163ef --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/cert/CSRMeta.java @@ -0,0 +1,329 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.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 org.onap.aaf.cadi.cm.CertException; +import org.onap.aaf.cadi.cm.Factory; +import org.onap.aaf.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 sanList = new ArrayList(); + + 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 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/org/onap/aaf/authz/cm/cert/StandardFields.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/cert/StandardFields.java new file mode 100644 index 00000000..f298d0d8 --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/cert/StandardFields.java @@ -0,0 +1,29 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.cert; + +import org.onap.aaf.cadi.cm.CertException; + +public interface StandardFields { + public void set(CSRMeta csr) throws CertException; +} diff --git a/authz-certman/src/main/java/org/onap/aaf/authz/cm/data/CertDrop.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/data/CertDrop.java new file mode 100644 index 00000000..03906c05 --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/data/CertDrop.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.data; + +public class CertDrop { + +} diff --git a/authz-certman/src/main/java/org/onap/aaf/authz/cm/data/CertRenew.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/data/CertRenew.java new file mode 100644 index 00000000..a0eb306e --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/data/CertRenew.java @@ -0,0 +1,27 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.data; + +public class CertRenew { + +} diff --git a/authz-certman/src/main/java/org/onap/aaf/authz/cm/data/CertReq.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/data/CertReq.java new file mode 100644 index 00000000..668686a8 --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/data/CertReq.java @@ -0,0 +1,51 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.data; + +import java.util.List; + +import javax.xml.datatype.XMLGregorianCalendar; + +import org.onap.aaf.authz.cm.ca.CA; +import org.onap.aaf.authz.cm.cert.BCFactory; +import org.onap.aaf.authz.cm.cert.CSRMeta; + +import org.onap.aaf.cadi.cm.CertException; + +public class CertReq { + // These cannot be null + public CA certAuthority; + public String mechid; + public List fqdns; + // Notify + public List 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/org/onap/aaf/authz/cm/data/CertResp.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/data/CertResp.java new file mode 100644 index 00000000..d06f63b4 --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/data/CertResp.java @@ -0,0 +1,66 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.data; + +import java.io.IOException; +import java.security.GeneralSecurityException; +import java.security.KeyPair; +import java.security.cert.X509Certificate; + +import org.onap.aaf.authz.cm.cert.CSRMeta; + +import org.onap.aaf.cadi.cm.CertException; +import org.onap.aaf.cadi.cm.Factory; +import org.onap.aaf.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/org/onap/aaf/authz/cm/facade/Facade.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/facade/Facade.java new file mode 100644 index 00000000..a5c8c650 --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/facade/Facade.java @@ -0,0 +1,161 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.facade; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.onap.aaf.authz.cm.mapper.Mapper; +import org.onap.aaf.authz.env.AuthzTrans; +import org.onap.aaf.authz.layer.Result; + + +/** + * + * + */ +public interface Facade { + +///////////////////// 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 check(AuthzTrans trans, HttpServletResponse resp, String perm) throws IOException; + + /** + * + * @return + */ + public Mapper mapper(); + +///////////////////// STANDARD ELEMENTS ////////////////// + + /** + * + * @param trans + * @param resp + * @param rservlet + * @return + */ + public abstract Result requestCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, boolean withTrust); + + /** + * + * @param trans + * @param req + * @param resp + * @return + */ + public abstract Result renewCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, boolean withTrust); + + /** + * + * @param trans + * @param req + * @param resp + * @return + */ + public abstract Result dropCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp); + + /** + * + * @param trans + * @param req + * @param resp + * @return + */ + Result createArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp); + + /** + * + * @param trans + * @param req + * @param resp + * @return + */ + Result readArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp); + + /** + * + * @param trans + * @param resp + * @param mechid + * @param machine + * @return + */ + Result readArtifacts(AuthzTrans trans, HttpServletResponse resp, String mechid, String machine); + + /** + * + * @param trans + * @param req + * @param resp + * @return + */ + Result updateArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp); + + /** + * + * @param trans + * @param req + * @param resp + * @return + */ + Result deleteArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp); + + /** + * + * @param trans + * @param resp + * @param mechid + * @param machine + * @return + */ + Result deleteArtifacts(AuthzTrans trans, HttpServletResponse resp, String mechid, String machine); + + + +} diff --git a/authz-certman/src/main/java/org/onap/aaf/authz/cm/facade/Facade1_0.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/facade/Facade1_0.java new file mode 100644 index 00000000..525b38a1 --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/facade/Facade1_0.java @@ -0,0 +1,47 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.facade; + +import org.onap.aaf.authz.cm.mapper.Mapper; +import org.onap.aaf.authz.cm.service.CMService; +import org.onap.aaf.authz.cm.service.CertManAPI; + +import org.onap.aaf.inno.env.APIException; +import org.onap.aaf.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 { + public Facade1_0(CertManAPI certman, + CMService service, + Mapper mapper, + Data.TYPE type) throws APIException { + super(certman, service, mapper, type); + } +} diff --git a/authz-certman/src/main/java/org/onap/aaf/authz/cm/facade/FacadeFactory.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/facade/FacadeFactory.java new file mode 100644 index 00000000..0c19837f --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/facade/FacadeFactory.java @@ -0,0 +1,43 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.facade; + +import org.onap.aaf.authz.cm.mapper.Mapper1_0; +import org.onap.aaf.authz.cm.service.CMService; +import org.onap.aaf.authz.cm.service.CertManAPI; +import org.onap.aaf.authz.env.AuthzTrans; + +import org.onap.aaf.inno.env.APIException; +import org.onap.aaf.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/org/onap/aaf/authz/cm/facade/FacadeImpl.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/facade/FacadeImpl.java new file mode 100644 index 00000000..468aacd9 --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/facade/FacadeImpl.java @@ -0,0 +1,493 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.facade; + +import static org.onap.aaf.authz.layer.Result.ERR_ActionNotCompleted; +import static org.onap.aaf.authz.layer.Result.ERR_BadData; +import static org.onap.aaf.authz.layer.Result.ERR_ConflictAlreadyExists; +import static org.onap.aaf.authz.layer.Result.ERR_Denied; +import static org.onap.aaf.authz.layer.Result.ERR_NotFound; +import static org.onap.aaf.authz.layer.Result.ERR_NotImplemented; +import static org.onap.aaf.authz.layer.Result.ERR_Policy; +import static org.onap.aaf.authz.layer.Result.ERR_Security; +import static org.onap.aaf.authz.layer.Result.OK; + +import java.io.IOException; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.onap.aaf.authz.cm.api.API_Cert; +import org.onap.aaf.authz.cm.ca.CA; +import org.onap.aaf.authz.cm.data.CertResp; +import org.onap.aaf.authz.cm.mapper.Mapper; +import org.onap.aaf.authz.cm.mapper.Mapper.API; +import org.onap.aaf.authz.cm.service.CMService; +import org.onap.aaf.authz.cm.service.CertManAPI; +import org.onap.aaf.authz.env.AuthzEnv; +import org.onap.aaf.authz.env.AuthzTrans; +import org.onap.aaf.authz.layer.Result; +import org.onap.aaf.dao.aaf.cass.ArtiDAO; +import org.onap.aaf.dao.aaf.cass.Status; + +import org.onap.aaf.cadi.aaf.AAFPermission; +import org.onap.aaf.inno.env.APIException; +import org.onap.aaf.inno.env.Data; +import org.onap.aaf.inno.env.Env; +import org.onap.aaf.inno.env.Slot; +import org.onap.aaf.inno.env.TimeTaken; +import org.onap.aaf.inno.env.util.Split; +import org.onap.aaf.rosetta.env.RosettaDF; +import org.onap.aaf.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 extends org.onap.aaf.authz.layer.FacadeImpl implements Facade + { + 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 errDF; + private final RosettaDF certRequestDF, certRenewDF, certDropDF; + private final RosettaDF certDF; + private final RosettaDF artiDF; + private Mapper mapper; + private Slot sCertAuth; + private CertManAPI certman; + private final String voidResp; + + public FacadeImpl(CertManAPI certman, + CMService service, + Mapper 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 mapper() { + return mapper; + } + + /* (non-Javadoc) + * @see com.att.authz.facade.AuthzFacade#error(org.onap.aaf.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 check(AuthzTrans trans, HttpServletResponse resp, String perm) throws IOException { + String[] p = Split.split('|',perm); + if(p.length!=3) { + return Result.err(Result.ERR_BadData,"Invalid Perm String"); + } + AAFPermission ap = new AAFPermission(p[0],p[1],p[2]); + if(certman.aafLurPerm.fish(trans.getUserPrincipal(), ap)) { + resp.setContentType(voidResp); + resp.getOutputStream().write(0); + return Result.ok(); + } else { + return Result.err(Result.ERR_Denied,"%s does not have %s",trans.user(),ap.getKey()); + } + } + + /* (non-Javadoc) + * @see com.att.auth.certman.facade.Facade#requestCert(org.onap.aaf.authz.env.AuthzTrans, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) + */ + @Override + public Result requestCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, boolean withTrust) { + TimeTaken tt = trans.start(REQUEST_CERT, Env.SUB|Env.ALWAYS); + try { + REQ request; + try { + Data 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 rcr = service.requestCert(trans,mapper.toReq(trans,request)); + if(rcr.notOK()) { + return Result.err(rcr); + } + + CA certAuth = trans.get(sCertAuth,null); + Result rc = mapper.toCert(trans, rcr, withTrust?certAuth.getTrustChain():null); + switch(rc.status) { + case OK: + RosettaData 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 renewCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, boolean withTrust) { + TimeTaken tt = trans.start(RENEW_CERT, Env.SUB|Env.ALWAYS); + try { + REQ request; + try { + Data 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 rcr = service.renewCert(trans,mapper.toRenew(trans,request)); + Result rc = mapper.toCert(trans, rcr, certman.getTrustChain(certAuth)); + + switch(rc.status) { + case OK: + RosettaData 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 dropCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) { + TimeTaken tt = trans.start(DROP_CERT, Env.SUB|Env.ALWAYS); + try { + REQ request; + try { + Data 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 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 createArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) { + TimeTaken tt = trans.start(CREATE_ARTIFACTS, Env.SUB); + try { + ARTIFACTS arti; + try { + Data 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 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 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 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 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 ra = mapper.fromArtifacts(service.readArtifacts(trans,add)); + if(ra.isOK()) { + RosettaData 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 updateArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) { + TimeTaken tt = trans.start(UPDATE_ARTIFACTS, Env.SUB); + try { + ARTIFACTS arti; + try { + Data 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 deleteArtifacts(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp) { + TimeTaken tt = trans.start(DELETE_ARTIFACTS, Env.SUB); + try { + ARTIFACTS arti; + try { + Data 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 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 deleteArtifacts(AuthzTrans trans, HttpServletResponse resp, String mechid, String machine) { + TimeTaken tt = trans.start(DELETE_ARTIFACTS, Env.SUB); + try { + Result 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/org/onap/aaf/authz/cm/mapper/Mapper.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/mapper/Mapper.java new file mode 100644 index 00000000..a04ac250 --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/mapper/Mapper.java @@ -0,0 +1,52 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.mapper; + +import java.io.IOException; +import java.util.List; + +import org.onap.aaf.authz.cm.data.CertDrop; +import org.onap.aaf.authz.cm.data.CertRenew; +import org.onap.aaf.authz.cm.data.CertReq; +import org.onap.aaf.authz.cm.data.CertResp; +import org.onap.aaf.authz.env.AuthzTrans; +import org.onap.aaf.authz.layer.Result; +import org.onap.aaf.dao.aaf.cass.ArtiDAO; + +public interface Mapper +{ + public enum API{ERROR,VOID,CERT,CERT_REQ,CERT_RENEW,CERT_DROP,ARTIFACTS}; + + public Class getClass(API api); + public A newInstance(API api); + + public ERROR errorFromMessage(StringBuilder holder, String msgID, String text, String... detail); + + public Result toCert(AuthzTrans trans, Result in, String[] trustChain) throws IOException; + public Result toReq(AuthzTrans trans, REQ req); + public Result toRenew(AuthzTrans trans, REQ req); + public Result toDrop(AuthzTrans trans, REQ req); + + public List toArtifact(AuthzTrans trans, ARTIFACTS arti); + public Result fromArtifacts(Result> readArtifactsByMachine); +} diff --git a/authz-certman/src/main/java/org/onap/aaf/authz/cm/mapper/Mapper1_0.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/mapper/Mapper1_0.java new file mode 100644 index 00000000..2cb861c4 --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/mapper/Mapper1_0.java @@ -0,0 +1,246 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.mapper; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import org.onap.aaf.authz.cm.data.CertDrop; +import org.onap.aaf.authz.cm.data.CertRenew; +import org.onap.aaf.authz.cm.data.CertReq; +import org.onap.aaf.authz.cm.data.CertResp; +import org.onap.aaf.authz.cm.validation.Validator; +import org.onap.aaf.authz.env.AuthzTrans; +import org.onap.aaf.authz.layer.Result; +import org.onap.aaf.dao.aaf.cass.ArtiDAO; +import org.onap.aaf.dao.aaf.cass.ArtiDAO.Data; + +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 org.onap.aaf.cadi.aaf.v2_0.AAFCon; +import org.onap.aaf.cadi.util.Vars; + + +public class Mapper1_0 implements Mapper { + + @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 newInstance(API api) { + switch(api) { + case CERT_REQ: return (A) new CertificateRequest(); + case CERT_RENEW: return (A) new CertificateRenew(); + case CERT_DROP: return (A) new CertificateDrop(); + case CERT: return (A) new CertInfo(); + case ARTIFACTS: return (A) new Artifacts(); + case ERROR: return (A)new Error(); + case VOID: return null; + } + return null; + } + + ////////////// Mapping Functions ///////////// + @Override + public Error errorFromMessage(StringBuilder holder, String msgID, String text, String... var) { + Error err = new Error(); + err.setMessageId(msgID); + // AT&T Restful Error Format requires numbers "%" placements + err.setText(Vars.convert(holder, text, var)); + for(String s : var) { + err.getVariables().add(s); + } + return err; + } + + /* (non-Javadoc) + * @see com.att.authz.certman.mapper.Mapper#toCert(org.onap.aaf.authz.env.AuthzTrans, org.onap.aaf.authz.layer.Result) + */ + @Override + public Result toCert(AuthzTrans trans, Result 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(org.onap.aaf.authz.env.AuthzTrans, java.lang.Object) + */ + @Override + public Result 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(org.onap.aaf.authz.env.AuthzTrans, java.lang.Object) + */ + @Override + public Result toRenew(AuthzTrans trans, BaseRequest req) { + return Result.err(Result.ERR_NotImplemented,"Not Implemented... yet"); + } + + /* (non-Javadoc) + * @see com.att.authz.certman.mapper.Mapper#toDrop(org.onap.aaf.authz.env.AuthzTrans, java.lang.Object) + */ + @Override + public Result toDrop(AuthzTrans trans, BaseRequest req) { + return Result.err(Result.ERR_NotImplemented,"Not Implemented... yet"); + } + + /* (non-Javadoc) + * @see org.onap.aaf.authz.cm.mapper.Mapper#toArtifact(org.onap.aaf.authz.env.AuthzTrans, java.lang.Object) + */ + @Override + public List toArtifact(AuthzTrans trans, Artifacts artifacts) { + List ladd = new ArrayList(); + 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 org.onap.aaf.authz.cm.mapper.Mapper#fromArtifacts(org.onap.aaf.authz.layer.Result) + */ + @Override + public Result fromArtifacts(Result> 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/org/onap/aaf/authz/cm/service/CMService.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/service/CMService.java new file mode 100644 index 00000000..9924973c --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/service/CMService.java @@ -0,0 +1,515 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.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 org.onap.aaf.authz.cm.api.API_Cert; +import org.onap.aaf.authz.cm.ca.CA; +import org.onap.aaf.authz.cm.cert.BCFactory; +import org.onap.aaf.authz.cm.cert.CSRMeta; +import org.onap.aaf.authz.cm.data.CertDrop; +import org.onap.aaf.authz.cm.data.CertRenew; +import org.onap.aaf.authz.cm.data.CertReq; +import org.onap.aaf.authz.cm.data.CertResp; +import org.onap.aaf.authz.cm.validation.Validator; +import org.onap.aaf.authz.env.AuthzTrans; +import org.onap.aaf.authz.layer.Result; +import org.onap.aaf.authz.org.Organization; +import org.onap.aaf.authz.org.OrganizationException; +import org.onap.aaf.authz.org.Organization.Identity; +import org.onap.aaf.dao.CassAccess; +import org.onap.aaf.dao.DAO; +import org.onap.aaf.dao.aaf.cass.ArtiDAO; +import org.onap.aaf.dao.aaf.cass.CacheInfoDAO; +import org.onap.aaf.dao.aaf.cass.CertDAO; +import org.onap.aaf.dao.aaf.cass.CredDAO; +import org.onap.aaf.dao.aaf.cass.HistoryDAO; +import org.onap.aaf.dao.aaf.cass.Status; +import org.onap.aaf.dao.aaf.hl.Question; + +import org.onap.aaf.cadi.Hash; +import org.onap.aaf.cadi.aaf.AAFPermission; +import org.onap.aaf.cadi.aaf.v2_0.AAFCon; +import org.onap.aaf.cadi.cm.Factory; +import org.onap.aaf.inno.env.APIException; +import org.onap.aaf.inno.env.Slot; +import org.onap.aaf.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[] daos; + + @SuppressWarnings("unchecked") + public CMService(AuthzTrans trans, CertManAPI certman) throws APIException, IOException { + + sCertAuth = certman.env.slot(API_Cert.CERT_AUTH); + Cluster cluster; + try { + cluster = org.onap.aaf.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[]) 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 dao : daos) { + dao.close(trans); + } + +// sessionFilter.destroy(); + cluster.close(); + } + }); + } + + public Result requestCert(AuthzTrans trans,Result 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 notes = null; + List 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> 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(); + 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();} + 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 renewCert(AuthzTrans trans, Result renew) { + if(renew.isOK()) { + return Result.err(Result.ERR_NotImplemented,"Not implemented yet"); + } else { + return Result.err(renew); + } + } + + public Result dropCert(AuthzTrans trans, Result drop) { + if(drop.isOK()) { + return Result.err(Result.ERR_NotImplemented,"Not implemented yet"); + } else { + return Result.err(drop); + } + } + + /////////////// + // Artifact + ////////////// + public Result createArtifact(AuthzTrans trans, List 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.renewDaysMAX_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 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> 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> 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> 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> rv = artiDAO.readByMachine(trans, machine); + return rv; + } + + public Result updateArtifact(AuthzTrans trans, List 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.renewDaysMAX_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 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> 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 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 deleteArtifact(AuthzTrans trans, List list) { + Validator v = new Validator().artisRequired(list, 1); + if(v.err()) { + return Result.err(Result.ERR_BadData,v.errs()); + } + + try { + boolean partial = false; + Result 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 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/org/onap/aaf/authz/cm/service/CertManAPI.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/service/CertManAPI.java new file mode 100644 index 00000000..e802db21 --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/service/CertManAPI.java @@ -0,0 +1,285 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.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 org.onap.aaf.authz.cm.api.API_Artifact; +import org.onap.aaf.authz.cm.api.API_Cert; +import org.onap.aaf.authz.cm.ca.CA; +import org.onap.aaf.authz.cm.facade.Facade1_0; +import org.onap.aaf.authz.cm.facade.FacadeFactory; +import org.onap.aaf.authz.cm.mapper.Mapper.API; +import org.onap.aaf.authz.env.AuthzEnv; +import org.onap.aaf.authz.env.AuthzTrans; +import org.onap.aaf.authz.env.AuthzTransFilter; +import org.onap.aaf.authz.server.AbsServer; +import org.onap.aaf.cache.Cache; +import org.onap.aaf.cache.Cache.Dated; +import org.onap.aaf.cssa.rserv.HttpMethods; + +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 org.onap.aaf.cadi.Access; +import org.onap.aaf.cadi.Access.Level; +import org.onap.aaf.cadi.CadiException; +import org.onap.aaf.cadi.TrustChecker; +import org.onap.aaf.cadi.aaf.v2_0.AAFAuthn; +import org.onap.aaf.cadi.aaf.v2_0.AAFCon; +import org.onap.aaf.cadi.aaf.v2_0.AAFConHttp; +import org.onap.aaf.cadi.aaf.v2_0.AAFLurPerm; +import org.onap.aaf.cadi.aaf.v2_0.AAFTrustChecker; +import org.onap.aaf.cadi.config.Config; +import org.onap.aaf.inno.env.APIException; +import org.onap.aaf.inno.env.Data; +import org.onap.aaf.inno.env.Env; +import org.onap.aaf.inno.env.Trans; +import org.onap.aaf.inno.env.util.Split; + +public class CertManAPI extends AbsServer { + + private static final String USER_PERMS = "userPerms"; + private static final Map certAuths = new TreeMap(); + 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 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 cac = (Class)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 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 slist = new ArrayList(); + 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 edlist = EnumSet.of( + RequestDispatcherType.REQUEST, + RequestDispatcherType.FORWARD, + RequestDispatcherType.ASYNC + ); + + /////////////////////// + // Apply Filters + /////////////////////// + List flist = new ArrayList(); + + // 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/org/onap/aaf/authz/cm/service/Code.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/service/Code.java new file mode 100644 index 00000000..2e5e389f --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/service/Code.java @@ -0,0 +1,45 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.service; + +import org.onap.aaf.authz.cm.facade.Facade1_0; +import org.onap.aaf.authz.env.AuthzTrans; +import org.onap.aaf.cssa.rserv.HttpCode; + +public abstract class Code extends HttpCode 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 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/org/onap/aaf/authz/cm/validation/Validator.java b/authz-certman/src/main/java/org/onap/aaf/authz/cm/validation/Validator.java new file mode 100644 index 00000000..be9f7285 --- /dev/null +++ b/authz-certman/src/main/java/org/onap/aaf/authz/cm/validation/Validator.java @@ -0,0 +1,165 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.validation; + +import java.util.List; + +import org.onap.aaf.authz.layer.Result; +import org.onap.aaf.dao.aaf.cass.ArtiDAO; +import org.onap.aaf.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 list, int min) { + if(list==null) { + msg(name + IS_NULL); + } else { + if(list.size() list, int min) { + if(list==null) { + msg(ARTIFACT_LIST_IS_NULL); + } else { + if(list.size() list, int min) { + if(list==null) { + msg(ARTIFACT_LIST_IS_NULL); + } else { + if(list.size() getNonCriticalExtensionOIDs() { + + return null; + } + + @Override + public byte[] getExtensionValue(String oid) { + + return null; + } + + @Override + public Set getCriticalExtensionOIDs() { + + return null; + } + + @Override + public void verify(PublicKey key, String sigProvider) throws CertificateException, NoSuchAlgorithmException, + InvalidKeyException, NoSuchProviderException, SignatureException { + + + } + + @Override + public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, + NoSuchProviderException, SignatureException { + + + } + + @Override + public String toString() { + + return null; + } + + @Override + public PublicKey getPublicKey() { + + return null; + } + + @Override + public byte[] getEncoded() throws CertificateEncodingException { + + return null; + } + + @Override + public int getVersion() { + + return 0; + } + + @Override + public byte[] getTBSCertificate() throws CertificateEncodingException { + + return null; + } + + @Override + public boolean[] getSubjectUniqueID() { + + return null; + } + + @Override + public Principal getSubjectDN() { + + return null; + } + + @Override + public byte[] getSignature() { + + return null; + } + + @Override + public byte[] getSigAlgParams() { + + return null; + } + + @Override + public String getSigAlgOID() { + + return null; + } + + @Override + public String getSigAlgName() { + + return null; + } + + @Override + public BigInteger getSerialNumber() { + + return null; + } + + @Override + public Date getNotBefore() { + + return null; + } + + @Override + public Date getNotAfter() { + + return null; + } + + @Override + public boolean[] getKeyUsage() { + + return null; + } + + @Override + public boolean[] getIssuerUniqueID() { + + return null; + } + + @Override + public Principal getIssuerDN() { + + return null; + } + + @Override + public int getBasicConstraints() { + + return 0; + } + + @Override + public void checkValidity(Date date) throws CertificateExpiredException, CertificateNotYetValidException { + + + } + + @Override + public void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException { + + } + }; + when(appCA.sign(Mockito.any(Trans.class), Mockito.any(CSRMeta.class))).thenReturn(cert); + certDAO = mock(CachedCertDAO.class, CALLS_REAL_METHODS); + } + + @Test + public void identity_True() throws CertificateException, IOException, CertException { + assertNotNull(appCA.sign(trans, csrMeta)); + } + + + @Test + public void identityNull() throws CertificateException { + try { + assertNotNull(appCA.sign(null, csrMeta)); + } catch (IOException e) { + + e.printStackTrace(); + } catch (CertException e) { + + e.printStackTrace(); + } + } + + @Test + public void identityBothNull() throws CertificateException { + try { + assertNotNull(appCA.sign(null, null)); + } catch (IOException e) { + + e.printStackTrace(); + } catch (CertException e) { + + e.printStackTrace(); + } + } + +} diff --git a/authz-certman/src/test/java/org/onap/aaf/authz/cm/ca/JU_DevlCA.java b/authz-certman/src/test/java/org/onap/aaf/authz/cm/ca/JU_DevlCA.java new file mode 100644 index 00000000..b859bf72 --- /dev/null +++ b/authz-certman/src/test/java/org/onap/aaf/authz/cm/ca/JU_DevlCA.java @@ -0,0 +1,287 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.ca; + +import static org.mockito.Mockito.CALLS_REAL_METHODS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import static org.junit.Assert.*; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.InvalidKeyException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.Principal; +import java.security.PublicKey; +import java.security.SignatureException; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateExpiredException; +import java.security.cert.CertificateNotYetValidException; +import java.security.cert.X509Certificate; +import java.util.Date; +import java.util.Set; + +import javax.security.auth.x500.X500Principal; +import javax.servlet.http.HttpServletRequest; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.aaf.authz.cm.ca.DevlCA; +import org.onap.aaf.authz.cm.cert.CSRMeta; +import org.onap.aaf.dao.aaf.cached.CachedCertDAO; +import org.onap.aaf.dao.aaf.cass.CertDAO; + +import com.att.aft.dme2.api.http.HttpResponse; +import com.att.aft.dme2.request.HttpRequest; +import org.onap.aaf.cadi.cm.CertException; +import org.onap.aaf.inno.env.Trans; + + +@RunWith(MockitoJUnitRunner.class) +public class JU_DevlCA { + + @Mock + private static CachedCertDAO certDAO; + + @Mock + private static HttpServletRequest req; + + @Mock + private static CSRMeta csrMeta; + + static Trans trans; + + static X509Certificate cert; + static byte [] name = {1,23,4,54,6,56}; + + private static DevlCA devICA; + + @BeforeClass + public static void setUp() throws CertificateException, CertException, IOException { + String str = "core java api"; + byte[] b = str.getBytes(); + Principal prc = new X500Principal("CN=Duke, OU=JavaSoft, O=Sun Microsystems, C=US"); + req = mock(HttpServletRequest.class); + devICA = mock(DevlCA.class); + X509Certificate cert = new X509Certificate() { + + @Override + public boolean hasUnsupportedCriticalExtension() { + return false; + } + + @Override + public Set getNonCriticalExtensionOIDs() { + + return null; + } + + @Override + public byte[] getExtensionValue(String oid) { + + return null; + } + + @Override + public Set getCriticalExtensionOIDs() { + + return null; + } + + @Override + public void verify(PublicKey key, String sigProvider) throws CertificateException, NoSuchAlgorithmException, + InvalidKeyException, NoSuchProviderException, SignatureException { + + + } + + @Override + public void verify(PublicKey key) throws CertificateException, NoSuchAlgorithmException, InvalidKeyException, + NoSuchProviderException, SignatureException { + + + } + + @Override + public String toString() { + + return null; + } + + @Override + public PublicKey getPublicKey() { + + return null; + } + + @Override + public byte[] getEncoded() throws CertificateEncodingException { + + return null; + } + + @Override + public int getVersion() { + + return 0; + } + + @Override + public byte[] getTBSCertificate() throws CertificateEncodingException { + + return null; + } + + @Override + public boolean[] getSubjectUniqueID() { + + return null; + } + + @Override + public Principal getSubjectDN() { + + return null; + } + + @Override + public byte[] getSignature() { + + return null; + } + + @Override + public byte[] getSigAlgParams() { + + return null; + } + + @Override + public String getSigAlgOID() { + + return null; + } + + @Override + public String getSigAlgName() { + + return null; + } + + @Override + public BigInteger getSerialNumber() { + + return null; + } + + @Override + public Date getNotBefore() { + + return null; + } + + @Override + public Date getNotAfter() { + + return null; + } + + @Override + public boolean[] getKeyUsage() { + + return null; + } + + @Override + public boolean[] getIssuerUniqueID() { + + return null; + } + + @Override + public Principal getIssuerDN() { + + return null; + } + + @Override + public int getBasicConstraints() { + + return 0; + } + + @Override + public void checkValidity(Date date) throws CertificateExpiredException, CertificateNotYetValidException { + + + } + + @Override + public void checkValidity() throws CertificateExpiredException, CertificateNotYetValidException { + + } + }; + when(devICA.sign(Mockito.any(Trans.class), Mockito.any(CSRMeta.class))).thenReturn(cert); + certDAO = mock(CachedCertDAO.class, CALLS_REAL_METHODS); + } + + @Test + public void identity_True() throws CertificateException, IOException, CertException { + assertNotNull(devICA.sign(trans, csrMeta)); + } + + + @Test + public void identityNull() throws CertificateException { + try { + assertNotNull(devICA.sign(null, csrMeta)); + } catch (IOException e) { + + e.printStackTrace(); + } catch (CertException e) { + + e.printStackTrace(); + } + } + + @Test + public void identityBothNull() throws CertificateException { + try { + assertNotNull(devICA.sign(null, null)); + } catch (IOException e) { + + e.printStackTrace(); + } catch (CertException e) { + + e.printStackTrace(); + } + } + +} diff --git a/authz-certman/src/test/java/org/onap/aaf/authz/cm/cert/JU_BCFactory.java b/authz-certman/src/test/java/org/onap/aaf/authz/cm/cert/JU_BCFactory.java new file mode 100644 index 00000000..3435d490 --- /dev/null +++ b/authz-certman/src/test/java/org/onap/aaf/authz/cm/cert/JU_BCFactory.java @@ -0,0 +1,132 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.cert; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.security.Key; +import java.security.PrivateKey; +import java.security.PublicKey; + +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.aaf.authz.cm.cert.BCFactory; + +import org.onap.aaf.cadi.cm.CertException; +import org.onap.aaf.inno.env.TimeTaken; +import org.onap.aaf.inno.env.Trans; + +@RunWith(MockitoJUnitRunner.class) +public class JU_BCFactory { + + private static BCFactory bcFactory = new BCFactory(); + + private static BCFactory bcFact; + + private static PrivateKey pk; + + + private static Trans trans; + + + private static PKCS10CertificationRequest req; + + @BeforeClass + public static void setUp() throws IOException { + pk = new XYZKey(); + trans = mock(Trans.class); + req = mock(PKCS10CertificationRequest.class); + when(req.getEncoded()).thenReturn(new byte[1]); + when(trans.start(Mockito.anyString(), Mockito.anyInt())).thenReturn(new TimeTaken(null, 0) { + + @Override + public void output(StringBuilder sb) { + // TODO Auto-generated method stub + + } + }); + bcFact = mock(BCFactory.class); + } + + @Test + public void toStrin() throws OperatorCreationException, IOException, CertException { + assertNotNull(bcFactory.toString(trans, req)); + } + + @Test + public void toStrinMoc() throws OperatorCreationException, IOException, CertException { + assertNotNull(bcFact.toString(trans, req)); + } + + @Rule + public ExpectedException thrown= ExpectedException.none(); + + @Test + public void toCSR() { + try { + assertNotNull(bcFactory.toCSR(trans, new File("/random/path"))); + thrown.expect(FileNotFoundException.class); + } catch (IOException e) { + + e.printStackTrace(); + } + } + +} + +class XYZKey implements Key, PublicKey, PrivateKey { + + int rotValue; + public XYZKey() { + rotValue = 1200213; + } + public String getAlgorithm() { + return "XYZ"; + } + + public String getFormat() { + return "XYZ Special Format"; + } + + public byte[] getEncoded() { + byte b[] = new byte[4]; + b[3] = (byte) ((rotValue << 24) & 0xff); + b[2] = (byte) ((rotValue << 16) & 0xff); + b[1] = (byte) ((rotValue << 8) & 0xff); + b[0] = (byte) ((rotValue << 0) & 0xff); + return b; + } +} diff --git a/authz-certman/src/test/java/org/onap/aaf/authz/cm/cert/JU_CSRMeta.java b/authz-certman/src/test/java/org/onap/aaf/authz/cm/cert/JU_CSRMeta.java new file mode 100644 index 00000000..da6b1984 --- /dev/null +++ b/authz-certman/src/test/java/org/onap/aaf/authz/cm/cert/JU_CSRMeta.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.cert; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; + +import java.io.IOException; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; + +import org.bouncycastle.asn1.x500.X500Name; +import org.bouncycastle.operator.OperatorCreationException; +import org.bouncycastle.pkcs.PKCS10CertificationRequest; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.aaf.authz.cm.cert.CSRMeta; + +import org.onap.aaf.cadi.cm.CertException; +import org.onap.aaf.inno.env.Trans; + +@RunWith(MockitoJUnitRunner.class) +public class JU_CSRMeta { + + private static CSRMeta csrmeta; + private static Trans trans; + private static PKCS10CertificationRequest req; + + @BeforeClass + public static void setUp() { + trans = mock(Trans.class); + csrmeta = new CSRMeta(); + csrmeta.cn("CN"); + csrmeta.email("pupleti@ht.com"); + csrmeta.mechID("HAKJH787"); + csrmeta.o("O"); + csrmeta.l("L"); + csrmeta.st("ST"); + csrmeta.c("C"); + csrmeta.challenge("Challenge"); + csrmeta.san("CA"); + } + + @Test + public void x500Name() throws IOException { + + X500Name x500 = csrmeta.x500Name(); + assertEquals(x500.toString(),"CN=CN,E=pupleti@ht.com,OU=HAKJH787,O=O,L=L,ST=ST,C=C"); + } + + @Test + public void initialConversationCert() throws CertificateException, OperatorCreationException, IOException { + X509Certificate cert = csrmeta.initialConversationCert(trans); + assertEquals(cert.getBasicConstraints(),-1); + } + + @Test + public void generateCSR() throws IOException, CertException { + req = csrmeta.generateCSR(trans); + assertNotNull(req); + } + + @Rule + public ExpectedException thrown= ExpectedException.none(); + + @Test + public void dump() throws IOException, CertException { + req = csrmeta.generateCSR(trans); + csrmeta.dump(req); + } + +} diff --git a/authz-certman/src/test/java/org/onap/aaf/authz/cm/data/JU_CertReq.java b/authz-certman/src/test/java/org/onap/aaf/authz/cm/data/JU_CertReq.java new file mode 100644 index 00000000..3ff3088c --- /dev/null +++ b/authz-certman/src/test/java/org/onap/aaf/authz/cm/data/JU_CertReq.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.data; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.aaf.authz.cm.ca.CA; +import org.onap.aaf.authz.cm.cert.BCFactory; +import org.onap.aaf.authz.cm.cert.CSRMeta; +import org.onap.aaf.authz.cm.cert.StandardFields; +import org.onap.aaf.authz.cm.data.CertReq; + +import org.onap.aaf.cadi.cm.CertException; +import org.onap.aaf.inno.env.Trans; + +@RunWith(MockitoJUnitRunner.class) +public class JU_CertReq { + + private static BCFactory bcFact; + + private static CSRMeta value; + + private static CertReq req; + + @BeforeClass + public static void setUp() { + bcFact = mock(BCFactory.class); + value = mock(CSRMeta.class); + req = mock(CertReq.class); + + } + + @Test + public void getCSRMeta() throws CertException { + //req = new CertReq(); + req.mechid = "1213"; + List fqdnsas = new ArrayList(); + fqdnsas.add("String1"); + List emails = new ArrayList(); + emails.add("pupleti@hotmail.com"); + req.emails = emails; + req.fqdns = fqdnsas; + StandardFields sf = mock(StandardFields.class); + req.certAuthority = new CA("testName", sf, "ALL") { + + @Override + public X509Certificate sign(Trans trans, CSRMeta csrmeta) throws IOException, CertException { + + return null; + } + }; + req.sponsor = "asa@df.co"; + assertNull(req.getCSRMeta()); + } +} diff --git a/authz-certman/src/test/java/org/onap/aaf/authz/cm/facade/JU_FacadeImpl.java b/authz-certman/src/test/java/org/onap/aaf/authz/cm/facade/JU_FacadeImpl.java new file mode 100644 index 00000000..2f305bb4 --- /dev/null +++ b/authz-certman/src/test/java/org/onap/aaf/authz/cm/facade/JU_FacadeImpl.java @@ -0,0 +1,195 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.facade; + +import static org.junit.Assert.*; +import static org.mockito.Mockito.CALLS_REAL_METHODS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.IOException; + +import javax.servlet.ServletOutputStream; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.xml.namespace.QName; +import javax.xml.validation.Schema; + +import org.junit.Before; +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mockito; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.aaf.authz.cm.facade.FacadeImpl; +import org.onap.aaf.authz.cm.mapper.Mapper; +import org.onap.aaf.authz.cm.service.CMService; +import org.onap.aaf.authz.cm.service.CertManAPI; +import org.onap.aaf.authz.env.AuthzEnv; +import org.onap.aaf.authz.env.AuthzTrans; +import org.onap.aaf.authz.layer.Result; + +import org.onap.aaf.cadi.aaf.AAFPermission; +import org.onap.aaf.cadi.aaf.v2_0.AAFLurPerm; +import org.onap.aaf.inno.env.APIException; +import org.onap.aaf.inno.env.Data; +import org.onap.aaf.inno.env.LogTarget; +import org.onap.aaf.inno.env.TimeTaken; +import org.onap.aaf.inno.env.Trans; +import org.onap.aaf.rosetta.env.RosettaDF; +import org.onap.aaf.rosetta.env.RosettaData; + + +@RunWith(MockitoJUnitRunner.class) +public class JU_FacadeImpl { + + private static AuthzTrans trans; + private static HttpServletResponse resp; + private static CertManAPI certman; + private static FacadeImpl hImpl; + private static CMService service; + private Mapper mapper; + private Data.TYPE dataType; + private static AuthzEnv env; + + private static FacadeImpl fImpl; + private static HttpServletRequest req; + + @Before + public void setUp() throws APIException, IOException { + fImpl = mock(FacadeImpl.class); + env = mock(AuthzEnv.class); + resp = mock(HttpServletResponse.class); + req = mock(HttpServletRequest.class); + hImpl = mock(FacadeImpl.class, CALLS_REAL_METHODS); + Result rvd = (Result) mock(Result.class); + trans = mock(AuthzTrans.class); + when(trans.error()).thenReturn(new LogTarget() { + + @Override + public void printf(String fmt, Object... vars) {} + + @Override + public void log(Throwable e, Object... msgs) { + e.getMessage(); + e.printStackTrace(); + msgs.toString(); + + } + + @Override + public void log(Object... msgs) { + } + + @Override + public boolean isLoggable() { + + return false; + } + }); + when(trans.start(Mockito.anyString(), Mockito.anyInt())).thenReturn(new TimeTaken("Now", 1) { + + @Override + public void output(StringBuilder sb) { + + } + }); + when(fImpl.check(Mockito.any(AuthzTrans.class), Mockito.any(HttpServletResponse.class), Mockito.anyString())).thenReturn(rvd); + when(resp.getOutputStream()).thenReturn(new ServletOutputStream() { + + @Override + public void write(int b) throws IOException { + + + } + }); + + } + + @Test + public void check() throws IOException { + AAFPermission ap = new AAFPermission("str1","str3","str2"); + String perms = ap.getInstance(); + assertNotNull(hImpl.check(trans, resp, perms)); + } + + @Test + public void checkNull() throws IOException { + AAFPermission ap = new AAFPermission(null,"Str3","str2"); + String perms = ap.getInstance(); + assertNotNull(hImpl.check(trans, resp, perms)); + } + + @Test + public void checkTwoNull() throws IOException { + AAFPermission ap = new AAFPermission(null,null,"str2"); + String perms = ap.getInstance(); + assertNotNull(fImpl.check(trans, resp, perms)); + } + + @Test + public void checkAllNull() throws IOException { + AAFPermission ap = new AAFPermission(null,null,null); + String perms = ap.getInstance(); + assertNotNull(fImpl.check(trans, resp, perms)); + } + + @Test + public void checkTrans_null() throws IOException { + AAFPermission ap = new AAFPermission("str1","str3","str2"); + String perms = ap.getInstance(); + assertNotNull(hImpl.check(null, resp, perms)); + } + + @Test + public void checkRespNull() throws IOException { + AAFPermission ap = new AAFPermission("str1","str3","str2"); + String perms = ap.getInstance(); + assertNotNull(hImpl.check(trans, null, perms)); + } + + @Test + public void requestCert() { + assertNotNull(hImpl.requestCert(trans, req, resp, true)); + } + + @Test + public void renewCert() { + assertNotNull(hImpl.renewCert(trans, req, resp, true)); + } + + @Test + public void dropCert() { + assertNotNull(hImpl.renewCert(trans, req, resp, true)); + } + + @Test + public void createArtifacts() { + assertNotNull(hImpl.createArtifacts(trans, req, resp)); + } + + @Test + public void readArtifacts() { + assertNotNull(hImpl.readArtifacts(trans, req, resp)); + } +} diff --git a/authz-certman/src/test/java/org/onap/aaf/authz/cm/validation/JU_Validator.java b/authz-certman/src/test/java/org/onap/aaf/authz/cm/validation/JU_Validator.java new file mode 100644 index 00000000..b7600112 --- /dev/null +++ b/authz-certman/src/test/java/org/onap/aaf/authz/cm/validation/JU_Validator.java @@ -0,0 +1,100 @@ +/******************************************************************************* + * ============LICENSE_START==================================================== + * * org.onap.aaf + * * =========================================================================== + * * Copyright © 2017 AT&T Intellectual Property. All rights reserved. + * * =========================================================================== + * * Licensed under the Apache License, Version 2.0 (the "License"); + * * you may not use this file except in compliance with the License. + * * You may obtain a copy of the License at + * * + * * http://www.apache.org/licenses/LICENSE-2.0 + * * + * * Unless required by applicable law or agreed to in writing, software + * * distributed under the License is distributed on an "AS IS" BASIS, + * * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * * See the License for the specific language governing permissions and + * * limitations under the License. + * * ============LICENSE_END==================================================== + * * + * * ECOMP is a trademark and service mark of AT&T Intellectual Property. + * * + ******************************************************************************/ +package org.onap.aaf.authz.cm.validation; + +import static org.junit.Assert.*; + +import java.util.ArrayList; + +import org.junit.BeforeClass; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.runners.MockitoJUnitRunner; +import org.onap.aaf.authz.cm.validation.Validator; +import org.onap.aaf.dao.aaf.cass.ArtiDAO; + +@RunWith(MockitoJUnitRunner.class) +public class JU_Validator { + + private static Validator validator; + + @BeforeClass + public static void setUp() { + validator = new Validator(); + } + + @Test + public void nullCheck() { + assertNotNull(validator.nullOrBlank("TestName", null).errs()); + } + + @Test + public void blankCheck() { + assertNotNull(validator.nullOrBlank("TestName", "").err()); + } + + @Test + public void notOK_null() { + assertNotNull(validator.notOK(null)); + } + + @Test + public void isNullCheck() { + assertNotNull(validator.isNull("TestName", null).errs()); + } + + @Test + public void nullBlankMin() { + assertNotNull(validator.nullBlankMin("TestName", null, 0)); + } + + @Test + public void artistsRequired() { + assertNotNull(validator.artisRequired(null, 0)); + } + + @Test + public void artistRequired() { + assertNotNull(validator.artisRequired(new ArrayList(), -1)); + } + + @Test + public void artistRequired_Null() { + assertNotNull(validator.artisRequired(null, -1)); + } + + @Test + public void artistkeys() { + assertNotNull(validator.artisKeys(new ArrayList(), -1)); + } + + @Test + public void artistKeys_Null() { + assertNotNull(validator.artisKeys(null, -1)); + } + + @Test + public void keys() { + assertNotNull(validator.keys(new ArtiDAO.Data())); + } +} -- cgit 1.2.3-korg