From c060284812fbbc18fcf22eb628c47c251505fe50 Mon Sep 17 00:00:00 2001 From: Instrumental Date: Mon, 2 Jul 2018 09:40:49 -0500 Subject: Update CM to us Local Intermediate Certs Issue-ID: AAF-384 Change-Id: Iefd36c5b9ab8011ac696cb85e74c54edb63cb40a Signed-off-by: Instrumental --- .../src/main/java/org/onap/aaf/auth/cm/ca/CA.java | 31 +- .../main/java/org/onap/aaf/auth/cm/ca/JscepCA.java | 2 +- .../main/java/org/onap/aaf/auth/cm/ca/LocalCA.java | 50 +- .../onap/aaf/auth/cm/ca/X509ChainWithIssuer.java | 24 +- .../java/org/onap/aaf/auth/cm/ca/X509andChain.java | 13 +- .../java/org/onap/aaf/auth/cm/cert/BCFactory.java | 4 +- .../java/org/onap/aaf/auth/cm/cert/CSRMeta.java | 4 +- .../main/java/org/onap/aaf/auth/cm/cert/RDN.java | 2 +- .../java/org/onap/aaf/auth/cm/data/CertReq.java | 2 +- .../java/org/onap/aaf/auth/cm/data/CertResp.java | 13 +- .../org/onap/aaf/auth/cm/facade/FacadeImpl.java | 4 +- .../org/onap/aaf/auth/cm/mapper/Mapper1_0.java | 14 +- .../org/onap/aaf/auth/cm/mapper/Mapper2_0.java | 7 +- .../org/onap/aaf/auth/cm/service/CMService.java | 6 +- .../java/org/onap/aaf/auth/cm/ca/JU_AppCA.java | 3 +- .../org/onap/aaf/auth/cm/cert/JU_BCFactory.java | 2 +- .../org/onap/aaf/auth/cm/test/CertmanTest.java | 2 +- .../org/onap/aaf/auth/env/AuthzTransFilter.java | 3 +- .../java/org/onap/aaf/auth/rserv/TransFilter.java | 3 +- .../onap/aaf/auth/server/JettyServiceStarter.java | 9 +- .../onap/aaf/auth/gui/pages/CMArtifactShow.java | 2 +- .../org/onap/aaf/cadi/aaf/v2_0/AAFConHttp.java | 3 +- .../java/org/onap/aaf/cadi/cm/ArtifactDir.java | 286 ------ .../java/org/onap/aaf/cadi/cm/CertException.java | 45 - .../main/java/org/onap/aaf/cadi/cm/CmAgent.java | 892 ------------------- .../main/java/org/onap/aaf/cadi/cm/Factory.java | 486 ----------- .../java/org/onap/aaf/cadi/cm/PlaceArtifact.java | 32 - .../org/onap/aaf/cadi/cm/PlaceArtifactInFiles.java | 52 -- .../onap/aaf/cadi/cm/PlaceArtifactInKeystore.java | 140 --- .../onap/aaf/cadi/cm/PlaceArtifactOnStream.java | 51 -- .../org/onap/aaf/cadi/cm/PlaceArtifactScripts.java | 157 ---- .../java/org/onap/aaf/cadi/configure/Agent.java | 956 +++++++++++++++++++++ .../org/onap/aaf/cadi/configure/ArtifactDir.java | 288 +++++++ .../org/onap/aaf/cadi/configure/CertException.java | 45 + .../java/org/onap/aaf/cadi/configure/Factory.java | 504 +++++++++++ .../org/onap/aaf/cadi/configure/PlaceArtifact.java | 32 + .../aaf/cadi/configure/PlaceArtifactInFiles.java | 53 ++ .../cadi/configure/PlaceArtifactInKeystore.java | 150 ++++ .../aaf/cadi/configure/PlaceArtifactOnStream.java | 51 ++ .../aaf/cadi/configure/PlaceArtifactScripts.java | 157 ++++ .../org/onap/aaf/cadi/cm/test/JU_ArtifactDir.java | 2 +- .../onap/aaf/cadi/cm/test/JU_CertException.java | 3 +- .../java/org/onap/aaf/cadi/cm/test/JU_CmAgent.java | 20 +- .../java/org/onap/aaf/cadi/cm/test/JU_Factory.java | 13 +- .../aaf/cadi/cm/test/JU_PlaceArtifactInFiles.java | 2 +- .../cadi/cm/test/JU_PlaceArtifactInKeystore.java | 7 +- .../aaf/cadi/cm/test/JU_PlaceArtifactOnStream.java | 3 +- .../aaf/cadi/cm/test/JU_PlaceArtifactScripts.java | 2 +- .../core/src/main/java/org/onap/aaf/cadi/Symm.java | 2 + .../main/java/org/onap/aaf/cadi/config/Config.java | 8 +- .../org/onap/aaf/cadi/config/SecurityInfoC.java | 8 +- .../java/org/onap/aaf/cadi/filter/CadiFilter.java | 3 +- .../org/onap/aaf/cadi/filter/CadiHTTPManip.java | 3 +- .../java/org/onap/aaf/misc/env/util/Split.java | 13 + 54 files changed, 2417 insertions(+), 2252 deletions(-) delete mode 100644 cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/ArtifactDir.java delete mode 100644 cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/CertException.java delete mode 100644 cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/CmAgent.java delete mode 100644 cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/Factory.java delete mode 100644 cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifact.java delete mode 100644 cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifactInFiles.java delete mode 100644 cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifactInKeystore.java delete mode 100644 cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifactOnStream.java delete mode 100644 cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifactScripts.java create mode 100644 cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/Agent.java create mode 100644 cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/ArtifactDir.java create mode 100644 cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/CertException.java create mode 100644 cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/Factory.java create mode 100644 cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifact.java create mode 100644 cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactInFiles.java create mode 100644 cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactInKeystore.java create mode 100644 cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactOnStream.java create mode 100644 cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactScripts.java diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/CA.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/CA.java index ea726480..ac3e1a54 100644 --- a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/CA.java +++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/CA.java @@ -36,7 +36,8 @@ import org.onap.aaf.auth.cm.cert.CSRMeta; import org.onap.aaf.auth.cm.cert.RDN; import org.onap.aaf.cadi.Access; import org.onap.aaf.cadi.Access.Level; -import org.onap.aaf.cadi.cm.CertException; +import org.onap.aaf.cadi.config.Config; +import org.onap.aaf.cadi.configure.CertException; import org.onap.aaf.misc.env.Trans; import org.onap.aaf.misc.env.util.Split; @@ -57,9 +58,9 @@ public abstract class CA { private final String env; private MessageDigest messageDigest; private final String permType; - private Set caIssuerDNs; private final ArrayList idDomains; private String[] trustedCAs; + private String[] caIssuerDNs; private List rdns; @@ -71,7 +72,7 @@ public abstract class CA { if(permType==null) { throw new CertException(CM_CA_PREFIX + name + ".perm_type" + MUST_EXIST_TO_CREATE_CSRS_FOR + caName); } - caIssuerDNs = new HashSet<>(); + caIssuerDNs = Split.splitTrim(':', access.getProperty(Config.CADI_X509_ISSUERS, null)); String tag = CA.CM_CA_PREFIX+caName+CA.CM_CA_BASE_SUBJECT; @@ -112,7 +113,12 @@ public abstract class CA { String trustCas = access.getProperty(CM_TRUST_CAS,null); if(trustCas!=null) { for(String fname : Split.splitTrim(',', trustCas)) { - File crt = new File(data,fname); + File crt; + if(fname.contains("/")) { + crt = new File(fname); + } else { + crt = new File(data,fname); + } if(crt.exists()) { access.printf(Level.INIT, "Loading CA Cert from %s", crt.getAbsolutePath()); bytes = new byte[(int)crt.length()]; @@ -139,7 +145,19 @@ public abstract class CA { } protected void addCaIssuerDN(String issuerDN) { - caIssuerDNs.add(issuerDN); + boolean changed = true; + for(String id : caIssuerDNs) { + if(id.equals(issuerDN)) { + changed = false; + break; + } + } + if(changed) { + String[] newsa = new String[caIssuerDNs.length+1]; + newsa[0]=issuerDN; + System.arraycopy(caIssuerDNs, 0, newsa, 1, caIssuerDNs.length); + caIssuerDNs = newsa; + } } protected synchronized void addTrustedCA(final String crtString) { @@ -161,7 +179,7 @@ public abstract class CA { trustedCAs = temp; } - public Set getCaIssuerDNs() { + public String[] getCaIssuerDNs() { return caIssuerDNs; } @@ -211,4 +229,5 @@ public abstract class CA { public CSRMeta newCSRMeta() { return new CSRMeta(rdns); } + } diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/JscepCA.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/JscepCA.java index ee73dbdc..3f398381 100644 --- a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/JscepCA.java +++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/JscepCA.java @@ -48,7 +48,7 @@ import org.onap.aaf.cadi.Access; import org.onap.aaf.cadi.LocatorException; import org.onap.aaf.cadi.Access.Level; import org.onap.aaf.cadi.Locator.Item; -import org.onap.aaf.cadi.cm.CertException; +import org.onap.aaf.cadi.configure.CertException; import org.onap.aaf.cadi.locator.HotPeerLocator; import org.onap.aaf.misc.env.Env; import org.onap.aaf.misc.env.TimeTaken; diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/LocalCA.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/LocalCA.java index e2287c3b..af2d2f6b 100644 --- a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/LocalCA.java +++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/LocalCA.java @@ -39,6 +39,7 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPublicKey; import java.util.ArrayList; +import java.util.Collections; import java.util.Date; import java.util.GregorianCalendar; import java.util.List; @@ -64,28 +65,33 @@ import org.onap.aaf.auth.cm.cert.RDN; import org.onap.aaf.auth.env.NullTrans; import org.onap.aaf.cadi.Access; import org.onap.aaf.cadi.Access.Level; -import org.onap.aaf.cadi.cm.CertException; -import org.onap.aaf.cadi.cm.Factory; +import org.onap.aaf.cadi.configure.CertException; +import org.onap.aaf.cadi.configure.Factory; import org.onap.aaf.misc.env.Env; import org.onap.aaf.misc.env.TimeTaken; import org.onap.aaf.misc.env.Trans; public class LocalCA extends CA { + private final static BigInteger ONE = new BigInteger("1"); // Extensions private static final KeyPurposeId[] ASN_WebUsage = new KeyPurposeId[] { KeyPurposeId.id_kp_serverAuth, // WebServer - KeyPurposeId.id_kp_clientAuth};// WebClient - + KeyPurposeId.id_kp_clientAuth // WebClient + }; + private final PrivateKey caKey; private final X500Name issuer; private final SecureRandom random = new SecureRandom(); - private byte[] serialish; + private BigInteger serial; private final X509ChainWithIssuer x509cwi; // "Cert" is CACert - + + public LocalCA(Access access, final String name, final String env, final String[][] params) throws IOException, CertException { super(access, name, env); - serialish = new byte[24]; + + serial = new BigInteger(64,random); + if(params.length<1 || params[0].length<2) { throw new IOException("LocalCA expects cm_ca.=org.onap.aaf.auth.cm.ca.LocalCA,[;]+"); } @@ -180,7 +186,9 @@ public class LocalCA extends CA { } X500NameBuilder xnb = new X500NameBuilder(); - for(RDN rnd : RDN.parse(',', x509cwi.getIssuerDN())) { + List rp = RDN.parse(',', x509cwi.getIssuerDN()); + Collections.reverse(rp); + for(RDN rnd : rp) { xnb.addRDN(rnd.aoi,rnd.value); } issuer = xnb.build(); @@ -201,9 +209,10 @@ public class LocalCA extends CA { TimeTaken tt = trans.start("Create/Sign Cert",Env.SUB); try { BigInteger bi; - synchronized(serialish) { - random.nextBytes(serialish); - bi = new BigInteger(serialish); + + synchronized(ONE) { + bi = serial; + serial = serial.add(ONE); } RSAPublicKey rpk = (RSAPublicKey)csrmeta.keypair(trans).getPublic(); @@ -225,20 +234,23 @@ public class LocalCA extends CA { JcaX509ExtensionUtils extUtils = new JcaX509ExtensionUtils(); xcb.addExtension(Extension.basicConstraints, - false, new BasicConstraints(false)) + false, new BasicConstraints(false + )) .addExtension(Extension.keyUsage, true, new KeyUsage(KeyUsage.digitalSignature - | KeyUsage.keyEncipherment)) + | KeyUsage.keyEncipherment + | KeyUsage.nonRepudiation)) .addExtension(Extension.extendedKeyUsage, true, new ExtendedKeyUsage(ASN_WebUsage)) - .addExtension(Extension.authorityKeyIdentifier, - false, extUtils.createAuthorityKeyIdentifier(x509cwi.cert)) - .addExtension(Extension.subjectKeyIdentifier, - false, extUtils.createSubjectKeyIdentifier(x509cwi.cert.getPublicKey())) + false, extUtils.createAuthorityKeyIdentifier(x509cwi.cert)) + .addExtension(Extension.subjectKeyIdentifier, + false, extUtils.createSubjectKeyIdentifier(rpk)) .addExtension(Extension.subjectAlternativeName, false, new GeneralNames(sans)) - ; +// .addExtension(MiscObjectIdentifiers.netscape, true, new NetscapeCertType( +// NetscapeCertType.sslClient|NetscapeCertType.sslClient)) + ; x509 = new JcaX509CertificateConverter().getCertificate( xcb.build(BCFactory.contentSigner(caKey))); @@ -248,7 +260,7 @@ public class LocalCA extends CA { tt.done(); } - return new X509ChainWithIssuer(x509cwi,x509); + return new X509andChain(x509,x509cwi.trustChain); } } diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/X509ChainWithIssuer.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/X509ChainWithIssuer.java index 6ba5a37f..e31b9988 100644 --- a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/X509ChainWithIssuer.java +++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/X509ChainWithIssuer.java @@ -29,13 +29,14 @@ import java.security.cert.X509Certificate; import java.util.Collection; import java.util.List; -import org.onap.aaf.cadi.cm.CertException; -import org.onap.aaf.cadi.cm.Factory; +import org.onap.aaf.cadi.configure.CertException; +import org.onap.aaf.cadi.configure.Factory; public class X509ChainWithIssuer extends X509andChain { private String issuerDN; + public X509Certificate caX509; - public X509ChainWithIssuer(X509ChainWithIssuer orig, X509Certificate x509) { + public X509ChainWithIssuer(X509ChainWithIssuer orig, X509Certificate x509) throws IOException, CertException { super(x509,orig.trustChain); issuerDN=orig.issuerDN; } @@ -48,7 +49,8 @@ public class X509ChainWithIssuer extends X509andChain { if(rdr==null) { // cover for badly formed array continue; } - byte[] bytes = Factory.decode(rdr); + + byte[] bytes = Factory.decode(rdr,null); try { certs = Factory.toX509Certificate(bytes); } catch (CertificateException e) { @@ -62,24 +64,24 @@ public class X509ChainWithIssuer extends X509andChain { } if(cert==null) { // first in Trust Chain issuerDN = subject.toString(); + cert=x509; // adding each time makes sure last one is signer. } addTrustChainEntry(x509); - cert=x509; // adding each time makes sure last one is signer. } } } public X509ChainWithIssuer(Certificate[] certs) throws IOException, CertException { X509Certificate x509; - for(Certificate c : certs) { - x509=(X509Certificate)c; + for(int i=certs.length-1; i>=0; --i) { + x509=(X509Certificate)certs[i]; Principal subject = x509.getSubjectDN(); if(subject!=null) { - if(cert==null) { // first in Trust Chain - issuerDN= subject.toString(); - } addTrustChainEntry(x509); - cert=x509; // adding each time makes sure last one is signer. + if(i==0) { // last one is signer + cert=x509; + issuerDN= subject.toString(); + } } } } diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/X509andChain.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/X509andChain.java index 46a6393a..5141cc62 100644 --- a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/X509andChain.java +++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/ca/X509andChain.java @@ -25,8 +25,8 @@ import java.security.cert.X509Certificate; import java.util.List; import org.onap.aaf.auth.env.NullTrans; -import org.onap.aaf.cadi.cm.CertException; -import org.onap.aaf.cadi.cm.Factory; +import org.onap.aaf.cadi.configure.CertException; +import org.onap.aaf.cadi.configure.Factory; /** @@ -45,14 +45,14 @@ public class X509andChain { trustChain = null; } - public X509andChain(X509Certificate cert, String[] trustChain) { + public X509andChain(X509Certificate cert, String[] tc) throws IOException, CertException { this.cert = cert; - this.trustChain = trustChain; + trustChain=tc; } - public X509andChain(X509Certificate cert, List chain) { + public X509andChain(X509Certificate cert, List chain) throws IOException, CertException { this.cert = cert; - trustChain = new String[chain.size()]; + trustChain = new String[chain.size()+1]; chain.toArray(trustChain); } @@ -67,6 +67,7 @@ public class X509andChain { trustChain=temp; } } + public X509Certificate getX509() { return cert; diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/BCFactory.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/BCFactory.java index 7f4590f3..70ddd438 100644 --- a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/BCFactory.java +++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/BCFactory.java @@ -37,8 +37,8 @@ import org.bouncycastle.pkcs.PKCS10CertificationRequest; import org.onap.aaf.auth.cm.ca.CA; import org.onap.aaf.auth.cm.validation.CertmanValidator; import org.onap.aaf.cadi.Symm; -import org.onap.aaf.cadi.cm.CertException; -import org.onap.aaf.cadi.cm.Factory; +import org.onap.aaf.cadi.configure.CertException; +import org.onap.aaf.cadi.configure.Factory; import org.onap.aaf.misc.env.Env; import org.onap.aaf.misc.env.TimeTaken; import org.onap.aaf.misc.env.Trans; diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/CSRMeta.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/CSRMeta.java index 2b763f7f..7d417d5f 100644 --- a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/CSRMeta.java +++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/CSRMeta.java @@ -49,8 +49,8 @@ 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.cadi.configure.CertException; +import org.onap.aaf.cadi.configure.Factory; import org.onap.aaf.misc.env.Trans; public class CSRMeta { diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/RDN.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/RDN.java index 5b55f1ca..564a4b5d 100644 --- a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/RDN.java +++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/cert/RDN.java @@ -25,7 +25,7 @@ import java.util.List; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.x500.style.BCStyle; -import org.onap.aaf.cadi.cm.CertException; +import org.onap.aaf.cadi.configure.CertException; import org.onap.aaf.cadi.util.Split; public class RDN { diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertReq.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertReq.java index aa0b9c26..d960945c 100644 --- a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertReq.java +++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertReq.java @@ -28,7 +28,7 @@ import javax.xml.datatype.XMLGregorianCalendar; import org.onap.aaf.auth.cm.ca.CA; import org.onap.aaf.auth.cm.cert.BCFactory; import org.onap.aaf.auth.cm.cert.CSRMeta; -import org.onap.aaf.cadi.cm.CertException; +import org.onap.aaf.cadi.configure.CertException; public class CertReq { // These cannot be null diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertResp.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertResp.java index 595025e7..970bfb85 100644 --- a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertResp.java +++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/data/CertResp.java @@ -25,12 +25,11 @@ import java.io.IOException; import java.security.GeneralSecurityException; import java.security.KeyPair; import java.security.cert.X509Certificate; -import java.util.Set; import org.onap.aaf.auth.cm.ca.CA; import org.onap.aaf.auth.cm.cert.CSRMeta; -import org.onap.aaf.cadi.cm.CertException; -import org.onap.aaf.cadi.cm.Factory; +import org.onap.aaf.cadi.configure.CertException; +import org.onap.aaf.cadi.configure.Factory; import org.onap.aaf.misc.env.Trans; public class CertResp { @@ -40,17 +39,15 @@ public class CertResp { private String privateKey, certString; private String[] trustChain; - private String[] trustCAs; private String[] notes; - public CertResp(Trans trans, CA ca, X509Certificate x509, CSRMeta csrMeta, String[] trustChain, String[] trustCAs, String[] notes) throws IOException, GeneralSecurityException, CertException { + public CertResp(Trans trans, CA ca, X509Certificate x509, CSRMeta csrMeta, String[] trustChain, String[] notes) throws IOException, GeneralSecurityException, CertException { keyPair = csrMeta.keypair(trans); privateKey = Factory.toString(trans, keyPair.getPrivate()); certString = Factory.toString(trans,x509); challenge=csrMeta.challenge(); this.ca = ca; this.trustChain = trustChain; - this.trustCAs = trustCAs; this.notes = notes; } @@ -76,7 +73,7 @@ public class CertResp { return notes; } - public Set caIssuerDNs() { + public String[] caIssuerDNs() { return ca.getCaIssuerDNs(); } @@ -89,6 +86,6 @@ public class CertResp { } public String[] trustCAs() { - return trustCAs; + return ca.getTrustedCAs(); } } diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/facade/FacadeImpl.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/facade/FacadeImpl.java index 0598ee60..51a905a4 100644 --- a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/facade/FacadeImpl.java +++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/facade/FacadeImpl.java @@ -58,8 +58,8 @@ import org.onap.aaf.auth.env.AuthzEnv; import org.onap.aaf.auth.env.AuthzTrans; import org.onap.aaf.auth.layer.Result; import org.onap.aaf.cadi.aaf.AAFPermission; -import org.onap.aaf.cadi.cm.CertException; -import org.onap.aaf.cadi.cm.Factory; +import org.onap.aaf.cadi.configure.CertException; +import org.onap.aaf.cadi.configure.Factory; import org.onap.aaf.misc.env.APIException; import org.onap.aaf.misc.env.Data; import org.onap.aaf.misc.env.Env; diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper1_0.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper1_0.java index 16517c95..c06734f4 100644 --- a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper1_0.java +++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper1_0.java @@ -31,8 +31,8 @@ import org.onap.aaf.auth.cm.data.CertReq; import org.onap.aaf.auth.cm.data.CertResp; import org.onap.aaf.auth.cm.validation.CertmanValidator; import org.onap.aaf.auth.dao.cass.ArtiDAO; -import org.onap.aaf.auth.dao.cass.CertDAO; import org.onap.aaf.auth.dao.cass.ArtiDAO.Data; +import org.onap.aaf.auth.dao.cass.CertDAO; import org.onap.aaf.auth.env.AuthzTrans; import org.onap.aaf.auth.layer.Result; import org.onap.aaf.cadi.util.FQI; @@ -108,7 +108,9 @@ public class Mapper1_0 implements Mapper { if((value=cin.challenge())!=null) { cout.setChallenge(value); } + // In Version 1, Cert is always first cout.getCerts().add(cin.asCertString()); + // Follow with Trust Chain if(cin.trustChain()!=null) { for(String c : cin.trustChain()) { if(c!=null) { @@ -116,12 +118,15 @@ public class Mapper1_0 implements Mapper { } } } + // Adding all the Certs in one response is a mistake. Makes it very hard for Agent to setup // Certs in keystore versus Truststore. Separate in Version 2_0 if(cin.trustCAs()!=null) { for(String c : cin.trustCAs()) { if(c!=null) { - cout.getCerts().add(c); + if(!cout.getCerts().contains(c)) { + cout.getCerts().add(c); + } } } } @@ -138,7 +143,10 @@ public class Mapper1_0 implements Mapper { } cout.setNotes(sb.toString()); } - cout.getCaIssuerDNs().addAll(cin.caIssuerDNs()); + List caIssuerDNs = cout.getCaIssuerDNs(); + for(String s : cin.caIssuerDNs()) { + caIssuerDNs.add(s); + } cout.setEnv(cin.env()); return Result.ok(cout); diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper2_0.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper2_0.java index 13123bdf..76f7d9be 100644 --- a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper2_0.java +++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/mapper/Mapper2_0.java @@ -127,7 +127,12 @@ public class Mapper2_0 implements Mapper { } cout.setNotes(sb.toString()); } - cout.getCaIssuerDNs().addAll(cin.caIssuerDNs()); + + List caIssuerDNs = cout.getCaIssuerDNs(); + for(String s : cin.caIssuerDNs()) { + caIssuerDNs.add(s); + } + cout.setEnv(cin.env()); return Result.ok(cout); } else { diff --git a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/service/CMService.java b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/service/CMService.java index 4ef5472a..8d39f540 100644 --- a/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/service/CMService.java +++ b/auth/auth-certman/src/main/java/org/onap/aaf/auth/cm/service/CMService.java @@ -59,7 +59,7 @@ import org.onap.aaf.auth.org.Organization.Identity; import org.onap.aaf.auth.org.OrganizationException; import org.onap.aaf.cadi.Hash; import org.onap.aaf.cadi.aaf.AAFPermission; -import org.onap.aaf.cadi.cm.Factory; +import org.onap.aaf.cadi.configure.Factory; import org.onap.aaf.cadi.util.FQI; import org.onap.aaf.misc.env.APIException; import org.onap.aaf.misc.env.util.Chrono; @@ -317,7 +317,7 @@ public class CMService { crdd.type = CredDAO.CERT_SHA256_RSA; credDAO.create(trans, crdd); - CertResp cr = new CertResp(trans, ca, x509, csrMeta, x509ac.getTrustChain(), ca.getTrustedCAs(), compileNotes(notes)); + CertResp cr = new CertResp(trans, ca, x509, csrMeta, x509ac.getTrustChain(),compileNotes(notes)); return Result.ok(cr); } catch (Exception e) { trans.error().log(e); @@ -398,7 +398,7 @@ public class CMService { cdd.x509=Factory.toString(trans, x509); certDAO.create(trans, cdd); - CertResp cr = new CertResp(trans, ca, x509, csrMeta, x509ac.getTrustChain(), ca.getTrustedCAs(), compileNotes(null)); + CertResp cr = new CertResp(trans, ca, x509, csrMeta, x509ac.getTrustChain(), compileNotes(null)); return Result.ok(cr); } catch (Exception e) { trans.error().log(e); diff --git a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/ca/JU_AppCA.java b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/ca/JU_AppCA.java index f6d5cab1..d81ea9bc 100644 --- a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/ca/JU_AppCA.java +++ b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/ca/JU_AppCA.java @@ -52,10 +52,9 @@ import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; -import org.onap.aaf.auth.cm.ca.CA; import org.onap.aaf.auth.cm.cert.CSRMeta; import org.onap.aaf.auth.dao.cached.CachedCertDAO; -import org.onap.aaf.cadi.cm.CertException; +import org.onap.aaf.cadi.configure.CertException; import org.onap.aaf.misc.env.Trans; //TODO: Gabe [JUnit] Import does not exist diff --git a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/cert/JU_BCFactory.java b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/cert/JU_BCFactory.java index 856d09c2..337bc9ed 100644 --- a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/cert/JU_BCFactory.java +++ b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/cert/JU_BCFactory.java @@ -41,7 +41,7 @@ import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; -import org.onap.aaf.cadi.cm.CertException; +import org.onap.aaf.cadi.configure.CertException; import org.onap.aaf.misc.env.TimeTaken; import org.onap.aaf.misc.env.Trans; diff --git a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/test/CertmanTest.java b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/test/CertmanTest.java index 7d3f25ca..5ec96f25 100644 --- a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/test/CertmanTest.java +++ b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/test/CertmanTest.java @@ -41,8 +41,8 @@ import org.onap.aaf.cadi.Locator.Item; import org.onap.aaf.cadi.client.Future; import org.onap.aaf.cadi.client.Rcli; import org.onap.aaf.cadi.client.Retryable; -import org.onap.aaf.cadi.cm.Factory; import org.onap.aaf.cadi.config.SecurityInfoC; +import org.onap.aaf.cadi.configure.Factory; import org.onap.aaf.cadi.http.HBasicAuthSS; import org.onap.aaf.cadi.http.HMangr; import org.onap.aaf.cadi.locator.DNSLocator; diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTransFilter.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTransFilter.java index cbc0737c..531e40ab 100644 --- a/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTransFilter.java +++ b/auth/auth-core/src/main/java/org/onap/aaf/auth/env/AuthzTransFilter.java @@ -29,6 +29,7 @@ import javax.servlet.http.HttpServletRequest; import org.onap.aaf.auth.rserv.TransFilter; import org.onap.aaf.cadi.CadiException; import org.onap.aaf.cadi.Connector; +import org.onap.aaf.cadi.LocatorException; import org.onap.aaf.cadi.TrustChecker; import org.onap.aaf.cadi.principal.TaggedPrincipal; import org.onap.aaf.cadi.principal.TrustPrincipal; @@ -48,7 +49,7 @@ public class AuthzTransFilter extends TransFilter { public static final int BUCKETSIZE = 2; - public AuthzTransFilter(AuthzEnv env, Connector con, TrustChecker tc, Object ... additionalTafLurs) throws CadiException { + public AuthzTransFilter(AuthzEnv env, Connector con, TrustChecker tc, Object ... additionalTafLurs) throws CadiException, LocatorException { super(env.access(),con, tc, additionalTafLurs); this.env = env; serviceMetric = new Metric(); diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/TransFilter.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/TransFilter.java index 400c539c..c286e507 100644 --- a/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/TransFilter.java +++ b/auth/auth-core/src/main/java/org/onap/aaf/auth/rserv/TransFilter.java @@ -37,6 +37,7 @@ import org.onap.aaf.cadi.Access; import org.onap.aaf.cadi.CadiException; import org.onap.aaf.cadi.CadiWrap; import org.onap.aaf.cadi.Connector; +import org.onap.aaf.cadi.LocatorException; import org.onap.aaf.cadi.Lur; import org.onap.aaf.cadi.TrustChecker; import org.onap.aaf.cadi.config.Config; @@ -66,7 +67,7 @@ public abstract class TransFilter implements Filter { private final String[] no_authn; - public TransFilter(Access access, Connector con, TrustChecker tc, Object ... additionalTafLurs) throws CadiException { + public TransFilter(Access access, Connector con, TrustChecker tc, Object ... additionalTafLurs) throws CadiException, LocatorException { cadi = new CadiHTTPManip(access, con, tc, additionalTafLurs); String no = access.getProperty(Config.CADI_NOAUTHN, null); if(no!=null) { diff --git a/auth/auth-core/src/main/java/org/onap/aaf/auth/server/JettyServiceStarter.java b/auth/auth-core/src/main/java/org/onap/aaf/auth/server/JettyServiceStarter.java index 4b2ca32c..cefc7a23 100644 --- a/auth/auth-core/src/main/java/org/onap/aaf/auth/server/JettyServiceStarter.java +++ b/auth/auth-core/src/main/java/org/onap/aaf/auth/server/JettyServiceStarter.java @@ -231,11 +231,16 @@ public class JettyServiceStarter ex try { register(service.registrants(port)); access().printf(Level.INIT, "Starting Jetty Service for %s, version %s, on %s://%s:%d", service.app_name,service.app_version,protocol,hostname,port); + server.join(); } catch(Exception e) { access().log(e,"Error registering " + service.app_name); - // Question: Should Registered Services terminate? + String doExit = access().getProperty("cadi_exitOnFailure", "true"); + if (doExit == "true") { + System.exit(1); + } else { + throw e; + } } - server.join(); } private FilterChain buildFilterChain(final AbsService as, final FilterChain doLast) throws CadiException, LocatorException { diff --git a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtifactShow.java b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtifactShow.java index 0ad73649..296e41e1 100644 --- a/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtifactShow.java +++ b/auth/auth-gui/src/main/java/org/onap/aaf/auth/gui/pages/CMArtifactShow.java @@ -47,7 +47,7 @@ import org.onap.aaf.cadi.CadiException; import org.onap.aaf.cadi.client.Future; import org.onap.aaf.cadi.client.Rcli; import org.onap.aaf.cadi.client.Retryable; -import org.onap.aaf.cadi.cm.Factory; +import org.onap.aaf.cadi.configure.Factory; import org.onap.aaf.cadi.util.FQI; import org.onap.aaf.misc.env.APIException; import org.onap.aaf.misc.env.Env; diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AAFConHttp.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AAFConHttp.java index 7237cb5f..9fc38d9f 100644 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AAFConHttp.java +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/aaf/v2_0/AAFConHttp.java @@ -70,8 +70,9 @@ public class AAFConHttp extends AAFCon { } catch (IOException /*| GeneralSecurityException*/ e) { throw new CadiException(e); } + } else { + throw new CadiException("No IDs (" + Config.CADI_ALIAS + " or " + Config.AAF_APPID + ") have been identified."); } - return null; } public AAFConHttp(Access access, String tag) throws APIException, CadiException, LocatorException { diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/ArtifactDir.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/ArtifactDir.java deleted file mode 100644 index 7259d68e..00000000 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/ArtifactDir.java +++ /dev/null @@ -1,286 +0,0 @@ -/** - * ============LICENSE_START==================================================== - * org.onap.aaf - * =========================================================================== - * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. - * =========================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END==================================================== - * - */ - -package org.onap.aaf.cadi.cm; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.PrintStream; -import java.io.PrintWriter; -import java.security.KeyStore; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import org.onap.aaf.cadi.CadiException; -import org.onap.aaf.cadi.Symm; -import org.onap.aaf.cadi.config.Config; -import org.onap.aaf.cadi.util.Chmod; -import org.onap.aaf.misc.env.Trans; -import org.onap.aaf.misc.env.util.Chrono; - -import certman.v1_0.Artifacts.Artifact; -import certman.v1_0.CertInfo; - -public abstract class ArtifactDir implements PlaceArtifact { - - protected static final String C_R = "\n"; - protected File dir; - private List encodeds = new ArrayList(); - - private Symm symm; - // This checks for multiple passes of Dir on the same objects. Run clear after done. - protected static Map processed = new HashMap(); - - - /** - * Note: Derived Classes should ALWAYS call "super.place(cert,arti)" first, and - * then "placeProperties(arti)" just after they implement - */ - @Override - public final boolean place(Trans trans, CertInfo certInfo, Artifact arti, String machine) throws CadiException { - validate(arti); - - try { - // Obtain/setup directory as required - dir = new File(arti.getDir()); - if(processed.get("dir")==null) { - if(!dir.exists()) { - Chmod.to755.chmod(dir); - if(!dir.mkdirs()) { - throw new CadiException("Could not create " + dir); - } - } - - // Also place cm_url and Host Name - addProperty(Config.CM_URL,trans.getProperty(Config.CM_URL)); - addProperty(Config.HOSTNAME,machine); - addProperty(Config.AAF_ENV,certInfo.getEnv()); - // Obtain Issuers - boolean first = true; - StringBuilder issuers = new StringBuilder(); - for(String dn : certInfo.getCaIssuerDNs()) { - if(first) { - first=false; - } else { - issuers.append(':'); - } - issuers.append(dn); - } - addProperty(Config.CADI_X509_ISSUERS,issuers.toString()); - } - symm = (Symm)processed.get("symm"); - if(symm==null) { - // CADI Key Gen - File f = new File(dir,arti.getNs() + ".keyfile"); - if(!f.exists()) { - write(f,Chmod.to400,Symm.keygen()); - } - symm = Symm.obtain(f); - - addEncProperty("ChallengePassword", certInfo.getChallenge()); - - processed.put("symm",symm); - } - - _place(trans, certInfo,arti); - - placeProperties(arti); - - processed.put("dir",dir); - - } catch (Exception e) { - throw new CadiException(e); - } - return true; - } - - /** - * Derived Classes implement this instead, so Dir can process first, and write any Properties last - * @param cert - * @param arti - * @return - * @throws CadiException - */ - protected abstract boolean _place(Trans trans, CertInfo certInfo, Artifact arti) throws CadiException; - - protected void addProperty(String tag, String value) throws IOException { - StringBuilder sb = new StringBuilder(); - sb.append(tag); - sb.append('='); - sb.append(value); - encodeds.add(sb.toString()); - } - - protected void addEncProperty(String tag, String value) throws IOException { - StringBuilder sb = new StringBuilder(); - sb.append(tag); - sb.append('='); - sb.append("enc:"); - sb.append(symm.enpass(value)); - encodeds.add(sb.toString()); - } - - protected void write(File f, Chmod c, String ... data) throws IOException { - f.setWritable(true,true); - - FileOutputStream fos = new FileOutputStream(f); - PrintStream ps = new PrintStream(fos); - try { - for(String s : data) { - ps.print(s); - } - } finally { - ps.close(); - c.chmod(f); - } - } - - protected void write(File f, Chmod c, byte[] bytes) throws IOException { - f.setWritable(true,true); - - FileOutputStream fos = new FileOutputStream(f); - try { - fos.write(bytes); - } finally { - fos.close(); - c.chmod(f); - } - } - - protected void write(File f, Chmod c, KeyStore ks, char[] pass ) throws IOException, CadiException { - f.setWritable(true,true); - - FileOutputStream fos = new FileOutputStream(f); - try { - ks.store(fos, pass); - } catch (Exception e) { - throw new CadiException(e); - } finally { - fos.close(); - c.chmod(f); - } - } - - - private void validate(Artifact a) throws CadiException { - StringBuilder sb = new StringBuilder(); - if(a.getDir()==null) { - sb.append("File Artifacts require a path"); - } - - if(a.getNs()==null) { - if(sb.length()>0) { - sb.append('\n'); - } - sb.append("File Artifacts require an AAF Namespace"); - } - - if(sb.length()>0) { - throw new CadiException(sb.toString()); - } - } - - private boolean placeProperties(Artifact arti) throws CadiException { - if(encodeds.size()==0) { - return true; - } - boolean first=processed.get("dir")==null; - try { - File f = new File(dir,arti.getNs()+".props"); - if(f.exists()) { - if(first) { - f.delete(); - } else { - f.setWritable(true); - } - } - - // Append if not first - PrintWriter pw = new PrintWriter(new FileWriter(f,!first)); - try { - // Write a Header - if(first) { - for(int i=0;i<60;++i) { - pw.print('#'); - } - pw.println(); - pw.println("# Properties Generated by AT&T Certificate Manager"); - pw.print("# by "); - pw.println(System.getProperty("user.name")); - pw.print("# on "); - pw.println(Chrono.dateStamp()); - pw.println("# @copyright 2016, AT&T"); - for(int i=0;i<60;++i) { - pw.print('#'); - } - pw.println(); - for(String prop : encodeds) { - if( prop.startsWith("cm_") - || prop.startsWith(Config.HOSTNAME) - || prop.startsWith(Config.AAF_ENV)) { - pw.println(prop); - } - } - } - - for(String prop : encodeds) { - if(prop.startsWith("cadi")) { - pw.println(prop); - } - } - } finally { - pw.close(); - } - Chmod.to644.chmod(f); - - if(first) { - // Challenge - f = new File(dir,arti.getNs()+".chal"); - if(f.exists()) { - f.delete(); - } - pw = new PrintWriter(new FileWriter(f)); - try { - for(String prop : encodeds) { - if(prop.startsWith("Challenge")) { - pw.println(prop); - } - } - } finally { - pw.close(); - } - Chmod.to400.chmod(f); - } - } catch(Exception e) { - throw new CadiException(e); - } - return true; - } - - public static void clear() { - processed.clear(); - } - -} diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/CertException.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/CertException.java deleted file mode 100644 index 5c525ff2..00000000 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/CertException.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * ============LICENSE_START==================================================== - * org.onap.aaf - * =========================================================================== - * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. - * =========================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END==================================================== - * - */ - -package org.onap.aaf.cadi.cm; - -public class CertException extends Exception { - - /** - * - */ - private static final long serialVersionUID = 1373028409048516401L; - - public CertException() { - } - - public CertException(String message) { - super(message); - } - - public CertException(Throwable cause) { - super(cause); - } - - public CertException(String message, Throwable cause) { - super(message, cause); - } -} \ No newline at end of file diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/CmAgent.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/CmAgent.java deleted file mode 100644 index a899662b..00000000 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/CmAgent.java +++ /dev/null @@ -1,892 +0,0 @@ -/** - * ============LICENSE_START==================================================== - * org.onap.aaf - * =========================================================================== - * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. - * =========================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END==================================================== - * - */ - -package org.onap.aaf.cadi.cm; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.PrintStream; -import java.net.ConnectException; -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.nio.file.Files; -import java.security.KeyStore; -import java.security.cert.X509Certificate; -import java.util.ArrayDeque; -import java.util.Date; -import java.util.Deque; -import java.util.GregorianCalendar; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Properties; - -import org.onap.aaf.cadi.CadiException; -import org.onap.aaf.cadi.CmdLine; -import org.onap.aaf.cadi.LocatorException; -import org.onap.aaf.cadi.PropAccess; -import org.onap.aaf.cadi.Symm; -import org.onap.aaf.cadi.aaf.client.ErrMessage; -import org.onap.aaf.cadi.aaf.v2_0.AAFCon; -import org.onap.aaf.cadi.aaf.v2_0.AAFConHttp; -import org.onap.aaf.cadi.client.Future; -import org.onap.aaf.cadi.client.Rcli; -import org.onap.aaf.cadi.client.Retryable; -import org.onap.aaf.cadi.config.Config; -import org.onap.aaf.cadi.http.HBasicAuthSS; -import org.onap.aaf.cadi.locator.SingleEndpointLocator; -import org.onap.aaf.cadi.sso.AAFSSO; -import org.onap.aaf.cadi.util.FQI; -import org.onap.aaf.misc.env.APIException; -import org.onap.aaf.misc.env.Data.TYPE; -import org.onap.aaf.misc.env.Env; -import org.onap.aaf.misc.env.TimeTaken; -import org.onap.aaf.misc.env.Trans; -import org.onap.aaf.misc.env.util.Chrono; -import org.onap.aaf.misc.env.util.Split; -import org.onap.aaf.misc.rosetta.env.RosettaDF; -import org.onap.aaf.misc.rosetta.env.RosettaEnv; - -import aaf.v2_0.Perm; -import aaf.v2_0.Perms; -import certman.v1_0.Artifacts; -import certman.v1_0.Artifacts.Artifact; -import certman.v1_0.CertInfo; -import certman.v1_0.CertificateRequest; -import locate.v1_1.Configuration; -import locate.v1_1.Configuration.Props; - -public class CmAgent { - private static final String HASHES = "######################"; - private static final String PRINT = "print"; - private static final String FILE = "file"; - private static final String PKCS12 = "pkcs12"; - private static final String JKS = "jks"; - private static final String SCRIPT="script"; - - private static final String CM_VER = "1.0"; - public static final int PASS_SIZE = 24; - private static int TIMEOUT; - - private static RosettaDF reqDF; - private static RosettaDF certDF; - private static RosettaDF artifactsDF; - private static RosettaDF configDF; - private static RosettaDF permDF; - private static ErrMessage errMsg; - private static Map placeArtifact; - private static RosettaEnv env; - - private static boolean doExit; - - public static void main(String[] args) { - int exitCode = 0; - doExit = true; - try { - AAFSSO aafsso = new AAFSSO(args, new AAFSSO.ProcessArgs() { - @Override - public Properties process(String[] args, Properties props) { - if(args.length>1) { - if(args[0].equals("validate")) { - props.put(Config.CADI_PROP_FILES, args[1]); - } else if (!args[0].equals("genkeypair")) { - props.put("aaf_id", args[1]); - } - } - return props; - } - }); - if(aafsso.loginOnly()) { - aafsso.setLogDefault(); - aafsso.writeFiles(); - System.out.println("AAF SSO information created in ~/.aaf"); - } else { - PropAccess access = aafsso.access(); - env = new RosettaEnv(access.getProperties()); - Deque cmds = new ArrayDeque(); - for(String p : args) { - if("-noexit".equalsIgnoreCase(p)) { - doExit = false; - } else if(p.indexOf('=') < 0) { - cmds.add(p); - } - } - - if(cmds.size()==0) { - aafsso.setLogDefault(); - // NOTE: CHANGE IN CMDS should be reflected in AAFSSO constructor, to get FQI->aaf-id or not - System.out.println("Usage: java -jar cmd []*"); - System.out.println(" create []"); - System.out.println(" read []"); - System.out.println(" update []"); - System.out.println(" delete []"); - System.out.println(" copy [,]*"); - System.out.println(" place []"); - System.out.println(" showpass []"); - System.out.println(" check []"); - System.out.println(" config "); - System.out.println(" validate "); - System.out.println(" genkeypair"); - if (doExit) { - System.exit(1); - } - } - - TIMEOUT = Integer.parseInt(env.getProperty(Config.AAF_CONN_TIMEOUT, "5000")); - - reqDF = env.newDataFactory(CertificateRequest.class); - artifactsDF = env.newDataFactory(Artifacts.class); - certDF = env.newDataFactory(CertInfo.class); - configDF = env.newDataFactory(Configuration.class); - permDF = env.newDataFactory(Perms.class); - errMsg = new ErrMessage(env); - - placeArtifact = new HashMap(); - placeArtifact.put(JKS, new PlaceArtifactInKeystore(JKS)); - placeArtifact.put(PKCS12, new PlaceArtifactInKeystore(PKCS12)); - placeArtifact.put(FILE, new PlaceArtifactInFiles()); - placeArtifact.put(PRINT, new PlaceArtifactOnStream(System.out)); - placeArtifact.put(SCRIPT, new PlaceArtifactScripts()); - - Trans trans = env.newTrans(); - String token; - if((token=access.getProperty("oauth_token"))!=null) { - trans.setProperty("oauth_token", token); - } - try { - // show Std out again - aafsso.setLogDefault(); - aafsso.setStdErrDefault(); - - // if CM_URL can be obtained, add to sso.props, if written - String cm_url = getProperty(access,env,false, Config.CM_URL,Config.CM_URL+": "); - if(cm_url!=null) { - aafsso.addProp(Config.CM_URL, cm_url); - } - aafsso.writeFiles(); - - AAFCon aafcon = new AAFConHttp(access,Config.CM_URL); - - String cmd = cmds.removeFirst(); - switch(cmd) { - case "place": - placeCerts(trans,aafcon,cmds); - break; - case "create": - createArtifact(trans, aafcon,cmds); - break; - case "read": - readArtifact(trans, aafcon, cmds); - break; - case "copy": - copyArtifact(trans, aafcon, cmds); - break; - case "update": - updateArtifact(trans, aafcon, cmds); - break; - case "delete": - deleteArtifact(trans, aafcon, cmds); - break; - case "showpass": - showPass(trans, aafcon, cmds); - break; - case "config": - initConfig(trans,access,aafcon,cmds); - break; - case "validate": - validate(aafsso,aafcon); - break; - case "check": - try { - exitCode = check(trans,aafcon,cmds); - } catch (Exception e) { - exitCode = 1; - throw e; - } - break; - default: - AAFSSO.cons.printf("Unknown command \"%s\"\n", cmd); - } - } finally { - StringBuilder sb = new StringBuilder(); - trans.auditTrail(4, sb, Trans.REMOTE); - if(sb.length()>0) { - trans.info().log("Trans Info\n",sb); - } - } - aafsso.close(); - } - } catch (Exception e) { - e.printStackTrace(); - } - if(exitCode != 0 && doExit) { - System.exit(exitCode); - } - } - - private static String getProperty(PropAccess pa, Env env, boolean secure, String tag, String prompt, Object ... def) { - String value; - if((value=pa.getProperty(tag))==null) { - if(secure) { - value = new String(AAFSSO.cons.readPassword(prompt, def)); - } else { - value = AAFSSO.cons.readLine(prompt,def).trim(); - } - if(value!=null) { - if(value.length()>0) { - pa.setProperty(tag,value); - env.setProperty(tag,value); - } else if(def.length==1) { - value=def[0].toString(); - pa.setProperty(tag,value); - env.setProperty(tag,value); - } - } - } - return value; - } - - private static String fqi(Deque cmds) { - if(cmds.size()<1) { - String alias = env.getProperty(Config.CADI_ALIAS); - return alias!=null?alias:AAFSSO.cons.readLine("MechID: "); - } - return cmds.removeFirst(); - } - - private static String machine(Deque cmds) throws UnknownHostException { - if(cmds.size()>0) { - return cmds.removeFirst(); - } else { - String mach = env.getProperty(Config.HOSTNAME); - return mach!=null?mach:InetAddress.getLocalHost().getHostName(); - } - } - - private static String[] machines(Deque cmds) { - String machines; - if(cmds.size()>0) { - machines = cmds.removeFirst(); - } else { - machines = AAFSSO.cons.readLine("Machines (sep by ','): "); - } - return Split.split(',', machines); - } - - private static void createArtifact(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { - String mechID = fqi(cmds); - String machine = machine(cmds); - - Artifacts artifacts = new Artifacts(); - Artifact arti = new Artifact(); - artifacts.getArtifact().add(arti); - arti.setMechid(mechID!=null?mechID:AAFSSO.cons.readLine("MechID: ")); - arti.setMachine(machine!=null?machine:AAFSSO.cons.readLine("Machine (%s): ",InetAddress.getLocalHost().getHostName())); - arti.setCa(AAFSSO.cons.readLine("CA: (%s): ","aaf")); - - String resp = AAFSSO.cons.readLine("Types [file,jks,script] (%s): ", "jks"); - for(String s : Split.splitTrim(',', resp)) { - arti.getType().add(s); - } - // Always do Script - if(!resp.contains(SCRIPT)) { - arti.getType().add(SCRIPT); - } - - // Note: Sponsor is set on Creation by CM - String configRootName = FQI.reverseDomain(arti.getMechid()); - arti.setNs(AAFSSO.cons.readLine("Namespace (%s): ",configRootName)); - arti.setDir(AAFSSO.cons.readLine("Directory (%s): ", System.getProperty("user.dir"))); - arti.setOsUser(AAFSSO.cons.readLine("OS User (%s): ", System.getProperty("user.name"))); - arti.setRenewDays(Integer.parseInt(AAFSSO.cons.readLine("Renewal Days (%s):", "30"))); - arti.setNotification(toNotification(AAFSSO.cons.readLine("Notification (mailto owner):", ""))); - - TimeTaken tt = trans.start("Create Artifact", Env.REMOTE); - try { - Future future = aafcon.client(CM_VER).create("/cert/artifacts", artifactsDF, artifacts); - if(future.get(TIMEOUT)) { - trans.info().printf("Call to AAF Certman successful %s, %s",arti.getMechid(), arti.getMachine()); - } else { - trans.error().printf("Call to AAF Certman failed, %s", - errMsg.toMsg(future)); - } - } finally { - tt.done(); - } - } - - private static String toNotification(String notification) { - if(notification==null) { - notification=""; - } else if(notification.length()>0) { - if(notification.indexOf(':')<0) { - notification = "mailto:" + notification; - } - } - return notification; - } - - - private static void readArtifact(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { - String mechID = fqi(cmds); - String machine = machine(cmds); - - TimeTaken tt = trans.start("Read Artifact", Env.SUB); - try { - Future future = aafcon.client(CM_VER) - .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF,"Authorization","Bearer " + trans.getProperty("oauth_token")); - - if(future.get(TIMEOUT)) { - boolean printed = false; - for(Artifact a : future.value.getArtifact()) { - AAFSSO.cons.printf("MechID: %s\n",a.getMechid()); - AAFSSO.cons.printf(" Sponsor: %s\n",a.getSponsor()); - AAFSSO.cons.printf("Machine: %s\n",a.getMachine()); - AAFSSO.cons.printf("CA: %s\n",a.getCa()); - StringBuilder sb = new StringBuilder(); - boolean first = true; - for(String t : a.getType()) { - if(first) {first=false;} - else{sb.append(',');} - sb.append(t); - } - AAFSSO.cons.printf("Types: %s\n",sb); - AAFSSO.cons.printf("Namespace: %s\n",a.getNs()); - AAFSSO.cons.printf("Directory: %s\n",a.getDir()); - AAFSSO.cons.printf("O/S User: %s\n",a.getOsUser()); - AAFSSO.cons.printf("Renew Days: %d\n",a.getRenewDays()); - AAFSSO.cons.printf("Notification %s\n",a.getNotification()); - printed = true; - } - if(!printed) { - AAFSSO.cons.printf("Artifact for %s %s does not exist\n", mechID, machine); - } - } else { - trans.error().log(errMsg.toMsg(future)); - } - } finally { - tt.done(); - } - } - - private static void copyArtifact(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { - String mechID = fqi(cmds); - String machine = machine(cmds); - String[] newmachs = machines(cmds); - if(machine==null || newmachs == null) { - trans.error().log("No machines listed to copy to"); - } else { - TimeTaken tt = trans.start("Copy Artifact", Env.REMOTE); - try { - Future future = aafcon.client(CM_VER) - .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF); - - if(future.get(TIMEOUT)) { - boolean printed = false; - for(Artifact a : future.value.getArtifact()) { - for(String m : newmachs) { - a.setMachine(m); - Future fup = aafcon.client(CM_VER).update("/cert/artifacts", artifactsDF, future.value); - if(fup.get(TIMEOUT)) { - trans.info().printf("Copy of %s %s successful to %s",mechID,machine,m); - } else { - trans.error().printf("Call to AAF Certman failed, %s", - errMsg.toMsg(fup)); - } - - printed = true; - } - } - if(!printed) { - AAFSSO.cons.printf("Artifact for %s %s does not exist", mechID, machine); - } - } else { - trans.error().log(errMsg.toMsg(future)); - } - } finally { - tt.done(); - } - } - } - - private static void updateArtifact(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { - String mechID = fqi(cmds); - String machine = machine(cmds); - - TimeTaken tt = trans.start("Update Artifact", Env.REMOTE); - try { - Future fread = aafcon.client(CM_VER) - .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF); - - if(fread.get(TIMEOUT)) { - Artifacts artifacts = new Artifacts(); - for(Artifact a : fread.value.getArtifact()) { - Artifact arti = new Artifact(); - artifacts.getArtifact().add(arti); - - AAFSSO.cons.printf("For %s on %s\n", a.getMechid(),a.getMachine()); - arti.setMechid(a.getMechid()); - arti.setMachine(a.getMachine()); - arti.setCa(AAFSSO.cons.readLine("CA: (%s): ",a.getCa())); - StringBuilder sb = new StringBuilder(); - boolean first = true; - for(String t : a.getType()) { - if(first) {first=false;} - else{sb.append(',');} - sb.append(t); - } - - String resp = AAFSSO.cons.readLine("Types [file,jks,pkcs12] (%s): ", sb); - for(String s : Split.splitTrim(',', resp)) { - arti.getType().add(s); - } - // Always do Script - if(!resp.contains(SCRIPT)) { - arti.getType().add(SCRIPT); - } - - // Note: Sponsor is set on Creation by CM - arti.setNs(AAFSSO.cons.readLine("Namespace (%s): ",a.getNs())); - arti.setDir(AAFSSO.cons.readLine("Directory (%s): ", a.getDir())); - arti.setOsUser(AAFSSO.cons.readLine("OS User (%s): ", a.getOsUser())); - arti.setRenewDays(Integer.parseInt(AAFSSO.cons.readLine("Renew Days (%s):", a.getRenewDays()))); - arti.setNotification(toNotification(AAFSSO.cons.readLine("Notification (%s):", a.getNotification()))); - - } - if(artifacts.getArtifact().size()==0) { - AAFSSO.cons.printf("Artifact for %s %s does not exist", mechID, machine); - } else { - Future fup = aafcon.client(CM_VER).update("/cert/artifacts", artifactsDF, artifacts); - if(fup.get(TIMEOUT)) { - trans.info().printf("Call to AAF Certman successful %s, %s",mechID,machine); - } else { - trans.error().printf("Call to AAF Certman failed, %s", - errMsg.toMsg(fup)); - } - } - } else { - trans.error().printf("Call to AAF Certman failed, %s %s, %s", - errMsg.toMsg(fread),mechID,machine); - } - } finally { - tt.done(); - } - } - - private static void deleteArtifact(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { - String mechid = fqi(cmds); - String machine = machine(cmds); - - TimeTaken tt = trans.start("Delete Artifact", Env.REMOTE); - try { - Future future = aafcon.client(CM_VER) - .delete("/cert/artifacts/"+mechid+"/"+machine,"application/json" ); - - if(future.get(TIMEOUT)) { - trans.info().printf("Call to AAF Certman successful %s, %s",mechid,machine); - } else { - trans.error().printf("Call to AAF Certman failed, %s %s, %s", - errMsg.toMsg(future),mechid,machine); - } - } finally { - tt.done(); - } - } - - - - private static boolean placeCerts(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { - boolean rv = false; - String mechID = fqi(cmds); - String machine = machine(cmds); - String[] fqdns = Split.split(':', machine); - String key; - if(fqdns.length>1) { - key = fqdns[0]; - machine = fqdns[1]; - } else { - key = machine; - } - - TimeTaken tt = trans.start("Place Artifact", Env.REMOTE); - try { - Future acf = aafcon.client(CM_VER) - .read("/cert/artifacts/"+mechID+'/'+key, artifactsDF); - if(acf.get(TIMEOUT)) { - if(acf.value.getArtifact()==null || acf.value.getArtifact().isEmpty()) { - AAFSSO.cons.printf("===> There are no artifacts for %s on machine '%s'\n", mechID, key); - } else { - for(Artifact a : acf.value.getArtifact()) { - String osID = System.getProperty("user.name"); - if(a.getOsUser().equals(osID)) { - CertificateRequest cr = new CertificateRequest(); - cr.setMechid(a.getMechid()); - cr.setSponsor(a.getSponsor()); - for(int i=0;i f = aafcon.client(CM_VER) - .updateRespondString("/cert/" + a.getCa()+"?withTrust",reqDF, cr); - if(f.get(TIMEOUT)) { - CertInfo capi = certDF.newData().in(TYPE.JSON).load(f.body()).asObject(); - for(String type : a.getType()) { - PlaceArtifact pa = placeArtifact.get(type); - if(pa!=null) { - if(rv = pa.place(trans, capi, a,machine)) { - notifyPlaced(a,rv); - } - } - } - // Cover for the above multiple pass possibilities with some static Data, then clear per Artifact - } else { - trans.error().log(errMsg.toMsg(f)); - } - } else { - trans.error().log("You must be OS User \"" + a.getOsUser() +"\" to place Certificates on this box"); - } - } - } - } else { - trans.error().log(errMsg.toMsg(acf)); - } - } finally { - tt.done(); - } - return rv; - } - - private static void notifyPlaced(Artifact a, boolean rv) { - } - - private static void showPass(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { - String mechID = fqi(cmds); - String machine = machine(cmds); - - TimeTaken tt = trans.start("Show Password", Env.REMOTE); - try { - Future acf = aafcon.client(CM_VER) - .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF); - if(acf.get(TIMEOUT)) { - // Have to wait for JDK 1.7 source... - //switch(artifact.getType()) { - if(acf.value.getArtifact()==null || acf.value.getArtifact().isEmpty()) { - AAFSSO.cons.printf("No Artifacts found for %s on %s", mechID, machine); - } else { - String id = aafcon.defID(); - boolean allowed; - for(Artifact a : acf.value.getArtifact()) { - allowed = id!=null && (id.equals(a.getSponsor()) || - (id.equals(a.getMechid()) - && aafcon.securityInfo().defSS.getClass().isAssignableFrom(HBasicAuthSS.class))); - if(!allowed) { - Future pf = aafcon.client(CM_VER).read("/cert/may/" + - a.getNs() + ".certman|"+a.getCa()+"|showpass","*/*"); - if(pf.get(TIMEOUT)) { - allowed = true; - } else { - trans.error().log(errMsg.toMsg(pf)); - } - } - if(allowed) { - File dir = new File(a.getDir()); - Properties props = new Properties(); - FileInputStream fis = new FileInputStream(new File(dir,a.getNs()+".props")); - try { - props.load(fis); - fis.close(); - fis = new FileInputStream(new File(dir,a.getNs()+".chal")); - props.load(fis); - } finally { - fis.close(); - } - - File f = new File(dir,a.getNs()+".keyfile"); - if(f.exists()) { - Symm symm = Symm.obtain(f); - - for(Iterator> iter = props.entrySet().iterator(); iter.hasNext();) { - Entry en = iter.next(); - if(en.getValue().toString().startsWith("enc:")) { - System.out.printf("%s=%s\n", en.getKey(), symm.depass(en.getValue().toString())); - } - } - } else { - trans.error().printf("%s.keyfile must exist to read passwords for %s on %s", - f.getAbsolutePath(),a.getMechid(), a.getMachine()); - } - } - } - } - } else { - trans.error().log(errMsg.toMsg(acf)); - } - } finally { - tt.done(); - } - - } - - - private static void initConfig(Trans trans, PropAccess pa, AAFCon aafcon, Deque cmds) throws Exception { - final String fqi = fqi(cmds); - final String locator = getProperty(pa,aafcon.env,false,Config.AAF_LOCATE_URL,"AAF Locator URL: "); - final String rootFile = FQI.reverseDomain(fqi); - final File dir = new File(pa.getProperty(Config.CADI_ETCDIR, ".")); - if(dir.exists()) { - System.out.println("Writing to " + dir.getCanonicalFile()); - } else if(dir.mkdirs()) { - System.out.println("Created directory " + dir.getCanonicalFile()); - } else { - System.err.println("Unable to create or write to " + dir.getCanonicalPath()); - return; - } - - TimeTaken tt = trans.start("Get Configuration", Env.REMOTE); - try { - boolean ok=false; - File fprops = File.createTempFile(rootFile, ".tmp",dir); - PrintStream out = new PrintStream(new FileOutputStream(fprops)); - out.println(HASHES); - out.print("# Configuration File generated on "); - out.println(new Date().toString()); - out.println(HASHES); - - File fkf = new File(dir,rootFile+".keyfile"); - if(!fkf.exists()) { - CmdLine.main(new String[] {"keygen",fkf.toString()}); - } - out.print("cadi_keyfile="); - out.println(fkf.getCanonicalPath()); - - out.print(Config.AAF_APPID); - out.print('='); - out.println(fqi); - - Symm filesymm = Symm.obtain(fkf); - out.print(Config.AAF_APPPASS); - out.print("=enc:"); - String ps = pa.decrypt(pa.getProperty(Config.AAF_APPPASS), false); - ps = filesymm.enpass(ps); - out.println(ps); - - out.print(Config.CADI_TRUSTSTORE); - out.print("="); - File origTruststore = new File(pa.getProperty(Config.CADI_TRUSTSTORE)); - File newTruststore = new File(dir,origTruststore.getName()); - if(!newTruststore.exists()) { - Files.copy(origTruststore.toPath(), newTruststore.toPath()); - } - out.println(newTruststore.getCanonicalPath()); - - out.print(Config.CADI_TRUSTSTORE_PASSWORD); - out.print("=enc:"); - ps = pa.decrypt(pa.getProperty(Config.CADI_TRUSTSTORE_PASSWORD), false); - ps = filesymm.enpass(ps); - out.println(ps); - - - try { - Future acf = aafcon.client(new SingleEndpointLocator(locator)) - .read("/configure/"+fqi+"/aaf", configDF); - if(acf.get(TIMEOUT)) { -// out.println(acf.value.getName()); - for(Props props : acf.value.getProps()) { - out.println(props.getTag() + '=' + props.getValue()); - } - ok = true; - } else if(acf.code()==401){ - trans.error().log("Bad Password sent to AAF"); - } else { - trans.error().log(errMsg.toMsg(acf)); - } - } finally { - out.close(); - } - if(ok) { - File newFile = new File(dir,rootFile+".common.props"); - fprops.renameTo(newFile); - System.out.println("Created " + newFile.getCanonicalPath()); - fprops = newFile; - } else { - fprops.delete(); - } - } finally { - tt.done(); - } - } - - private static void validate(final AAFSSO aafsso, final AAFCon aafcon) throws LocatorException, CadiException, APIException { - System.out.println("Validating Configuration..."); - aafcon.clone(aafsso.access().getProperty(Config.AAF_URL)).best(new Retryable() { - @Override - public Void code(Rcli client) throws CadiException, ConnectException, APIException { - Future fc = client.read("/authz/perms/user/"+aafsso.user(),permDF); - if(fc.get(aafcon.timeout)) { - System.out.print("Success connecting to "); - System.out.println(client.getURI()); - System.out.print(" Permissions for "); - System.out.println(aafsso.user()); - for(Perm p : fc.value.getPerm()) { - System.out.print('\t'); - System.out.print(p.getType()); - System.out.print('|'); - System.out.print(p.getInstance()); - System.out.print('|'); - System.out.println(p.getAction()); - } - } else { - System.err.println("Error: " + fc.code() + ' ' + fc.body()); - } - return null; - } - }); - } - - /** - * Check returns Error Codes, so that Scripts can know what to do - * - * 0 - Check Complete, nothing to do - * 1 - General Error - * 2 - Error for specific Artifact - read check.msg - * 10 - Certificate Updated - check.msg is email content - * - * @param trans - * @param aafcon - * @param cmds - * @return - * @throws Exception - */ - private static int check(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { - int exitCode=1; - String mechID = fqi(cmds); - String machine = machine(cmds); - - TimeTaken tt = trans.start("Check Certificate", Env.REMOTE); - try { - - Future acf = aafcon.client(CM_VER) - .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF); - if(acf.get(TIMEOUT)) { - // Have to wait for JDK 1.7 source... - //switch(artifact.getType()) { - if(acf.value.getArtifact()==null || acf.value.getArtifact().isEmpty()) { - AAFSSO.cons.printf("No Artifacts found for %s on %s", mechID, machine); - } else { - String id = aafcon.defID(); - GregorianCalendar now = new GregorianCalendar(); - for(Artifact a : acf.value.getArtifact()) { - if(id.equals(a.getMechid())) { - File dir = new File(a.getDir()); - Properties props = new Properties(); - FileInputStream fis = new FileInputStream(new File(dir,a.getNs()+".props")); - try { - props.load(fis); - } finally { - fis.close(); - } - - String prop; - File f; - - if((prop=props.getProperty(Config.CADI_KEYFILE))==null || - !(f=new File(prop)).exists()) { - trans.error().printf("Keyfile must exist to check Certificates for %s on %s", - a.getMechid(), a.getMachine()); - } else { - String ksf = props.getProperty(Config.CADI_KEYSTORE); - String ksps = props.getProperty(Config.CADI_KEYSTORE_PASSWORD); - if(ksf==null || ksps == null) { - trans.error().printf("Properties %s and %s must exist to check Certificates for %s on %s", - Config.CADI_KEYSTORE, Config.CADI_KEYSTORE_PASSWORD,a.getMechid(), a.getMachine()); - } else { - KeyStore ks = KeyStore.getInstance("JKS"); - Symm symm = Symm.obtain(f); - - fis = new FileInputStream(ksf); - try { - ks.load(fis,symm.depass(ksps).toCharArray()); - } finally { - fis.close(); - } - X509Certificate cert = (X509Certificate)ks.getCertificate(mechID); - String msg = null; - - if(cert==null) { - msg = String.format("X509Certificate does not exist for %s on %s in %s", - a.getMechid(), a.getMachine(), ksf); - trans.error().log(msg); - exitCode = 2; - } else { - GregorianCalendar renew = new GregorianCalendar(); - renew.setTime(cert.getNotAfter()); - renew.add(GregorianCalendar.DAY_OF_MONTH,-1*a.getRenewDays()); - if(renew.after(now)) { - msg = String.format("X509Certificate for %s on %s has been checked on %s. It expires on %s; it will not be renewed until %s.\n", - a.getMechid(), a.getMachine(),Chrono.dateOnlyStamp(now),cert.getNotAfter(),Chrono.dateOnlyStamp(renew)); - trans.info().log(msg); - exitCode = 0; // OK - } else { - trans.info().printf("X509Certificate for %s on %s expiration, %s, needs Renewal.\n", - a.getMechid(), a.getMachine(),cert.getNotAfter()); - cmds.offerLast(mechID); - cmds.offerLast(machine); - if(placeCerts(trans,aafcon,cmds)) { - msg = String.format("X509Certificate for %s on %s has been renewed. Ensure services using are refreshed.\n", - a.getMechid(), a.getMachine()); - exitCode = 10; // Refreshed - } else { - msg = String.format("X509Certificate for %s on %s attempted renewal, but failed. Immediate Investigation is required!\n", - a.getMechid(), a.getMachine()); - exitCode = 1; // Error Renewing - } - } - } - if(msg!=null) { - FileOutputStream fos = new FileOutputStream(a.getDir()+'/'+a.getNs()+".msg"); - try { - fos.write(msg.getBytes()); - } finally { - fos.close(); - } - } - } - - } - } - } - } - } else { - trans.error().log(errMsg.toMsg(acf)); - exitCode=1; - } - } finally { - tt.done(); - } - return exitCode; - } - -} - - - - diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/Factory.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/Factory.java deleted file mode 100644 index e969fab3..00000000 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/Factory.java +++ /dev/null @@ -1,486 +0,0 @@ -/** - * ============LICENSE_START==================================================== - * org.onap.aaf - * =========================================================================== - * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. - * =========================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END==================================================== - * - */ - -package org.onap.aaf.cadi.cm; - -import java.io.BufferedReader; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.io.StringReader; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.security.InvalidKeyException; -import java.security.Key; -import java.security.KeyFactory; -import java.security.KeyPair; -import java.security.KeyPairGenerator; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.Provider; -import java.security.PublicKey; -import java.security.SecureRandom; -import java.security.Security; -import java.security.Signature; -import java.security.SignatureException; -import java.security.cert.Certificate; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.security.spec.InvalidKeySpecException; -import java.security.spec.PKCS8EncodedKeySpec; -import java.security.spec.X509EncodedKeySpec; -import java.util.Collection; -import java.util.List; - -import javax.crypto.Cipher; -import javax.crypto.NoSuchPaddingException; - -import org.onap.aaf.cadi.Symm; -import org.onap.aaf.misc.env.Env; -import org.onap.aaf.misc.env.TimeTaken; -import org.onap.aaf.misc.env.Trans; - -public class Factory { - private static final String PRIVATE_KEY_HEADER = "PRIVATE KEY"; - public static final String KEY_ALGO = "RSA"; - public static final String SIG_ALGO = "SHA256withRSA"; - - public static final int KEY_LENGTH = 2048; - private static final KeyPairGenerator keygen; - private static final KeyFactory keyFactory; - private static final CertificateFactory certificateFactory; - private static final SecureRandom random; - - - private static final Symm base64 = Symm.base64.copy(64); - - static { - random = new SecureRandom(); - KeyPairGenerator tempKeygen; - try { - tempKeygen = KeyPairGenerator.getInstance(KEY_ALGO);//,"BC"); - tempKeygen.initialize(KEY_LENGTH, random); - } catch (NoSuchAlgorithmException e) { - tempKeygen = null; - e.printStackTrace(System.err); - } - keygen = tempKeygen; - - KeyFactory tempKeyFactory; - try { - tempKeyFactory=KeyFactory.getInstance(KEY_ALGO);//,"BC" - } catch (NoSuchAlgorithmException e) { - tempKeyFactory = null; - e.printStackTrace(System.err); - }; - keyFactory = tempKeyFactory; - - CertificateFactory tempCertificateFactory; - try { - tempCertificateFactory = CertificateFactory.getInstance("X.509"); - } catch (CertificateException e) { - tempCertificateFactory = null; - e.printStackTrace(System.err); - } - certificateFactory = tempCertificateFactory; - - - } - - - public static KeyPair generateKeyPair(Trans trans) { - TimeTaken tt; - if(trans!=null) { - tt = trans.start("Generate KeyPair", Env.SUB); - } else { - tt = null; - } - try { - return keygen.generateKeyPair(); - } finally { - if(tt!=null) { - tt.done(); - } - } - } - - private static final String LINE_END = "-----\n"; - - protected static String textBuilder(String kind, byte[] bytes) throws IOException { - StringBuilder sb = new StringBuilder(); - sb.append("-----BEGIN "); - sb.append(kind); - sb.append(LINE_END); - - ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - base64.encode(bais, baos); - sb.append(new String(baos.toByteArray())); - - if(sb.charAt(sb.length()-1)!='\n') { - sb.append('\n'); - } - sb.append("-----END "); - sb.append(kind); - sb.append(LINE_END); - return sb.toString(); - } - - public static PrivateKey toPrivateKey(Trans trans, String pk) throws IOException, CertException { - byte[] bytes = decode(new StringReader(pk)); - return toPrivateKey(trans, bytes); - } - - public static PrivateKey toPrivateKey(Trans trans, byte[] bytes) throws IOException, CertException { - TimeTaken tt=trans.start("Reconstitute Private Key", Env.SUB); - try { - return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(bytes)); - } catch (InvalidKeySpecException e) { - throw new CertException("Translating Private Key from PKCS8 KeySpec",e); - } finally { - tt.done(); - } - } - - public static PrivateKey toPrivateKey(Trans trans, File file) throws IOException, CertException { - TimeTaken tt = trans.start("Decode Private Key File", Env.SUB); - try { - return toPrivateKey(trans,decode(file)); - }finally { - tt.done(); - } - } - - public static String toString(Trans trans, PrivateKey pk) throws IOException { -// PKCS8EncodedKeySpec pemContents = new PKCS8EncodedKeySpec(pk.getEncoded()); - trans.debug().log("Private Key to String"); - return textBuilder(PRIVATE_KEY_HEADER,pk.getEncoded()); - } - - public static PublicKey toPublicKey(Trans trans, String pk) throws IOException { - TimeTaken tt = trans.start("Reconstitute Public Key", Env.SUB); - try { - ByteArrayInputStream bais = new ByteArrayInputStream(pk.getBytes()); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Symm.base64noSplit.decode(bais, baos); - - return keyFactory.generatePublic(new X509EncodedKeySpec(baos.toByteArray())); - } catch (InvalidKeySpecException e) { - trans.error().log(e,"Translating Public Key from X509 KeySpec"); - return null; - } finally { - tt.done(); - } - } - - public static String toString(Trans trans, PublicKey pk) throws IOException { - trans.debug().log("Public Key to String"); - return textBuilder("PUBLIC KEY",pk.getEncoded()); - } - - public static Collection toX509Certificate(String x509) throws CertificateException { - return toX509Certificate(x509.getBytes()); - } - - public static Collection toX509Certificate(List x509s) throws CertificateException { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - try { - for(String x509 : x509s) { - baos.write(x509.getBytes()); - } - } catch (IOException e) { - throw new CertificateException(e); - } - return toX509Certificate(new ByteArrayInputStream(baos.toByteArray())); - } - - public static Collection toX509Certificate(byte[] x509) throws CertificateException { - return certificateFactory.generateCertificates(new ByteArrayInputStream(x509)); - } - - public static Collection toX509Certificate(Trans trans, File file) throws CertificateException, FileNotFoundException { - FileInputStream fis = new FileInputStream(file); - try { - try { - return toX509Certificate(fis); - } finally { - fis.close(); - } - } catch (IOException e) { - throw new CertificateException(e); - } - } - - public static Collection toX509Certificate(InputStream is) throws CertificateException { - return certificateFactory.generateCertificates(is); - } - - public static String toString(Trans trans, Certificate cert) throws IOException, CertException { - if(trans.debug().isLoggable()) { - StringBuilder sb = new StringBuilder("Certificate to String"); - if(cert instanceof X509Certificate) { - sb.append(" - "); - sb.append(((X509Certificate)cert).getSubjectDN()); - } - trans.debug().log(sb); - } - try { - if(cert==null) { - throw new CertException("Certificate not built"); - } - return textBuilder("CERTIFICATE",cert.getEncoded()); - } catch (CertificateEncodingException e) { - throw new CertException(e); - } - } - - public static Cipher pkCipher() throws NoSuchAlgorithmException, NoSuchPaddingException { - return Cipher.getInstance(KEY_ALGO); - } - - public static Cipher pkCipher(Key key, boolean encrypt) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException { - Cipher cipher = Cipher.getInstance(KEY_ALGO); - cipher.init(encrypt?Cipher.ENCRYPT_MODE:Cipher.DECRYPT_MODE,key); - return cipher; - } - - public static byte[] strip(Reader rdr) throws IOException { - BufferedReader br = new BufferedReader(rdr); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - String line; - while((line=br.readLine())!=null) { - if(line.length()>0 && - !line.startsWith("-----") && - line.indexOf(':')<0) { // Header elements - baos.write(line.getBytes()); - } - } - return baos.toByteArray(); - } - - public static class StripperInputStream extends InputStream { - private Reader created; - private BufferedReader br; - private int idx; - private String line; - - public StripperInputStream(Reader rdr) { - if(rdr instanceof BufferedReader) { - br = (BufferedReader)rdr; - } else { - br = new BufferedReader(rdr); - } - created = null; - } - - public StripperInputStream(File file) throws FileNotFoundException { - this(new FileReader(file)); - created = br; - } - - public StripperInputStream(InputStream is) throws FileNotFoundException { - this(new InputStreamReader(is)); - created = br; - } - - @Override - public int read() throws IOException { - if(line==null || idx>=line.length()) { - while((line=br.readLine())!=null) { - if(line.length()>0 && - !line.startsWith("-----") && - line.indexOf(':')<0) { // Header elements - break; - } - } - - if(line==null) { - return -1; - } - idx = 0; - } - return line.charAt(idx++); - } - - /* (non-Javadoc) - * @see java.io.InputStream#close() - */ - @Override - public void close() throws IOException { - if(created!=null) { - created.close(); - } - } - } - - public static class Base64InputStream extends InputStream { - private InputStream created; - private InputStream is; - private byte trio[]; - private byte duo[]; - private int idx; - - - public Base64InputStream(File file) throws FileNotFoundException { - this(new FileInputStream(file)); - created = is; - } - - public Base64InputStream(InputStream is) throws FileNotFoundException { - this.is = is; - trio = new byte[3]; - idx = 4; - } - - @Override - public int read() throws IOException { - if(duo==null || idx>=duo.length) { - int read = is.read(trio); - if(read==-1) { - return -1; - } - duo = Symm.base64.decode(trio); - if(duo==null || duo.length==0) { - return -1; - } - idx=0; - } - - return duo[idx++]; - } - - /* (non-Javadoc) - * @see java.io.InputStream#close() - */ - @Override - public void close() throws IOException { - if(created!=null) { - created.close(); - } - } - } - - public static byte[] decode(byte[] bytes) throws IOException { - ByteArrayInputStream bais = new ByteArrayInputStream(bytes); - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - Symm.base64.decode(bais, baos); - return baos.toByteArray(); - } - - public static byte[] decode(File f) throws IOException { - FileReader fr = new FileReader(f); - try { - return Factory.decode(fr); - } finally { - fr.close(); - } - - } - public static byte[] decode(Reader rdr) throws IOException { - return decode(strip(rdr)); - } - - - public static byte[] binary(File file) throws IOException { - DataInputStream dis = new DataInputStream(new FileInputStream(file)); - try { - byte[] bytes = new byte[(int)file.length()]; - dis.readFully(bytes); - return bytes; - } finally { - dis.close(); - } - } - - - public static byte[] sign(Trans trans, byte[] bytes, PrivateKey pk) throws IOException, InvalidKeyException, SignatureException, NoSuchAlgorithmException { - TimeTaken tt = trans.start("Sign Data", Env.SUB); - try { - Signature sig = Signature.getInstance(SIG_ALGO); - sig.initSign(pk, random); - sig.update(bytes); - return sig.sign(); - } finally { - tt.done(); - } - } - - public static String toSignatureString(byte[] signed) throws IOException { - return textBuilder("SIGNATURE", signed); - } - - public static boolean verify(Trans trans, byte[] bytes, byte[] signature, PublicKey pk) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException { - TimeTaken tt = trans.start("Verify Data", Env.SUB); - try { - Signature sig = Signature.getInstance(SIG_ALGO); - sig.initVerify(pk); - sig.update(bytes); - return sig.verify(signature); - } finally { - tt.done(); - } - } - - /** - * Get the Security Provider, or, if not exists yet, attempt to load - * - * @param providerType - * @param params - * @return - * @throws CertException - */ - public static synchronized Provider getSecurityProvider(String providerType, String[][] params) throws CertException { - Provider p = Security.getProvider(providerType); - if(p!=null) { - switch(providerType) { - case "PKCS12": - - break; - case "PKCS11": // PKCS11 only known to be supported by Sun - try { - Class clsSunPKCS11 = Class.forName("sun.security.pkcs11.SunPKCS11"); - Constructor cnst = clsSunPKCS11.getConstructor(String.class); - Object sunPKCS11 = cnst.newInstance(params[0][0]); - if (sunPKCS11==null) { - throw new CertException("SunPKCS11 Provider cannot be constructed for " + params[0][0]); - } - Security.addProvider((Provider)sunPKCS11); - } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - throw new CertException(e); - } - break; - default: - throw new CertException(providerType + " is not a known Security Provider for your JDK."); - } - } - return p; - } -} diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifact.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifact.java deleted file mode 100644 index 369f48d0..00000000 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifact.java +++ /dev/null @@ -1,32 +0,0 @@ -/** - * ============LICENSE_START==================================================== - * org.onap.aaf - * =========================================================================== - * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. - * =========================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END==================================================== - * - */ - -package org.onap.aaf.cadi.cm; - -import certman.v1_0.Artifacts.Artifact; -import certman.v1_0.CertInfo; - -import org.onap.aaf.cadi.CadiException; -import org.onap.aaf.misc.env.Trans; - -public interface PlaceArtifact { - public boolean place(Trans trans, CertInfo cert, Artifact arti, String machine) throws CadiException; -} diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifactInFiles.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifactInFiles.java deleted file mode 100644 index f419577b..00000000 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifactInFiles.java +++ /dev/null @@ -1,52 +0,0 @@ -/** - * ============LICENSE_START==================================================== - * org.onap.aaf - * =========================================================================== - * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. - * =========================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END==================================================== - * - */ - -package org.onap.aaf.cadi.cm; - -import java.io.File; - -import org.onap.aaf.cadi.CadiException; -import org.onap.aaf.cadi.util.Chmod; -import org.onap.aaf.misc.env.Trans; - -import certman.v1_0.Artifacts.Artifact; -import certman.v1_0.CertInfo; - -public class PlaceArtifactInFiles extends ArtifactDir { - @Override - public boolean _place(Trans trans, CertInfo certInfo, Artifact arti) throws CadiException { - try { - // Setup Public Cert - File f = new File(dir,arti.getNs()+".crt"); - write(f,Chmod.to644,certInfo.getCerts().get(0),C_R); - - // Setup Private Key - f = new File(dir,arti.getNs()+".key"); - write(f,Chmod.to400,certInfo.getPrivatekey(),C_R); - - } catch (Exception e) { - throw new CadiException(e); - } - return true; - } -} - - diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifactInKeystore.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifactInKeystore.java deleted file mode 100644 index 2b498d4f..00000000 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifactInKeystore.java +++ /dev/null @@ -1,140 +0,0 @@ -/** - * ============LICENSE_START==================================================== - * org.onap.aaf - * =========================================================================== - * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. - * =========================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END==================================================== - * - */ - -package org.onap.aaf.cadi.cm; - -import java.io.File; -import java.security.KeyStore; -import java.security.PrivateKey; -import java.security.cert.Certificate; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.onap.aaf.cadi.CadiException; -import org.onap.aaf.cadi.Symm; -import org.onap.aaf.cadi.config.Config; -import org.onap.aaf.cadi.util.Chmod; -import org.onap.aaf.misc.env.Trans; - -import certman.v1_0.Artifacts.Artifact; -import certman.v1_0.CertInfo; - -public class PlaceArtifactInKeystore extends ArtifactDir { - private String kst; - - public PlaceArtifactInKeystore(String kst) { - this.kst = kst; - } - - @Override - public boolean _place(Trans trans, CertInfo certInfo, Artifact arti) throws CadiException { - File fks = new File(dir,arti.getNs()+'.'+kst); - try { - KeyStore jks = KeyStore.getInstance(kst); - if(fks.exists()) { - fks.delete(); - } - - // Get the Cert(s)... Might include Trust store - Collection certColl = Factory.toX509Certificate(certInfo.getCerts()); - // find where the trusts end in 1.0 API - - X509Certificate x509; - List certList = new ArrayList(); - Certificate[] trustChain = null; - Certificate[] trustCAs; - for(Certificate c : certColl) { - x509 = (X509Certificate)c; - if(trustChain==null && x509.getSubjectDN().equals(x509.getIssuerDN())) { - trustChain = new Certificate[certList.size()]; - certList.toArray(trustChain); - certList.clear(); // reuse - } - certList.add(x509); - } - - // remainder should be Trust CAs - trustCAs = new Certificate[certList.size()]; - certList.toArray(trustCAs); - - // Properties, etc - // Add CADI Keyfile Entry to Properties - addProperty(Config.CADI_KEYFILE,arti.getDir()+'/'+arti.getNs() + ".keyfile"); - // Set Keystore Password - addProperty(Config.CADI_KEYSTORE,fks.getAbsolutePath()); - String keystorePass = Symm.randomGen(CmAgent.PASS_SIZE); - addEncProperty(Config.CADI_KEYSTORE_PASSWORD,keystorePass); - char[] keystorePassArray = keystorePass.toCharArray(); - jks.load(null,keystorePassArray); // load in - - // Add Private Key/Cert Entry for App - // Note: Java SSL security classes, while having a separate key from keystore, - // is documented to not actually work. - // java.security.UnrecoverableKeyException: Cannot recover key - // You can create a custom Key Manager to make it work, but Practicality - // dictates that you live with the default, meaning, they are the same - String keyPass = keystorePass; //Symm.randomGen(CmAgent.PASS_SIZE); - PrivateKey pk = Factory.toPrivateKey(trans, certInfo.getPrivatekey()); - addEncProperty(Config.CADI_KEY_PASSWORD, keyPass); - addProperty(Config.CADI_ALIAS, arti.getMechid()); -// Set attribs = new HashSet(); -// if(kst.equals("pkcs12")) { -// // Friendly Name -// attribs.add(new PKCS12Attribute("1.2.840.113549.1.9.20", arti.getNs())); -// } -// - KeyStore.ProtectionParameter protParam = - new KeyStore.PasswordProtection(keyPass.toCharArray()); - - KeyStore.PrivateKeyEntry pkEntry = - new KeyStore.PrivateKeyEntry(pk, trustChain); - jks.setEntry(arti.getMechid(), - pkEntry, protParam); - - // Write out - write(fks,Chmod.to400,jks,keystorePassArray); - - // Change out to TrustStore - fks = new File(dir,arti.getNs()+".trust."+kst); - jks = KeyStore.getInstance(kst); - - // Set Truststore Password - addProperty(Config.CADI_TRUSTSTORE,fks.getAbsolutePath()); - String trustStorePass = Symm.randomGen(CmAgent.PASS_SIZE); - addEncProperty(Config.CADI_TRUSTSTORE_PASSWORD,trustStorePass); - char[] truststorePassArray = trustStorePass.toCharArray(); - jks.load(null,truststorePassArray); // load in - - // Add Trusted Certificates, but PKCS12 doesn't support - for(int i=0; i0) { - trans.info().printf("Warning: %s\n",capi.getNotes()); - } - out.printf("Challenge: %s\n",capi.getChallenge()); - out.printf("PrivateKey:\n%s\n",capi.getPrivatekey()); - out.println("Certificate Chain:"); - for(String c : capi.getCerts()) { - out.println(c); - } - return true; - } -} diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifactScripts.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifactScripts.java deleted file mode 100644 index 9347f70e..00000000 --- a/cadi/aaf/src/main/java/org/onap/aaf/cadi/cm/PlaceArtifactScripts.java +++ /dev/null @@ -1,157 +0,0 @@ -/** - * ============LICENSE_START==================================================== - * org.onap.aaf - * =========================================================================== - * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. - * =========================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ============LICENSE_END==================================================== - * - */ - -package org.onap.aaf.cadi.cm; - -import java.io.File; - -import org.onap.aaf.cadi.CadiException; -import org.onap.aaf.cadi.util.Chmod; -import org.onap.aaf.misc.env.Trans; -import org.onap.aaf.misc.env.util.Chrono; -import org.onap.aaf.misc.env.util.Split; - -import certman.v1_0.Artifacts.Artifact; -import certman.v1_0.CertInfo; - -public class PlaceArtifactScripts extends ArtifactDir { - @Override - public boolean _place(Trans trans, CertInfo certInfo, Artifact arti) throws CadiException { - try { - // Setup check.sh script - String filename = arti.getNs()+".check.sh"; - File f1 = new File(dir,filename); - String email = arti.getNotification() + '\n'; - if(email.startsWith("mailto:")) { - email=email.substring(7); - } else { - email=arti.getOsUser() + '\n'; - } - - StringBuilder classpath = new StringBuilder(); - boolean first = true; - for(String pth : Split.split(File.pathSeparatorChar, System.getProperty("java.class.path"))) { - if(first) { - first=false; - } else { - classpath.append(File.pathSeparatorChar); - } - File f = new File(pth); - classpath.append(f.getCanonicalPath().replaceAll("[0-9]+\\.[0-9]+\\.[0-9]+","*")); - } - - write(f1,Chmod.to644, - "#!/bin/bash " + f1.getCanonicalPath()+'\n', - "# Certificate Manager Check Script\n", - "# Check on Certificate, and renew if needed.\n", - "# Generated by Certificate Manager " + Chrono.timeStamp()+'\n', - "DIR="+arti.getDir()+'\n', - "APP="+arti.getNs()+'\n', - "EMAIL="+email, - "CP=\""+classpath.toString()+"\"\n", - checkScript - ); - - // Setup check.sh script - File f2 = new File(dir,arti.getNs()+".crontab.sh"); - write(f2,Chmod.to644, - "#!/bin/bash " + f2.getCanonicalPath()+'\n', - "# Certificate Manager Crontab Loading Script\n", - "# Add/Update a Crontab entry, that adds a check on Certificate Manager generated Certificate nightly.\n", - "# Generated by Certificate Manager " + Chrono.timeStamp()+'\n', - "TFILE=\"/tmp/cmcron$$.temp\"\n", - "DIR=\""+arti.getDir()+"\"\n", - "CF=\""+arti.getNs()+" Certificate Check Script\"\n", - "SCRIPT=\""+f1.getCanonicalPath()+"\"\n", - cronScript - ); - - } catch (Exception e) { - throw new CadiException(e); - } - return true; - } - - /** - * Note: java.home gets Absolute Path of Java, where we probably want soft links from - * JAVA_HOME - * @return - */ - private final static String javaHome() { - String rc = System.getenv("JAVA_HOME"); - return rc==null?System.getProperty("java.home"):rc; - } - private final static String checkScript = - "> $DIR/$APP.msg\n\n" + - "function mailit {\n" + - " if [ -e /bin/mail ]; then\n" + - " MAILER=/bin/mail\n" + - " elif [ -e /usr/bin/mail ]; then \n" + - " MAILER=/usr/bin/mail\n" + - " else \n" + - " MAILER=\"\"\n" + - " fi\n" + - " if [ \"$MAILER\" = \"\" ]; then\n" + - " printf \"$*\"\n" + - " else \n" + - " printf \"$*\" | $MAILER -s \"AAF Certman Notification for `uname -n`\" $EMAIL\n"+ - " fi\n" + - "}\n\n" + - javaHome() + "/bin/" +"java -cp $CP " + - CmAgent.class.getName() + - " cadi_prop_files=$DIR/$APP.props check 2> $DIR/$APP.STDERR > $DIR/$APP.STDOUT\n" + - "case \"$?\" in\n" + - " 0)\n" + - " # Note: Validation will be mailed only the first day after any modification\n" + - " if [ \"`find $DIR -mtime 0 -name $APP.check.sh`\" != \"\" ] ; then\n" + - " mailit `echo \"Certficate Validated:\\n\\n\" | cat - $DIR/$APP.msg`\n" + - " else\n" + - " cat $DIR/$APP.msg\n" + - " fi\n" + - " ;;\n" + - " 1) mailit \"Error with Certificate Check:\\\\n\\\\nCheck logs $DIR/$APP.STDOUT and $DIR/$APP.STDERR on `uname -n`\"\n" + - " ;;\n" + - " 2) mailit `echo \"Certificate Check Error\\\\n\\\\n\" | cat - $DIR/$APP.msg`\n" + - " ;;\n" + - " 10) mailit `echo \"Certificate Replaced\\\\n\\\\n\" | cat - $DIR/$APP.msg`\n" + - " if [ -e $DIR/$APP.restart.sh ]; then\n" + - " # Note: it is THIS SCRIPT'S RESPONSIBILITY to notify upon success or failure as necessary!!\n" + - " /bin/sh $DIR/$APP.restart.sh\n" + - " fi\n" + - " ;;\n" + - " *) mailit `echo \"Unknown Error code for CM Agent\\\\n\\\\n\" | cat - $DIR/$APP.msg`\n" + - " ;;\n" + - " esac\n\n" + - " # Note: make sure to cover this sripts' exit Code\n"; - - private final static String cronScript = - "crontab -l | sed -n \"/#### BEGIN $CF/,/END $CF ####/!p\" > $TFILE\n" + - "# Note: Randomize Minutes (0-60) and hours (1-4)\n" + - "echo \"#### BEGIN $CF ####\" >> $TFILE\n" + - "echo \"$(( $RANDOM % 60)) $(( $(( $RANDOM % 3 )) + 1 )) * * * /bin/bash $SCRIPT " + - ">> $DIR/cronlog 2>&1 \" >> $TFILE\n" + - "echo \"#### END $CF ####\" >> $TFILE\n" + - "crontab $TFILE\n" + - "rm $TFILE\n"; -} - - - diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/Agent.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/Agent.java new file mode 100644 index 00000000..3c8719b4 --- /dev/null +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/Agent.java @@ -0,0 +1,956 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.cadi.configure; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.net.ConnectException; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.file.Files; +import java.security.KeyStore; +import java.security.cert.X509Certificate; +import java.util.ArrayDeque; +import java.util.Date; +import java.util.Deque; +import java.util.GregorianCalendar; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import java.util.Map.Entry; +import java.util.Properties; + +import org.onap.aaf.cadi.CadiException; +import org.onap.aaf.cadi.CmdLine; +import org.onap.aaf.cadi.LocatorException; +import org.onap.aaf.cadi.PropAccess; +import org.onap.aaf.cadi.Symm; +import org.onap.aaf.cadi.aaf.client.ErrMessage; +import org.onap.aaf.cadi.aaf.v2_0.AAFCon; +import org.onap.aaf.cadi.aaf.v2_0.AAFConHttp; +import org.onap.aaf.cadi.client.Future; +import org.onap.aaf.cadi.client.Rcli; +import org.onap.aaf.cadi.client.Retryable; +import org.onap.aaf.cadi.config.Config; +import org.onap.aaf.cadi.config.SecurityInfoC; +import org.onap.aaf.cadi.http.HBasicAuthSS; +import org.onap.aaf.cadi.locator.SingleEndpointLocator; +import org.onap.aaf.cadi.sso.AAFSSO; +import org.onap.aaf.cadi.util.FQI; +import org.onap.aaf.misc.env.APIException; +import org.onap.aaf.misc.env.Data.TYPE; +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.env.Trans; +import org.onap.aaf.misc.env.util.Chrono; +import org.onap.aaf.misc.env.util.Split; +import org.onap.aaf.misc.rosetta.env.RosettaDF; +import org.onap.aaf.misc.rosetta.env.RosettaEnv; + +import aaf.v2_0.Perm; +import aaf.v2_0.Perms; +import certman.v1_0.Artifacts; +import certman.v1_0.Artifacts.Artifact; +import certman.v1_0.CertInfo; +import certman.v1_0.CertificateRequest; +import locate.v1_1.Configuration; +import locate.v1_1.Configuration.Props; + +public class Agent { + private static final String HASHES = "################################################################"; + private static final String PRINT = "print"; + private static final String FILE = "file"; + private static final String PKCS12 = "pkcs12"; + private static final String JKS = "jks"; + private static final String SCRIPT="script"; + + private static final String CM_VER = "1.0"; + public static final int PASS_SIZE = 24; + private static int TIMEOUT; + + private static RosettaDF reqDF; + private static RosettaDF certDF; + private static RosettaDF artifactsDF; + private static RosettaDF configDF; + private static RosettaDF permDF; + private static ErrMessage errMsg; + private static Map placeArtifact; + private static RosettaEnv env; + + private static boolean doExit; + + public static void main(String[] args) { + int exitCode = 0; + doExit = true; + try { + AAFSSO aafsso; + PropAccess access; + + if(args.length>0 && args[0].equals("validate")) { + int idx = args[1].indexOf('='); + aafsso = null; + access = new PropAccess( + (idx<0?Config.CADI_PROP_FILES:args[1].substring(0, idx))+ + '='+ + (idx<0?args[1]:args[1].substring(idx+1))); + } else { + aafsso= new AAFSSO(args, new AAFSSO.ProcessArgs() { + @Override + public Properties process(String[] args, Properties props) { + if(args.length>1) { + if (!args[0].equals("genkeypair")) { + props.put("aaf_id", args[1]); + } + } + return props; + } + }); + access = aafsso.access(); + } + + if(aafsso!=null && aafsso.loginOnly()) { + aafsso.setLogDefault(); + aafsso.writeFiles(); + System.out.println("AAF SSO information created in ~/.aaf"); + } else { + env = new RosettaEnv(access.getProperties()); + Deque cmds = new ArrayDeque(); + for(String p : args) { + if("-noexit".equalsIgnoreCase(p)) { + doExit = false; + } else if(p.indexOf('=') < 0) { + cmds.add(p); + } + } + + if(cmds.size()==0) { + aafsso.setLogDefault(); + // NOTE: CHANGE IN CMDS should be reflected in AAFSSO constructor, to get FQI->aaf-id or not + System.out.println("Usage: java -jar cmd []*"); + System.out.println(" create []"); + System.out.println(" read []"); + System.out.println(" update []"); + System.out.println(" delete []"); + System.out.println(" copy [,]*"); + System.out.println(" place []"); + System.out.println(" showpass []"); + System.out.println(" check []"); + System.out.println(" config "); + System.out.println(" validate .props>"); + System.out.println(" genkeypair"); + if (doExit) { + System.exit(1); + } + } + + TIMEOUT = Integer.parseInt(env.getProperty(Config.AAF_CONN_TIMEOUT, "5000")); + + reqDF = env.newDataFactory(CertificateRequest.class); + artifactsDF = env.newDataFactory(Artifacts.class); + certDF = env.newDataFactory(CertInfo.class); + configDF = env.newDataFactory(Configuration.class); + permDF = env.newDataFactory(Perms.class); + errMsg = new ErrMessage(env); + + placeArtifact = new HashMap(); + placeArtifact.put(JKS, new PlaceArtifactInKeystore(JKS)); + placeArtifact.put(PKCS12, new PlaceArtifactInKeystore(PKCS12)); + placeArtifact.put(FILE, new PlaceArtifactInFiles()); + placeArtifact.put(PRINT, new PlaceArtifactOnStream(System.out)); + placeArtifact.put(SCRIPT, new PlaceArtifactScripts()); + + Trans trans = env.newTrans(); + String token; + if((token=access.getProperty("oauth_token"))!=null) { + trans.setProperty("oauth_token", token); + } + try { + if(aafsso!=null) { + // show Std out again + aafsso.setLogDefault(); + aafsso.setStdErrDefault(); + + // if CM_URL can be obtained, add to sso.props, if written + String cm_url = getProperty(access,env,false, Config.CM_URL,Config.CM_URL+": "); + if(cm_url!=null) { + aafsso.addProp(Config.CM_URL, cm_url); + } + aafsso.writeFiles(); + } + + AAFCon aafcon = new AAFConHttp(access,Config.CM_URL); + + String cmd = cmds.removeFirst(); + switch(cmd) { + case "place": + placeCerts(trans,aafcon,cmds); + break; + case "create": + createArtifact(trans, aafcon,cmds); + break; + case "read": + readArtifact(trans, aafcon, cmds); + break; + case "copy": + copyArtifact(trans, aafcon, cmds); + break; + case "update": + updateArtifact(trans, aafcon, cmds); + break; + case "delete": + deleteArtifact(trans, aafcon, cmds); + break; + case "showpass": + showPass(trans, aafcon, cmds); + break; + case "config": + initConfig(trans,access,aafcon,cmds); + break; + case "validate": + validate(access); + break; + case "check": + try { + exitCode = check(trans,aafcon,cmds); + } catch (Exception e) { + exitCode = 1; + throw e; + } + break; + default: + AAFSSO.cons.printf("Unknown command \"%s\"\n", cmd); + } + } finally { + StringBuilder sb = new StringBuilder(); + trans.auditTrail(4, sb, Trans.REMOTE); + if(sb.length()>0) { + trans.info().log("Trans Info\n",sb); + } + } + if(aafsso!=null) { + aafsso.close(); + } + } + } catch (Exception e) { + e.printStackTrace(); + } + if(exitCode != 0 && doExit) { + System.exit(exitCode); + } + } + + private static String getProperty(PropAccess pa, Env env, boolean secure, String tag, String prompt, Object ... def) { + String value; + if((value=pa.getProperty(tag))==null) { + if(secure) { + value = new String(AAFSSO.cons.readPassword(prompt, def)); + } else { + value = AAFSSO.cons.readLine(prompt,def).trim(); + } + if(value!=null) { + if(value.length()>0) { + pa.setProperty(tag,value); + env.setProperty(tag,value); + } else if(def.length==1) { + value=def[0].toString(); + pa.setProperty(tag,value); + env.setProperty(tag,value); + } + } + } + return value; + } + + private static String fqi(Deque cmds) { + if(cmds.size()<1) { + String alias = env.getProperty(Config.CADI_ALIAS); + return alias!=null?alias:AAFSSO.cons.readLine("MechID: "); + } + return cmds.removeFirst(); + } + + private static String machine(Deque cmds) throws UnknownHostException { + if(cmds.size()>0) { + return cmds.removeFirst(); + } else { + String mach = env.getProperty(Config.HOSTNAME); + return mach!=null?mach:InetAddress.getLocalHost().getHostName(); + } + } + + private static String[] machines(Deque cmds) { + String machines; + if(cmds.size()>0) { + machines = cmds.removeFirst(); + } else { + machines = AAFSSO.cons.readLine("Machines (sep by ','): "); + } + return Split.split(',', machines); + } + + private static void createArtifact(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { + String mechID = fqi(cmds); + String machine = machine(cmds); + + Artifacts artifacts = new Artifacts(); + Artifact arti = new Artifact(); + artifacts.getArtifact().add(arti); + arti.setMechid(mechID!=null?mechID:AAFSSO.cons.readLine("MechID: ")); + arti.setMachine(machine!=null?machine:AAFSSO.cons.readLine("Machine (%s): ",InetAddress.getLocalHost().getHostName())); + arti.setCa(AAFSSO.cons.readLine("CA: (%s): ","aaf")); + + String resp = AAFSSO.cons.readLine("Types [file,jks,script] (%s): ", "jks"); + for(String s : Split.splitTrim(',', resp)) { + arti.getType().add(s); + } + // Always do Script + if(!resp.contains(SCRIPT)) { + arti.getType().add(SCRIPT); + } + + // Note: Sponsor is set on Creation by CM + String configRootName = FQI.reverseDomain(arti.getMechid()); + arti.setNs(AAFSSO.cons.readLine("Namespace (%s): ",configRootName)); + arti.setDir(AAFSSO.cons.readLine("Directory (%s): ", System.getProperty("user.dir"))); + arti.setOsUser(AAFSSO.cons.readLine("OS User (%s): ", System.getProperty("user.name"))); + arti.setRenewDays(Integer.parseInt(AAFSSO.cons.readLine("Renewal Days (%s):", "30"))); + arti.setNotification(toNotification(AAFSSO.cons.readLine("Notification (mailto owner):", ""))); + + TimeTaken tt = trans.start("Create Artifact", Env.REMOTE); + try { + Future future = aafcon.client(CM_VER).create("/cert/artifacts", artifactsDF, artifacts); + if(future.get(TIMEOUT)) { + trans.info().printf("Call to AAF Certman successful %s, %s",arti.getMechid(), arti.getMachine()); + } else { + trans.error().printf("Call to AAF Certman failed, %s", + errMsg.toMsg(future)); + } + } finally { + tt.done(); + } + } + + private static String toNotification(String notification) { + if(notification==null) { + notification=""; + } else if(notification.length()>0) { + if(notification.indexOf(':')<0) { + notification = "mailto:" + notification; + } + } + return notification; + } + + + private static void readArtifact(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { + String mechID = fqi(cmds); + String machine = machine(cmds); + + TimeTaken tt = trans.start("Read Artifact", Env.SUB); + try { + Future future = aafcon.client(CM_VER) + .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF,"Authorization","Bearer " + trans.getProperty("oauth_token")); + + if(future.get(TIMEOUT)) { + boolean printed = false; + for(Artifact a : future.value.getArtifact()) { + AAFSSO.cons.printf("MechID: %s\n",a.getMechid()); + AAFSSO.cons.printf(" Sponsor: %s\n",a.getSponsor()); + AAFSSO.cons.printf("Machine: %s\n",a.getMachine()); + AAFSSO.cons.printf("CA: %s\n",a.getCa()); + StringBuilder sb = new StringBuilder(); + boolean first = true; + for(String t : a.getType()) { + if(first) {first=false;} + else{sb.append(',');} + sb.append(t); + } + AAFSSO.cons.printf("Types: %s\n",sb); + AAFSSO.cons.printf("Namespace: %s\n",a.getNs()); + AAFSSO.cons.printf("Directory: %s\n",a.getDir()); + AAFSSO.cons.printf("O/S User: %s\n",a.getOsUser()); + AAFSSO.cons.printf("Renew Days: %d\n",a.getRenewDays()); + AAFSSO.cons.printf("Notification %s\n",a.getNotification()); + printed = true; + } + if(!printed) { + AAFSSO.cons.printf("Artifact for %s %s does not exist\n", mechID, machine); + } + } else { + trans.error().log(errMsg.toMsg(future)); + } + } finally { + tt.done(); + } + } + + private static void copyArtifact(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { + String mechID = fqi(cmds); + String machine = machine(cmds); + String[] newmachs = machines(cmds); + if(machine==null || newmachs == null) { + trans.error().log("No machines listed to copy to"); + } else { + TimeTaken tt = trans.start("Copy Artifact", Env.REMOTE); + try { + Future future = aafcon.client(CM_VER) + .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF); + + if(future.get(TIMEOUT)) { + boolean printed = false; + for(Artifact a : future.value.getArtifact()) { + for(String m : newmachs) { + a.setMachine(m); + Future fup = aafcon.client(CM_VER).update("/cert/artifacts", artifactsDF, future.value); + if(fup.get(TIMEOUT)) { + trans.info().printf("Copy of %s %s successful to %s",mechID,machine,m); + } else { + trans.error().printf("Call to AAF Certman failed, %s", + errMsg.toMsg(fup)); + } + + printed = true; + } + } + if(!printed) { + AAFSSO.cons.printf("Artifact for %s %s does not exist", mechID, machine); + } + } else { + trans.error().log(errMsg.toMsg(future)); + } + } finally { + tt.done(); + } + } + } + + private static void updateArtifact(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { + String mechID = fqi(cmds); + String machine = machine(cmds); + + TimeTaken tt = trans.start("Update Artifact", Env.REMOTE); + try { + Future fread = aafcon.client(CM_VER) + .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF); + + if(fread.get(TIMEOUT)) { + Artifacts artifacts = new Artifacts(); + for(Artifact a : fread.value.getArtifact()) { + Artifact arti = new Artifact(); + artifacts.getArtifact().add(arti); + + AAFSSO.cons.printf("For %s on %s\n", a.getMechid(),a.getMachine()); + arti.setMechid(a.getMechid()); + arti.setMachine(a.getMachine()); + arti.setCa(AAFSSO.cons.readLine("CA: (%s): ",a.getCa())); + StringBuilder sb = new StringBuilder(); + boolean first = true; + for(String t : a.getType()) { + if(first) {first=false;} + else{sb.append(',');} + sb.append(t); + } + + String resp = AAFSSO.cons.readLine("Types [file,jks,pkcs12] (%s): ", sb); + for(String s : Split.splitTrim(',', resp)) { + arti.getType().add(s); + } + // Always do Script + if(!resp.contains(SCRIPT)) { + arti.getType().add(SCRIPT); + } + + // Note: Sponsor is set on Creation by CM + arti.setNs(AAFSSO.cons.readLine("Namespace (%s): ",a.getNs())); + arti.setDir(AAFSSO.cons.readLine("Directory (%s): ", a.getDir())); + arti.setOsUser(AAFSSO.cons.readLine("OS User (%s): ", a.getOsUser())); + arti.setRenewDays(Integer.parseInt(AAFSSO.cons.readLine("Renew Days (%s):", a.getRenewDays()))); + arti.setNotification(toNotification(AAFSSO.cons.readLine("Notification (%s):", a.getNotification()))); + + } + if(artifacts.getArtifact().size()==0) { + AAFSSO.cons.printf("Artifact for %s %s does not exist", mechID, machine); + } else { + Future fup = aafcon.client(CM_VER).update("/cert/artifacts", artifactsDF, artifacts); + if(fup.get(TIMEOUT)) { + trans.info().printf("Call to AAF Certman successful %s, %s",mechID,machine); + } else { + trans.error().printf("Call to AAF Certman failed, %s", + errMsg.toMsg(fup)); + } + } + } else { + trans.error().printf("Call to AAF Certman failed, %s %s, %s", + errMsg.toMsg(fread),mechID,machine); + } + } finally { + tt.done(); + } + } + + private static void deleteArtifact(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { + String mechid = fqi(cmds); + String machine = machine(cmds); + + TimeTaken tt = trans.start("Delete Artifact", Env.REMOTE); + try { + Future future = aafcon.client(CM_VER) + .delete("/cert/artifacts/"+mechid+"/"+machine,"application/json" ); + + if(future.get(TIMEOUT)) { + trans.info().printf("Call to AAF Certman successful %s, %s",mechid,machine); + } else { + trans.error().printf("Call to AAF Certman failed, %s %s, %s", + errMsg.toMsg(future),mechid,machine); + } + } finally { + tt.done(); + } + } + + + + private static boolean placeCerts(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { + boolean rv = false; + String mechID = fqi(cmds); + String machine = machine(cmds); + String[] fqdns = Split.split(':', machine); + String key; + if(fqdns.length>1) { + key = fqdns[0]; + machine = fqdns[1]; + } else { + key = machine; + } + + TimeTaken tt = trans.start("Place Artifact", Env.REMOTE); + try { + Future acf = aafcon.client(CM_VER) + .read("/cert/artifacts/"+mechID+'/'+key, artifactsDF); + if(acf.get(TIMEOUT)) { + if(acf.value.getArtifact()==null || acf.value.getArtifact().isEmpty()) { + AAFSSO.cons.printf("===> There are no artifacts for %s on machine '%s'\n", mechID, key); + } else { + for(Artifact a : acf.value.getArtifact()) { + String osID = System.getProperty("user.name"); + if(a.getOsUser().equals(osID)) { + CertificateRequest cr = new CertificateRequest(); + cr.setMechid(a.getMechid()); + cr.setSponsor(a.getSponsor()); + for(int i=0;i f = aafcon.client(CM_VER) + .updateRespondString("/cert/" + a.getCa()+"?withTrust",reqDF, cr); + if(f.get(TIMEOUT)) { + CertInfo capi = certDF.newData().in(TYPE.JSON).load(f.body()).asObject(); + for(String type : a.getType()) { + PlaceArtifact pa = placeArtifact.get(type); + if(pa!=null) { + if(rv = pa.place(trans, capi, a,machine)) { + notifyPlaced(a,rv); + } + } + } + // Cover for the above multiple pass possibilities with some static Data, then clear per Artifact + } else { + trans.error().log(errMsg.toMsg(f)); + } + } else { + trans.error().log("You must be OS User \"" + a.getOsUser() +"\" to place Certificates on this box"); + } + } + } + } else { + trans.error().log(errMsg.toMsg(acf)); + } + } finally { + tt.done(); + } + return rv; + } + + private static void notifyPlaced(Artifact a, boolean rv) { + } + + private static void showPass(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { + String mechID = fqi(cmds); + String machine = machine(cmds); + + TimeTaken tt = trans.start("Show Password", Env.REMOTE); + try { + Future acf = aafcon.client(CM_VER) + .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF); + if(acf.get(TIMEOUT)) { + // Have to wait for JDK 1.7 source... + //switch(artifact.getType()) { + if(acf.value.getArtifact()==null || acf.value.getArtifact().isEmpty()) { + AAFSSO.cons.printf("No Artifacts found for %s on %s", mechID, machine); + } else { + String id = aafcon.defID(); + boolean allowed; + for(Artifact a : acf.value.getArtifact()) { + allowed = id!=null && (id.equals(a.getSponsor()) || + (id.equals(a.getMechid()) + && aafcon.securityInfo().defSS.getClass().isAssignableFrom(HBasicAuthSS.class))); + if(!allowed) { + Future pf = aafcon.client(CM_VER).read("/cert/may/" + + a.getNs() + ".certman|"+a.getCa()+"|showpass","*/*"); + if(pf.get(TIMEOUT)) { + allowed = true; + } else { + trans.error().log(errMsg.toMsg(pf)); + } + } + if(allowed) { + File dir = new File(a.getDir()); + Properties props = new Properties(); + FileInputStream fis = new FileInputStream(new File(dir,a.getNs()+".cred.props")); + try { + props.load(fis); + fis.close(); + fis = new FileInputStream(new File(dir,a.getNs()+".chal")); + props.load(fis); + } finally { + fis.close(); + } + + File f = new File(dir,a.getNs()+".keyfile"); + if(f.exists()) { + Symm symm = Symm.obtain(f); + + for(Iterator> iter = props.entrySet().iterator(); iter.hasNext();) { + Entry en = iter.next(); + if(en.getValue().toString().startsWith("enc:")) { + System.out.printf("%s=%s\n", en.getKey(), symm.depass(en.getValue().toString())); + } + } + } else { + trans.error().printf("%s.keyfile must exist to read passwords for %s on %s", + f.getAbsolutePath(),a.getMechid(), a.getMachine()); + } + } + } + } + } else { + trans.error().log(errMsg.toMsg(acf)); + } + } finally { + tt.done(); + } + + } + + + private static void initConfig(Trans trans, PropAccess pa, AAFCon aafcon, Deque cmds) throws Exception { + final String fqi = fqi(cmds); + final String locator = getProperty(pa,aafcon.env,false,Config.AAF_LOCATE_URL,"AAF Locator URL: "); + final String rootFile = FQI.reverseDomain(fqi); + final File dir = new File(pa.getProperty(Config.CADI_ETCDIR, ".")); + if(dir.exists()) { + System.out.println("Writing to " + dir.getCanonicalFile()); + } else if(dir.mkdirs()) { + System.out.println("Created directory " + dir.getCanonicalFile()); + } else { + System.err.println("Unable to create or write to " + dir.getCanonicalPath()); + return; + } + + TimeTaken tt = trans.start("Get Configuration", Env.REMOTE); + try { + boolean ok=false; + File fProps = File.createTempFile(rootFile, ".tmp",dir); + File fSecureTempProps = File.createTempFile(rootFile, ".cred.tmp",dir); + File fSecureProps = new File(dir,rootFile+".cred.props"); + PrintStream psProps; + + File fLocProps = new File(dir,rootFile + ".location.props"); + if(!fLocProps.exists()) { + psProps = new PrintStream(new FileOutputStream(fLocProps)); + try { + psProps.println(HASHES); + psProps.print("# Configuration File generated on "); + psProps.println(new Date().toString()); + psProps.println(HASHES); + for(String tag : new String[] {Config.CADI_LATITUDE,Config.CADI_LONGITUDE}) { + psProps.print(tag); + psProps.print('='); + psProps.println(getProperty(pa, trans, false, tag, "%s: ",tag)); + } + } finally { + psProps.close(); + } + } + + psProps = new PrintStream(new FileOutputStream(fProps)); + try { + PrintStream psCredProps = new PrintStream(new FileOutputStream(fSecureTempProps)); + try { + psCredProps.println(HASHES); + psCredProps.print("# Configuration File generated on "); + psCredProps.println(new Date().toString()); + psCredProps.println(HASHES); + + psProps.println(HASHES); + psProps.print("# Configuration File generated on "); + psProps.println(new Date().toString()); + psProps.println(HASHES); + + psProps.print(Config.CADI_PROP_FILES); + psProps.print('='); + psProps.print(fSecureProps.getCanonicalPath()); + psProps.print(File.pathSeparatorChar); + psProps.println(fLocProps.getCanonicalPath()); + + File fkf = new File(dir,rootFile+".keyfile"); + if(!fkf.exists()) { + CmdLine.main(new String[] {"keygen",fkf.toString()}); + } + psCredProps.print("cadi_keyfile="); + psCredProps.println(fkf.getCanonicalPath()); + + psCredProps.print(Config.AAF_APPID); + psCredProps.print('='); + psCredProps.println(fqi); + + Symm filesymm = Symm.obtain(fkf); + psCredProps.print(Config.AAF_APPPASS); + psCredProps.print("=enc:"); + String ps = pa.decrypt(pa.getProperty(Config.AAF_APPPASS), false); + ps = filesymm.enpass(ps); + psCredProps.println(ps); + + psCredProps.print(Config.CADI_TRUSTSTORE); + psCredProps.print("="); + File origTruststore = new File(pa.getProperty(Config.CADI_TRUSTSTORE)); + File newTruststore = new File(dir,origTruststore.getName()); + if(!newTruststore.exists()) { + Files.copy(origTruststore.toPath(), newTruststore.toPath()); + } + psCredProps.println(newTruststore.getCanonicalPath()); + + psCredProps.print(Config.CADI_TRUSTSTORE_PASSWORD); + psCredProps.print("=enc:"); + ps = pa.decrypt(pa.getProperty(Config.CADI_TRUSTSTORE_PASSWORD), false); + ps = filesymm.enpass(ps); + psCredProps.println(ps); + + try { + Future acf = aafcon.client(new SingleEndpointLocator(locator)) + .read("/configure/"+fqi+"/aaf", configDF); + if(acf.get(TIMEOUT)) { + // out.println(acf.value.getName()); + for(Props props : acf.value.getProps()) { + psProps.println(props.getTag() + '=' + props.getValue()); + } + ok = true; + } else if(acf.code()==401){ + trans.error().log("Bad Password sent to AAF"); + } else { + trans.error().log(errMsg.toMsg(acf)); + } + } finally { + psProps.close(); + } + if(ok) { + File newFile = new File(dir,rootFile+".props"); + fProps.renameTo(newFile); + System.out.println("Created " + newFile.getCanonicalPath()); + fProps = newFile; + + fSecureTempProps.renameTo(fSecureProps); + System.out.println("Created " + fSecureProps.getCanonicalPath()); + fProps = newFile; + } else { + fProps.delete(); + fSecureTempProps.delete(); + } + } finally { + psCredProps.close(); + } + } finally { + psProps.close(); + } + } finally { + tt.done(); + } + } + + private static void validate(final PropAccess pa) throws LocatorException, CadiException, APIException { + System.out.println("Validating Configuration..."); + final AAFCon aafcon = new AAFConHttp(pa,Config.AAF_URL,new SecurityInfoC(pa)); + aafcon.best(new Retryable() { + @Override + public Void code(Rcli client) throws CadiException, ConnectException, APIException { + Future fc = client.read("/authz/perms/user/"+aafcon.defID(),permDF); + if(fc.get(aafcon.timeout)) { + System.out.print("Success connecting to "); + System.out.println(client.getURI()); + System.out.print(" Permissions for "); + System.out.println(aafcon.defID()); + for(Perm p : fc.value.getPerm()) { + System.out.print('\t'); + System.out.print(p.getType()); + System.out.print('|'); + System.out.print(p.getInstance()); + System.out.print('|'); + System.out.println(p.getAction()); + } + } else { + System.err.println("Error: " + fc.code() + ' ' + fc.body()); + } + return null; + } + }); + } + + /** + * Check returns Error Codes, so that Scripts can know what to do + * + * 0 - Check Complete, nothing to do + * 1 - General Error + * 2 - Error for specific Artifact - read check.msg + * 10 - Certificate Updated - check.msg is email content + * + * @param trans + * @param aafcon + * @param cmds + * @return + * @throws Exception + */ + private static int check(Trans trans, AAFCon aafcon, Deque cmds) throws Exception { + int exitCode=1; + String mechID = fqi(cmds); + String machine = machine(cmds); + + TimeTaken tt = trans.start("Check Certificate", Env.REMOTE); + try { + + Future acf = aafcon.client(CM_VER) + .read("/cert/artifacts/"+mechID+'/'+machine, artifactsDF); + if(acf.get(TIMEOUT)) { + // Have to wait for JDK 1.7 source... + //switch(artifact.getType()) { + if(acf.value.getArtifact()==null || acf.value.getArtifact().isEmpty()) { + AAFSSO.cons.printf("No Artifacts found for %s on %s", mechID, machine); + } else { + String id = aafcon.defID(); + GregorianCalendar now = new GregorianCalendar(); + for(Artifact a : acf.value.getArtifact()) { + if(id.equals(a.getMechid())) { + File dir = new File(a.getDir()); + Properties props = new Properties(); + FileInputStream fis = new FileInputStream(new File(dir,a.getNs()+".props")); + try { + props.load(fis); + } finally { + fis.close(); + } + + String prop; + File f; + + if((prop=props.getProperty(Config.CADI_KEYFILE))==null || + !(f=new File(prop)).exists()) { + trans.error().printf("Keyfile must exist to check Certificates for %s on %s", + a.getMechid(), a.getMachine()); + } else { + String ksf = props.getProperty(Config.CADI_KEYSTORE); + String ksps = props.getProperty(Config.CADI_KEYSTORE_PASSWORD); + if(ksf==null || ksps == null) { + trans.error().printf("Properties %s and %s must exist to check Certificates for %s on %s", + Config.CADI_KEYSTORE, Config.CADI_KEYSTORE_PASSWORD,a.getMechid(), a.getMachine()); + } else { + KeyStore ks = KeyStore.getInstance("JKS"); + Symm symm = Symm.obtain(f); + + fis = new FileInputStream(ksf); + try { + ks.load(fis,symm.depass(ksps).toCharArray()); + } finally { + fis.close(); + } + X509Certificate cert = (X509Certificate)ks.getCertificate(mechID); + String msg = null; + + if(cert==null) { + msg = String.format("X509Certificate does not exist for %s on %s in %s", + a.getMechid(), a.getMachine(), ksf); + trans.error().log(msg); + exitCode = 2; + } else { + GregorianCalendar renew = new GregorianCalendar(); + renew.setTime(cert.getNotAfter()); + renew.add(GregorianCalendar.DAY_OF_MONTH,-1*a.getRenewDays()); + if(renew.after(now)) { + msg = String.format("X509Certificate for %s on %s has been checked on %s. It expires on %s; it will not be renewed until %s.\n", + a.getMechid(), a.getMachine(),Chrono.dateOnlyStamp(now),cert.getNotAfter(),Chrono.dateOnlyStamp(renew)); + trans.info().log(msg); + exitCode = 0; // OK + } else { + trans.info().printf("X509Certificate for %s on %s expiration, %s, needs Renewal.\n", + a.getMechid(), a.getMachine(),cert.getNotAfter()); + cmds.offerLast(mechID); + cmds.offerLast(machine); + if(placeCerts(trans,aafcon,cmds)) { + msg = String.format("X509Certificate for %s on %s has been renewed. Ensure services using are refreshed.\n", + a.getMechid(), a.getMachine()); + exitCode = 10; // Refreshed + } else { + msg = String.format("X509Certificate for %s on %s attempted renewal, but failed. Immediate Investigation is required!\n", + a.getMechid(), a.getMachine()); + exitCode = 1; // Error Renewing + } + } + } + if(msg!=null) { + FileOutputStream fos = new FileOutputStream(a.getDir()+'/'+a.getNs()+".msg"); + try { + fos.write(msg.getBytes()); + } finally { + fos.close(); + } + } + } + + } + } + } + } + } else { + trans.error().log(errMsg.toMsg(acf)); + exitCode=1; + } + } finally { + tt.done(); + } + return exitCode; + } + +} + + + + diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/ArtifactDir.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/ArtifactDir.java new file mode 100644 index 00000000..74cf4e4b --- /dev/null +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/ArtifactDir.java @@ -0,0 +1,288 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.cadi.configure; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.security.KeyStore; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.onap.aaf.cadi.CadiException; +import org.onap.aaf.cadi.Symm; +import org.onap.aaf.cadi.config.Config; +import org.onap.aaf.cadi.util.Chmod; +import org.onap.aaf.misc.env.Trans; +import org.onap.aaf.misc.env.util.Chrono; + +import certman.v1_0.Artifacts.Artifact; +import certman.v1_0.CertInfo; + +public abstract class ArtifactDir implements PlaceArtifact { + + protected static final String C_R = "\n"; + protected File dir; + private List encodeds = new ArrayList(); + + private Symm symm; + // This checks for multiple passes of Dir on the same objects. Run clear after done. + protected static Map processed = new HashMap(); + + + /** + * Note: Derived Classes should ALWAYS call "super.place(cert,arti)" first, and + * then "placeProperties(arti)" just after they implement + */ + @Override + public final boolean place(Trans trans, CertInfo certInfo, Artifact arti, String machine) throws CadiException { + validate(arti); + + try { + // Obtain/setup directory as required + dir = new File(arti.getDir()); + if(processed.get("dir")==null) { + if(!dir.exists()) { + Chmod.to755.chmod(dir); + if(!dir.mkdirs()) { + throw new CadiException("Could not create " + dir); + } + } + + // Also place cm_url and Host Name + addProperty(Config.CM_URL,trans.getProperty(Config.CM_URL)); +// addProperty(Config.HOSTNAME,machine); +// addProperty(Config.AAF_ENV,certInfo.getEnv()); + // Obtain Issuers + boolean first = true; + StringBuilder issuers = new StringBuilder(); + for(String dn : certInfo.getCaIssuerDNs()) { + if(first) { + first=false; + } else { + issuers.append(':'); + } + issuers.append(dn); + } + addProperty(Config.CADI_X509_ISSUERS,issuers.toString()); + } + symm = (Symm)processed.get("symm"); + if(symm==null) { + // CADI Key Gen + File f = new File(dir,arti.getNs() + ".keyfile"); + if(!f.exists()) { + write(f,Chmod.to400,Symm.keygen()); + } + symm = Symm.obtain(f); + + addEncProperty("ChallengePassword", certInfo.getChallenge()); + + processed.put("symm",symm); + } + + _place(trans, certInfo,arti); + + placeProperties(arti); + + processed.put("dir",dir); + + } catch (Exception e) { + throw new CadiException(e); + } + return true; + } + + /** + * Derived Classes implement this instead, so Dir can process first, and write any Properties last + * @param cert + * @param arti + * @return + * @throws CadiException + */ + protected abstract boolean _place(Trans trans, CertInfo certInfo, Artifact arti) throws CadiException; + + protected void addProperty(String tag, String value) throws IOException { + StringBuilder sb = new StringBuilder(); + sb.append(tag); + sb.append('='); + sb.append(value); + encodeds.add(sb.toString()); + } + + protected void addEncProperty(String tag, String value) throws IOException { + StringBuilder sb = new StringBuilder(); + sb.append(tag); + sb.append('='); + sb.append("enc:"); + sb.append(symm.enpass(value)); + encodeds.add(sb.toString()); + } + + protected void write(File f, Chmod c, String ... data) throws IOException { + f.setWritable(true,true); + + FileOutputStream fos = new FileOutputStream(f); + PrintStream ps = new PrintStream(fos); + try { + for(String s : data) { + ps.print(s); + } + } finally { + ps.close(); + c.chmod(f); + } + } + + protected void write(File f, Chmod c, byte[] bytes) throws IOException { + f.setWritable(true,true); + + FileOutputStream fos = new FileOutputStream(f); + try { + fos.write(bytes); + } finally { + fos.close(); + c.chmod(f); + } + } + + protected void write(File f, Chmod c, KeyStore ks, char[] pass ) throws IOException, CadiException { + f.setWritable(true,true); + + FileOutputStream fos = new FileOutputStream(f); + try { + ks.store(fos, pass); + } catch (Exception e) { + throw new CadiException(e); + } finally { + fos.close(); + c.chmod(f); + } + } + + + private void validate(Artifact a) throws CadiException { + StringBuilder sb = new StringBuilder(); + if(a.getDir()==null) { + sb.append("File Artifacts require a path"); + } + + if(a.getNs()==null) { + if(sb.length()>0) { + sb.append('\n'); + } + sb.append("File Artifacts require an AAF Namespace"); + } + + if(sb.length()>0) { + throw new CadiException(sb.toString()); + } + } + + private boolean placeProperties(Artifact arti) throws CadiException { + if(encodeds.size()==0) { + return true; + } + boolean first=processed.get("dir")==null; + try { + File f = new File(dir,arti.getNs()+".cred.props"); + if(f.exists()) { + if(first) { + File backup = File.createTempFile(f.getName()+'.', ".backup",dir); + f.renameTo(backup); + } else { + f.setWritable(true); + } + } + + // Append if not first + PrintWriter pw = new PrintWriter(new FileWriter(f,!first)); + try { + // Write a Header + if(first) { + for(int i=0;i<60;++i) { + pw.print('#'); + } + pw.println(); + pw.println("# Properties Generated by AT&T Certificate Manager"); + pw.print("# by "); + pw.println(System.getProperty("user.name")); + pw.print("# on "); + pw.println(Chrono.dateStamp()); + pw.println("# @copyright 2016, AT&T"); + for(int i=0;i<60;++i) { + pw.print('#'); + } + pw.println(); + for(String prop : encodeds) { + if( prop.startsWith("cm_") + || prop.startsWith(Config.HOSTNAME) + || prop.startsWith(Config.AAF_ENV)) { + pw.println(prop); + } + } + } + + for(String prop : encodeds) { + if(prop.startsWith("cadi")) { + pw.println(prop); + } + } + } finally { + pw.close(); + } + Chmod.to644.chmod(f); + + if(first) { + // Challenge + f = new File(dir,arti.getNs()+".chal"); + if(f.exists()) { + f.delete(); + } + pw = new PrintWriter(new FileWriter(f)); + try { + for(String prop : encodeds) { + if(prop.startsWith("Challenge")) { + pw.println(prop); + } + } + } finally { + pw.close(); + } + Chmod.to400.chmod(f); + } + } catch(Exception e) { + throw new CadiException(e); + } + return true; + } + + public static void clear() { + processed.clear(); + } + +} diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/CertException.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/CertException.java new file mode 100644 index 00000000..4ea5e335 --- /dev/null +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/CertException.java @@ -0,0 +1,45 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.cadi.configure; + +public class CertException extends Exception { + + /** + * + */ + private static final long serialVersionUID = 1373028409048516401L; + + public CertException() { + } + + public CertException(String message) { + super(message); + } + + public CertException(Throwable cause) { + super(cause); + } + + public CertException(String message, Throwable cause) { + super(message, cause); + } +} \ No newline at end of file diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/Factory.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/Factory.java new file mode 100644 index 00000000..5bb99131 --- /dev/null +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/Factory.java @@ -0,0 +1,504 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.cadi.configure; + +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; +import java.io.StringReader; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.security.InvalidKeyException; +import java.security.Key; +import java.security.KeyFactory; +import java.security.KeyPair; +import java.security.KeyPairGenerator; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.Provider; +import java.security.PublicKey; +import java.security.SecureRandom; +import java.security.Security; +import java.security.Signature; +import java.security.SignatureException; +import java.security.cert.Certificate; +import java.security.cert.CertificateEncodingException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.Collection; +import java.util.List; + +import javax.crypto.Cipher; +import javax.crypto.NoSuchPaddingException; + +import org.onap.aaf.cadi.Symm; +import org.onap.aaf.cadi.client.Holder; +import org.onap.aaf.misc.env.Env; +import org.onap.aaf.misc.env.TimeTaken; +import org.onap.aaf.misc.env.Trans; + +public class Factory { + private static final String PRIVATE_KEY_HEADER = "PRIVATE KEY"; + public static final String KEY_ALGO = "RSA"; + public static final String SIG_ALGO = "SHA256withRSA"; + + public static final int KEY_LENGTH = 2048; + private static final KeyPairGenerator keygen; + private static final KeyFactory keyFactory; + private static final CertificateFactory certificateFactory; + private static final SecureRandom random; + + + private static final Symm base64 = Symm.base64.copy(64); + + static { + random = new SecureRandom(); + KeyPairGenerator tempKeygen; + try { + tempKeygen = KeyPairGenerator.getInstance(KEY_ALGO);//,"BC"); + tempKeygen.initialize(KEY_LENGTH, random); + } catch (NoSuchAlgorithmException e) { + tempKeygen = null; + e.printStackTrace(System.err); + } + keygen = tempKeygen; + + KeyFactory tempKeyFactory; + try { + tempKeyFactory=KeyFactory.getInstance(KEY_ALGO);//,"BC" + } catch (NoSuchAlgorithmException e) { + tempKeyFactory = null; + e.printStackTrace(System.err); + }; + keyFactory = tempKeyFactory; + + CertificateFactory tempCertificateFactory; + try { + tempCertificateFactory = CertificateFactory.getInstance("X.509"); + } catch (CertificateException e) { + tempCertificateFactory = null; + e.printStackTrace(System.err); + } + certificateFactory = tempCertificateFactory; + + + } + + + public static KeyPair generateKeyPair(Trans trans) { + TimeTaken tt; + if(trans!=null) { + tt = trans.start("Generate KeyPair", Env.SUB); + } else { + tt = null; + } + try { + return keygen.generateKeyPair(); + } finally { + if(tt!=null) { + tt.done(); + } + } + } + + private static final String LINE_END = "-----\n"; + + protected static String textBuilder(String kind, byte[] bytes) throws IOException { + StringBuilder sb = new StringBuilder(); + sb.append("-----BEGIN "); + sb.append(kind); + sb.append(LINE_END); + + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + base64.encode(bais, baos); + sb.append(new String(baos.toByteArray())); + + if(sb.charAt(sb.length()-1)!='\n') { + sb.append('\n'); + } + sb.append("-----END "); + sb.append(kind); + sb.append(LINE_END); + return sb.toString(); + } + + public static PrivateKey toPrivateKey(Trans trans, String pk) throws IOException, CertException { + byte[] bytes = decode(new StringReader(pk), null); + return toPrivateKey(trans, bytes); + } + + public static PrivateKey toPrivateKey(Trans trans, byte[] bytes) throws IOException, CertException { + TimeTaken tt=trans.start("Reconstitute Private Key", Env.SUB); + try { + return keyFactory.generatePrivate(new PKCS8EncodedKeySpec(bytes)); + } catch (InvalidKeySpecException e) { + throw new CertException("Translating Private Key from PKCS8 KeySpec",e); + } finally { + tt.done(); + } + } + + public static PrivateKey toPrivateKey(Trans trans, File file) throws IOException, CertException { + TimeTaken tt = trans.start("Decode Private Key File", Env.SUB); + try { + Holder firstLine = new Holder(null); + return toPrivateKey(trans,decode(file,firstLine)); + }finally { + tt.done(); + } + } + + public static String toString(Trans trans, PrivateKey pk) throws IOException { +// PKCS8EncodedKeySpec pemContents = new PKCS8EncodedKeySpec(pk.getEncoded()); + trans.debug().log("Private Key to String"); + return textBuilder(PRIVATE_KEY_HEADER,pk.getEncoded()); + } + + public static PublicKey toPublicKey(Trans trans, String pk) throws IOException { + TimeTaken tt = trans.start("Reconstitute Public Key", Env.SUB); + try { + ByteArrayInputStream bais = new ByteArrayInputStream(pk.getBytes()); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + Symm.base64noSplit.decode(new StripperInputStream(bais), baos); + + return keyFactory.generatePublic(new X509EncodedKeySpec(baos.toByteArray())); + } catch (InvalidKeySpecException e) { + trans.error().log(e,"Translating Public Key from X509 KeySpec"); + return null; + } finally { + tt.done(); + } + } + + public static String toString(Trans trans, PublicKey pk) throws IOException { + trans.debug().log("Public Key to String"); + return textBuilder("PUBLIC KEY",pk.getEncoded()); + } + + public static Collection toX509Certificate(String x509) throws CertificateException { + return toX509Certificate(x509.getBytes()); + } + + public static Collection toX509Certificate(List x509s) throws CertificateException { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + try { + for(String x509 : x509s) { + baos.write(x509.getBytes()); + } + } catch (IOException e) { + throw new CertificateException(e); + } + return toX509Certificate(new ByteArrayInputStream(baos.toByteArray())); + } + + public static Collection toX509Certificate(byte[] x509) throws CertificateException { + return certificateFactory.generateCertificates(new ByteArrayInputStream(x509)); + } + + public static Collection toX509Certificate(Trans trans, File file) throws CertificateException, FileNotFoundException { + FileInputStream fis = new FileInputStream(file); + try { + try { + return toX509Certificate(fis); + } finally { + fis.close(); + } + } catch (IOException e) { + throw new CertificateException(e); + } + } + + public static Collection toX509Certificate(InputStream is) throws CertificateException { + return certificateFactory.generateCertificates(is); + } + + public static String toString(Trans trans, Certificate cert) throws IOException, CertException { + if(trans.debug().isLoggable()) { + StringBuilder sb = new StringBuilder("Certificate to String"); + if(cert instanceof X509Certificate) { + sb.append(" - "); + sb.append(((X509Certificate)cert).getSubjectDN()); + } + trans.debug().log(sb); + } + try { + if(cert==null) { + throw new CertException("Certificate not built"); + } + return textBuilder("CERTIFICATE",cert.getEncoded()); + } catch (CertificateEncodingException e) { + throw new CertException(e); + } + } + + public static Cipher pkCipher() throws NoSuchAlgorithmException, NoSuchPaddingException { + return Cipher.getInstance(KEY_ALGO); + } + + public static Cipher pkCipher(Key key, boolean encrypt) throws InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException { + Cipher cipher = Cipher.getInstance(KEY_ALGO); + cipher.init(encrypt?Cipher.ENCRYPT_MODE:Cipher.DECRYPT_MODE,key); + return cipher; + } + + public static byte[] strip(Reader rdr) throws IOException { + return strip(rdr,null); + } + + public static byte[] strip(Reader rdr, Holder hs) throws IOException { + BufferedReader br = new BufferedReader(rdr); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + String line; + boolean notStarted = true; + while((line=br.readLine())!=null) { + if(notStarted) { + if(line.startsWith("-----")) { + notStarted = false; + if(hs!=null) { + hs.set(line); + } + } else { + continue; + } + } + if(line.length()>0 && + !line.startsWith("-----") && + line.indexOf(':')<0) { // Header elements + baos.write(line.getBytes()); + } + } + return baos.toByteArray(); + } + + public static class StripperInputStream extends InputStream { + private Reader created; + private BufferedReader br; + private int idx; + private String line; + + public StripperInputStream(Reader rdr) { + if(rdr instanceof BufferedReader) { + br = (BufferedReader)rdr; + } else { + br = new BufferedReader(rdr); + } + created = null; + } + + public StripperInputStream(File file) throws FileNotFoundException { + this(new FileReader(file)); + created = br; + } + + public StripperInputStream(InputStream is) throws FileNotFoundException { + this(new InputStreamReader(is)); + created = br; + } + + @Override + public int read() throws IOException { + if(line==null || idx>=line.length()) { + while((line=br.readLine())!=null) { + if(line.length()>0 && + !line.startsWith("-----") && + line.indexOf(':')<0) { // Header elements + break; + } + } + + if(line==null) { + return -1; + } + idx = 0; + } + return line.charAt(idx++); + } + + /* (non-Javadoc) + * @see java.io.InputStream#close() + */ + @Override + public void close() throws IOException { + if(created!=null) { + created.close(); + } + } + } + + public static class Base64InputStream extends InputStream { + private InputStream created; + private InputStream is; + private byte trio[]; + private byte duo[]; + private int idx; + + + public Base64InputStream(File file) throws FileNotFoundException { + this(new FileInputStream(file)); + created = is; + } + + public Base64InputStream(InputStream is) throws FileNotFoundException { + this.is = is; + trio = new byte[3]; + idx = 4; + } + + @Override + public int read() throws IOException { + if(duo==null || idx>=duo.length) { + int read = is.read(trio); + if(read==-1) { + return -1; + } + duo = Symm.base64.decode(trio); + if(duo==null || duo.length==0) { + return -1; + } + idx=0; + } + + return duo[idx++]; + } + + /* (non-Javadoc) + * @see java.io.InputStream#close() + */ + @Override + public void close() throws IOException { + if(created!=null) { + created.close(); + } + } + } + + public static byte[] decode(byte[] bytes) throws IOException { + ByteArrayInputStream bais = new ByteArrayInputStream(bytes); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + Symm.base64.decode(bais, baos); + return baos.toByteArray(); + } + + public static byte[] decode(File f, Holder hs) throws IOException { + FileReader fr = new FileReader(f); + try { + return Factory.decode(fr,hs); + } finally { + fr.close(); + } + } + + + public static byte[] decode(Reader rdr,Holder hs) throws IOException { + return decode(strip(rdr,hs)); + } + + + public static byte[] binary(File file) throws IOException { + DataInputStream dis = new DataInputStream(new FileInputStream(file)); + try { + byte[] bytes = new byte[(int)file.length()]; + dis.readFully(bytes); + return bytes; + } finally { + dis.close(); + } + } + + + public static byte[] sign(Trans trans, byte[] bytes, PrivateKey pk) throws IOException, InvalidKeyException, SignatureException, NoSuchAlgorithmException { + TimeTaken tt = trans.start("Sign Data", Env.SUB); + try { + Signature sig = Signature.getInstance(SIG_ALGO); + sig.initSign(pk, random); + sig.update(bytes); + return sig.sign(); + } finally { + tt.done(); + } + } + + public static String toSignatureString(byte[] signed) throws IOException { + return textBuilder("SIGNATURE", signed); + } + + public static boolean verify(Trans trans, byte[] bytes, byte[] signature, PublicKey pk) throws NoSuchAlgorithmException, InvalidKeyException, SignatureException { + TimeTaken tt = trans.start("Verify Data", Env.SUB); + try { + Signature sig = Signature.getInstance(SIG_ALGO); + sig.initVerify(pk); + sig.update(bytes); + return sig.verify(signature); + } finally { + tt.done(); + } + } + + /** + * Get the Security Provider, or, if not exists yet, attempt to load + * + * @param providerType + * @param params + * @return + * @throws CertException + */ + public static synchronized Provider getSecurityProvider(String providerType, String[][] params) throws CertException { + Provider p = Security.getProvider(providerType); + if(p!=null) { + switch(providerType) { + case "PKCS12": + + break; + case "PKCS11": // PKCS11 only known to be supported by Sun + try { + Class clsSunPKCS11 = Class.forName("sun.security.pkcs11.SunPKCS11"); + Constructor cnst = clsSunPKCS11.getConstructor(String.class); + Object sunPKCS11 = cnst.newInstance(params[0][0]); + if (sunPKCS11==null) { + throw new CertException("SunPKCS11 Provider cannot be constructed for " + params[0][0]); + } + Security.addProvider((Provider)sunPKCS11); + } catch (ClassNotFoundException | NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + throw new CertException(e); + } + break; + default: + throw new CertException(providerType + " is not a known Security Provider for your JDK."); + } + } + return p; + } +} diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifact.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifact.java new file mode 100644 index 00000000..4b200c04 --- /dev/null +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifact.java @@ -0,0 +1,32 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.cadi.configure; + +import certman.v1_0.Artifacts.Artifact; +import certman.v1_0.CertInfo; + +import org.onap.aaf.cadi.CadiException; +import org.onap.aaf.misc.env.Trans; + +public interface PlaceArtifact { + public boolean place(Trans trans, CertInfo cert, Artifact arti, String machine) throws CadiException; +} diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactInFiles.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactInFiles.java new file mode 100644 index 00000000..25fe776c --- /dev/null +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactInFiles.java @@ -0,0 +1,53 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.cadi.configure; + +import java.io.File; + +import org.onap.aaf.cadi.CadiException; +import org.onap.aaf.cadi.util.Chmod; +import org.onap.aaf.misc.env.Trans; + +import certman.v1_0.Artifacts.Artifact; +import certman.v1_0.CertInfo; + +public class PlaceArtifactInFiles extends ArtifactDir { + @Override + public boolean _place(Trans trans, CertInfo certInfo, Artifact arti) throws CadiException { + try { + // Setup Public Cert + File f = new File(dir,arti.getNs()+".crt"); + // In Version 1.0, App Cert is first + write(f,Chmod.to644,certInfo.getCerts().get(0),C_R); + + // Setup Private Key + f = new File(dir,arti.getNs()+".key"); + write(f,Chmod.to400,certInfo.getPrivatekey(),C_R); + + } catch (Exception e) { + throw new CadiException(e); + } + return true; + } +} + + diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactInKeystore.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactInKeystore.java new file mode 100644 index 00000000..2a522bc1 --- /dev/null +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactInKeystore.java @@ -0,0 +1,150 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.cadi.configure; + +import java.io.File; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.onap.aaf.cadi.CadiException; +import org.onap.aaf.cadi.Symm; +import org.onap.aaf.cadi.config.Config; +import org.onap.aaf.cadi.util.Chmod; +import org.onap.aaf.misc.env.Trans; + +import certman.v1_0.Artifacts.Artifact; +import certman.v1_0.CertInfo; + +public class PlaceArtifactInKeystore extends ArtifactDir { + private String kst; + + public PlaceArtifactInKeystore(String kst) { + this.kst = kst; + } + + @Override + public boolean _place(Trans trans, CertInfo certInfo, Artifact arti) throws CadiException { + File fks = new File(dir,arti.getNs()+'.'+kst); + try { + KeyStore jks = KeyStore.getInstance(kst); + if(fks.exists()) { + File backup = File.createTempFile(fks.getName()+'.', ".backup",dir); + fks.renameTo(backup); + } + + // Get the Cert(s)... Might include Trust store + Collection certColl = Factory.toX509Certificate(certInfo.getCerts()); + // find where the trusts end in 1.0 API + + X509Certificate x509; + List chainList = new ArrayList(); + Set caSet = new HashSet(); + for(Certificate c : certColl) { + x509 = (X509Certificate)c; + // Is a Root (self-signed, anyway) + if(x509.getSubjectDN().equals(x509.getIssuerDN())) { + caSet.add(x509); + } else { + chainList.add(x509); + } + } +// chainList.addAll(caSet); + //Collections.reverse(chainList); + + // Properties, etc + // Add CADI Keyfile Entry to Properties + addProperty(Config.CADI_KEYFILE,arti.getDir()+'/'+arti.getNs() + ".keyfile"); + // Set Keystore Password + addProperty(Config.CADI_KEYSTORE,fks.getAbsolutePath()); + String keystorePass = Symm.randomGen(Agent.PASS_SIZE); + addEncProperty(Config.CADI_KEYSTORE_PASSWORD,keystorePass); + char[] keystorePassArray = keystorePass.toCharArray(); + jks.load(null,keystorePassArray); // load in + + // Add Private Key/Cert Entry for App + // Note: Java SSL security classes, while having a separate key from keystore, + // is documented to not actually work. + // java.security.UnrecoverableKeyException: Cannot recover key + // You can create a custom Key Manager to make it work, but Practicality + // dictates that you live with the default, meaning, they are the same + String keyPass = keystorePass; //Symm.randomGen(CmAgent.PASS_SIZE); + PrivateKey pk = Factory.toPrivateKey(trans, certInfo.getPrivatekey()); + addEncProperty(Config.CADI_KEY_PASSWORD, keyPass); + addProperty(Config.CADI_ALIAS, arti.getMechid()); +// Set attribs = new HashSet(); +// if(kst.equals("pkcs12")) { +// // Friendly Name +// attribs.add(new PKCS12Attribute("1.2.840.113549.1.9.20", arti.getNs())); +// } +// + KeyStore.ProtectionParameter protParam = + new KeyStore.PasswordProtection(keyPass.toCharArray()); + + Certificate[] trustChain = new Certificate[chainList.size()]; + chainList.toArray(trustChain); + KeyStore.PrivateKeyEntry pkEntry = + new KeyStore.PrivateKeyEntry(pk, trustChain); + jks.setEntry(arti.getMechid(), + pkEntry, protParam); + + // Write out + write(fks,Chmod.to400,jks,keystorePassArray); + + // Change out to TrustStore + fks = new File(dir,arti.getNs()+".trust."+kst); + if(fks.exists()) { + File backup = File.createTempFile(fks.getName()+'.', ".backup",dir); + fks.renameTo(backup); + } + + jks = KeyStore.getInstance(kst); + + // Set Truststore Password + addProperty(Config.CADI_TRUSTSTORE,fks.getAbsolutePath()); + String trustStorePass = Symm.randomGen(Agent.PASS_SIZE); + addEncProperty(Config.CADI_TRUSTSTORE_PASSWORD,trustStorePass); + char[] truststorePassArray = trustStorePass.toCharArray(); + jks.load(null,truststorePassArray); // load in + + // Add Trusted Certificates, but PKCS12 doesn't support + Certificate[] trustCAs = new Certificate[caSet.size()]; + caSet.toArray(trustCAs); + for(int i=0; i0) { + trans.info().printf("Warning: %s\n",capi.getNotes()); + } + out.printf("Challenge: %s\n",capi.getChallenge()); + out.printf("PrivateKey:\n%s\n",capi.getPrivatekey()); + out.println("Certificate Chain:"); + for(String c : capi.getCerts()) { + out.println(c); + } + return true; + } +} diff --git a/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactScripts.java b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactScripts.java new file mode 100644 index 00000000..84161b50 --- /dev/null +++ b/cadi/aaf/src/main/java/org/onap/aaf/cadi/configure/PlaceArtifactScripts.java @@ -0,0 +1,157 @@ +/** + * ============LICENSE_START==================================================== + * org.onap.aaf + * =========================================================================== + * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved. + * =========================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END==================================================== + * + */ + +package org.onap.aaf.cadi.configure; + +import java.io.File; + +import org.onap.aaf.cadi.CadiException; +import org.onap.aaf.cadi.util.Chmod; +import org.onap.aaf.misc.env.Trans; +import org.onap.aaf.misc.env.util.Chrono; +import org.onap.aaf.misc.env.util.Split; + +import certman.v1_0.Artifacts.Artifact; +import certman.v1_0.CertInfo; + +public class PlaceArtifactScripts extends ArtifactDir { + @Override + public boolean _place(Trans trans, CertInfo certInfo, Artifact arti) throws CadiException { + try { + // Setup check.sh script + String filename = arti.getNs()+".check.sh"; + File f1 = new File(dir,filename); + String email = arti.getNotification() + '\n'; + if(email.startsWith("mailto:")) { + email=email.substring(7); + } else { + email=arti.getOsUser() + '\n'; + } + + StringBuilder classpath = new StringBuilder(); + boolean first = true; + for(String pth : Split.split(File.pathSeparatorChar, System.getProperty("java.class.path"))) { + if(first) { + first=false; + } else { + classpath.append(File.pathSeparatorChar); + } + File f = new File(pth); + classpath.append(f.getCanonicalPath().replaceAll("[0-9]+\\.[0-9]+\\.[0-9]+","*")); + } + + write(f1,Chmod.to644, + "#!/bin/bash " + f1.getCanonicalPath()+'\n', + "# Certificate Manager Check Script\n", + "# Check on Certificate, and renew if needed.\n", + "# Generated by Certificate Manager " + Chrono.timeStamp()+'\n', + "DIR="+arti.getDir()+'\n', + "APP="+arti.getNs()+'\n', + "EMAIL="+email, + "CP=\""+classpath.toString()+"\"\n", + checkScript + ); + + // Setup check.sh script + File f2 = new File(dir,arti.getNs()+".crontab.sh"); + write(f2,Chmod.to644, + "#!/bin/bash " + f2.getCanonicalPath()+'\n', + "# Certificate Manager Crontab Loading Script\n", + "# Add/Update a Crontab entry, that adds a check on Certificate Manager generated Certificate nightly.\n", + "# Generated by Certificate Manager " + Chrono.timeStamp()+'\n', + "TFILE=\"/tmp/cmcron$$.temp\"\n", + "DIR=\""+arti.getDir()+"\"\n", + "CF=\""+arti.getNs()+" Certificate Check Script\"\n", + "SCRIPT=\""+f1.getCanonicalPath()+"\"\n", + cronScript + ); + + } catch (Exception e) { + throw new CadiException(e); + } + return true; + } + + /** + * Note: java.home gets Absolute Path of Java, where we probably want soft links from + * JAVA_HOME + * @return + */ + private final static String javaHome() { + String rc = System.getenv("JAVA_HOME"); + return rc==null?System.getProperty("java.home"):rc; + } + private final static String checkScript = + "> $DIR/$APP.msg\n\n" + + "function mailit {\n" + + " if [ -e /bin/mail ]; then\n" + + " MAILER=/bin/mail\n" + + " elif [ -e /usr/bin/mail ]; then \n" + + " MAILER=/usr/bin/mail\n" + + " else \n" + + " MAILER=\"\"\n" + + " fi\n" + + " if [ \"$MAILER\" = \"\" ]; then\n" + + " printf \"$*\"\n" + + " else \n" + + " printf \"$*\" | $MAILER -s \"AAF Certman Notification for `uname -n`\" $EMAIL\n"+ + " fi\n" + + "}\n\n" + + javaHome() + "/bin/" +"java -cp $CP " + + Agent.class.getName() + + " cadi_prop_files=$DIR/$APP.props check 2> $DIR/$APP.STDERR > $DIR/$APP.STDOUT\n" + + "case \"$?\" in\n" + + " 0)\n" + + " # Note: Validation will be mailed only the first day after any modification\n" + + " if [ \"`find $DIR -mtime 0 -name $APP.check.sh`\" != \"\" ] ; then\n" + + " mailit `echo \"Certficate Validated:\\n\\n\" | cat - $DIR/$APP.msg`\n" + + " else\n" + + " cat $DIR/$APP.msg\n" + + " fi\n" + + " ;;\n" + + " 1) mailit \"Error with Certificate Check:\\\\n\\\\nCheck logs $DIR/$APP.STDOUT and $DIR/$APP.STDERR on `uname -n`\"\n" + + " ;;\n" + + " 2) mailit `echo \"Certificate Check Error\\\\n\\\\n\" | cat - $DIR/$APP.msg`\n" + + " ;;\n" + + " 10) mailit `echo \"Certificate Replaced\\\\n\\\\n\" | cat - $DIR/$APP.msg`\n" + + " if [ -e $DIR/$APP.restart.sh ]; then\n" + + " # Note: it is THIS SCRIPT'S RESPONSIBILITY to notify upon success or failure as necessary!!\n" + + " /bin/sh $DIR/$APP.restart.sh\n" + + " fi\n" + + " ;;\n" + + " *) mailit `echo \"Unknown Error code for CM Agent\\\\n\\\\n\" | cat - $DIR/$APP.msg`\n" + + " ;;\n" + + " esac\n\n" + + " # Note: make sure to cover this sripts' exit Code\n"; + + private final static String cronScript = + "crontab -l | sed -n \"/#### BEGIN $CF/,/END $CF ####/!p\" > $TFILE\n" + + "# Note: Randomize Minutes (0-60) and hours (1-4)\n" + + "echo \"#### BEGIN $CF ####\" >> $TFILE\n" + + "echo \"$(( $RANDOM % 60)) $(( $(( $RANDOM % 3 )) + 1 )) * * * /bin/bash $SCRIPT " + + ">> $DIR/cronlog 2>&1 \" >> $TFILE\n" + + "echo \"#### END $CF ####\" >> $TFILE\n" + + "crontab $TFILE\n" + + "rm $TFILE\n"; +} + + + diff --git a/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_ArtifactDir.java b/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_ArtifactDir.java index d0d67e23..ed23179a 100644 --- a/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_ArtifactDir.java +++ b/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_ArtifactDir.java @@ -42,7 +42,7 @@ import org.junit.Test; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.onap.aaf.cadi.CadiException; -import org.onap.aaf.cadi.cm.ArtifactDir; +import org.onap.aaf.cadi.configure.ArtifactDir; import org.onap.aaf.cadi.util.Chmod; import org.onap.aaf.misc.env.Trans; diff --git a/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_CertException.java b/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_CertException.java index aa12d7c6..a973bc22 100644 --- a/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_CertException.java +++ b/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_CertException.java @@ -24,8 +24,7 @@ package org.onap.aaf.cadi.cm.test; import static org.junit.Assert.*; import static org.hamcrest.CoreMatchers.*; import org.junit.*; - -import org.onap.aaf.cadi.cm.CertException; +import org.onap.aaf.cadi.configure.CertException; public class JU_CertException { diff --git a/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_CmAgent.java b/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_CmAgent.java index fbeb360f..b50c5a5e 100644 --- a/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_CmAgent.java +++ b/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_CmAgent.java @@ -28,7 +28,7 @@ import java.io.File; import org.junit.After; import org.junit.Before; import org.junit.Test; -import org.onap.aaf.cadi.cm.CmAgent; +import org.onap.aaf.cadi.configure.Agent; public class JU_CmAgent { @@ -58,62 +58,62 @@ public class JU_CmAgent { "-login", "-noExit", }; - CmAgent.main(args); + Agent.main(args); inStream.reset(); args = new String[] { "-noExit", }; - CmAgent.main(args); + Agent.main(args); inStream.reset(); args = new String[] { "place", "-noExit", }; - CmAgent.main(args); + Agent.main(args); inStream.reset(); args = new String[] { "-noExit", "create" }; - CmAgent.main(args); + Agent.main(args); inStream.reset(); args = new String[] { "-noExit", "read" }; - CmAgent.main(args); + Agent.main(args); inStream.reset(); args = new String[] { "-noExit", "copy" }; - CmAgent.main(args); + Agent.main(args); inStream.reset(); args = new String[] { "-noExit", "update" }; - CmAgent.main(args); + Agent.main(args); inStream.reset(); args = new String[] { "-noExit", "delete" }; - CmAgent.main(args); + Agent.main(args); inStream.reset(); args = new String[] { "-noExit", "showpass" }; - CmAgent.main(args); + Agent.main(args); } diff --git a/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_Factory.java b/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_Factory.java index fb186b89..b47abe2c 100644 --- a/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_Factory.java +++ b/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_Factory.java @@ -57,11 +57,10 @@ import java.util.List; import javax.crypto.Cipher; -import org.onap.aaf.cadi.cm.CertException; -import org.onap.aaf.cadi.cm.Factory; -import org.onap.aaf.cadi.cm.Factory.Base64InputStream; -import org.onap.aaf.cadi.cm.Factory.StripperInputStream; - +import org.onap.aaf.cadi.configure.CertException; +import org.onap.aaf.cadi.configure.Factory; +import org.onap.aaf.cadi.configure.Factory.Base64InputStream; +import org.onap.aaf.cadi.configure.Factory.StripperInputStream; import org.onap.aaf.misc.env.Env; import org.onap.aaf.misc.env.LogTarget; import org.onap.aaf.misc.env.TimeTaken; @@ -162,8 +161,8 @@ public class JU_Factory { assertThat(privateKeyString.startsWith("-----BEGIN PRIVATE KEY-----"), is(true)); assertThat(privateKeyString.endsWith("-----END PRIVATE KEY-----\n"), is(true)); - PublicKey publicKey = Factory.toPublicKey(transMock, cleanupString(publicKeyString)); - PrivateKey privateKey = Factory.toPrivateKey(transMock, cleanupString(privateKeyString)); + PublicKey publicKey = Factory.toPublicKey(transMock, publicKeyString); + PrivateKey privateKey = Factory.toPrivateKey(transMock, privateKeyString); Cipher encryptor = Factory.pkCipher(publicKey, true); Cipher decryptor = Factory.pkCipher(privateKey, false); diff --git a/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactInFiles.java b/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactInFiles.java index 3c83112c..7afb4cf4 100644 --- a/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactInFiles.java +++ b/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactInFiles.java @@ -32,7 +32,7 @@ import java.util.List; import org.junit.*; import org.mockito.*; import org.onap.aaf.cadi.CadiException; -import org.onap.aaf.cadi.cm.PlaceArtifactInFiles; +import org.onap.aaf.cadi.configure.PlaceArtifactInFiles; import org.onap.aaf.misc.env.Trans; import certman.v1_0.Artifacts.Artifact; diff --git a/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactInKeystore.java b/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactInKeystore.java index d146f631..0b086f11 100644 --- a/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactInKeystore.java +++ b/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactInKeystore.java @@ -39,7 +39,7 @@ import java.security.cert.CertificateException; import org.junit.*; import org.mockito.*; import org.onap.aaf.cadi.CadiException; -import org.onap.aaf.cadi.cm.PlaceArtifactInKeystore; +import org.onap.aaf.cadi.configure.PlaceArtifactInKeystore; import org.onap.aaf.misc.env.Env; import org.onap.aaf.misc.env.TimeTaken; import org.onap.aaf.misc.env.Trans; @@ -102,8 +102,9 @@ public class JU_PlaceArtifactInKeystore { certs.add(x509String); certs.add(x509Chain); assertThat(placer.place(transMock, certInfoMock, artiMock, "machine"), is(true)); - for (String ext : new String[] {"chal", "keyfile", "jks", "props", "trust.jks"}) { - assertThat(new File(dirName + '/' + nsName + '.' + ext).exists(), is(true)); + for (String ext : new String[] {"chal", "keyfile", "jks", "trust.jks", "cred.props"}) { + File f = new File(dirName + '/' + nsName + '.' + ext); + assertThat(f.exists(), is(true)); } // coverage diff --git a/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactOnStream.java b/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactOnStream.java index 6e390bed..3d8f41c6 100644 --- a/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactOnStream.java +++ b/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactOnStream.java @@ -32,8 +32,7 @@ import java.util.List; import org.junit.*; import org.mockito.*; - -import org.onap.aaf.cadi.cm.PlaceArtifactOnStream; +import org.onap.aaf.cadi.configure.PlaceArtifactOnStream; import org.onap.aaf.misc.env.LogTarget; import org.onap.aaf.misc.env.Trans; diff --git a/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactScripts.java b/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactScripts.java index 0ed29e10..682606c0 100644 --- a/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactScripts.java +++ b/cadi/aaf/src/test/java/org/onap/aaf/cadi/cm/test/JU_PlaceArtifactScripts.java @@ -30,7 +30,7 @@ import java.io.File; import org.junit.*; import org.mockito.*; import org.onap.aaf.cadi.CadiException; -import org.onap.aaf.cadi.cm.PlaceArtifactScripts; +import org.onap.aaf.cadi.configure.PlaceArtifactScripts; import org.onap.aaf.misc.env.Trans; import certman.v1_0.Artifacts.Artifact; diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/Symm.java b/cadi/core/src/main/java/org/onap/aaf/cadi/Symm.java index ea3891f9..5a3fe825 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/Symm.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/Symm.java @@ -450,9 +450,11 @@ public class Symm { this.range = range; } public int convert(int read) throws IOException { + // System.out.print((char)read); switch(read) { case -1: case '=': + case ' ': case '\n': case '\r': return -1; diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/config/Config.java b/cadi/core/src/main/java/org/onap/aaf/cadi/config/Config.java index c79c5cce..9a0a53cf 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/config/Config.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/config/Config.java @@ -43,6 +43,7 @@ import org.onap.aaf.cadi.CadiException; import org.onap.aaf.cadi.Connector; import org.onap.aaf.cadi.CredVal; import org.onap.aaf.cadi.Locator; +import org.onap.aaf.cadi.LocatorException; import org.onap.aaf.cadi.Lur; import org.onap.aaf.cadi.PropAccess; import org.onap.aaf.cadi.Symm; @@ -225,7 +226,7 @@ public class Config { } } - public static HttpTaf configHttpTaf(Connector con, SecurityInfoC si, TrustChecker tc, CredVal up, Lur lur, Object ... additionalTafLurs) throws CadiException { + public static HttpTaf configHttpTaf(Connector con, SecurityInfoC si, TrustChecker tc, CredVal up, Lur lur, Object ... additionalTafLurs) throws CadiException, LocatorException { Access access = si.access; ///////////////////////////////////////////////////// // Setup AAFCon for any following @@ -712,7 +713,7 @@ public class Config { @SuppressWarnings("unchecked") - public static Locator loadLocator(SecurityInfoC si, final String _url) { + public static Locator loadLocator(SecurityInfoC si, final String _url) throws LocatorException { Access access = si.access; Locator locator = null; if(_url==null) { @@ -753,6 +754,9 @@ public class Config { access.log(Level.INFO, "AAFLocator enabled using preloaded " + locator.getClass().getSimpleName()); } } catch (InvocationTargetException e) { + if(e.getTargetException() instanceof LocatorException) { + throw (LocatorException)e.getTargetException(); + } access.log(Level.INIT,e.getTargetException().getMessage(),"AAFLocator for",url,"could not be created.",e); } catch (Exception e) { access.log(Level.INIT,"AAFLocator for",url,"could not be created.",e); diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/config/SecurityInfoC.java b/cadi/core/src/main/java/org/onap/aaf/cadi/config/SecurityInfoC.java index 33aef6c9..cc366c27 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/config/SecurityInfoC.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/config/SecurityInfoC.java @@ -34,7 +34,7 @@ public class SecurityInfoC extends SecurityInfo { private static Map,SecurityInfoC> sicMap = new HashMap,SecurityInfoC>(); public SecuritySetter defSS; - private SecurityInfoC(Access access) throws CadiException { + public SecurityInfoC(Access access) throws CadiException { super(access); defSS = new SecuritySetter() { @Override @@ -54,14 +54,14 @@ public class SecurityInfoC extends SecurityInfo { }; } - @SuppressWarnings("unchecked") public static synchronized SecurityInfoC instance(Access access, Class cls) throws CadiException { - SecurityInfoC sic = sicMap.get(cls); + @SuppressWarnings("unchecked") + SecurityInfoC sic = (SecurityInfoC) sicMap.get(cls); if(sic==null) { sic = new SecurityInfoC(access); sicMap.put(cls, sic); } - return (SecurityInfoC)sic; + return sic; } public SecurityInfoC set(SecuritySetter defSS) { diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiFilter.java b/cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiFilter.java index 8577d55c..1f302c64 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiFilter.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiFilter.java @@ -38,6 +38,7 @@ import javax.servlet.http.HttpServletResponse; import org.onap.aaf.cadi.Access; import org.onap.aaf.cadi.CadiException; import org.onap.aaf.cadi.CadiWrap; +import org.onap.aaf.cadi.LocatorException; import org.onap.aaf.cadi.Lur; import org.onap.aaf.cadi.PropAccess; import org.onap.aaf.cadi.ServletContextAccess; @@ -188,7 +189,7 @@ public class CadiFilter implements Filter { } try { httpChecker = new CadiHTTPManip(access,null /*reuseable Con*/,tc, additionalTafLurs); - } catch (CadiException e1) { + } catch (CadiException | LocatorException e1) { throw new ServletException(e1); } } else if(access==null) { diff --git a/cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiHTTPManip.java b/cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiHTTPManip.java index 006d6b4e..0cc52203 100644 --- a/cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiHTTPManip.java +++ b/cadi/core/src/main/java/org/onap/aaf/cadi/filter/CadiHTTPManip.java @@ -32,6 +32,7 @@ import org.onap.aaf.cadi.CadiException; import org.onap.aaf.cadi.CadiWrap; import org.onap.aaf.cadi.Connector; import org.onap.aaf.cadi.CredVal; +import org.onap.aaf.cadi.LocatorException; import org.onap.aaf.cadi.Lur; import org.onap.aaf.cadi.Taf; import org.onap.aaf.cadi.TrustChecker; @@ -70,7 +71,7 @@ public class CadiHTTPManip { public static final Object[] noAdditional = new Object[0]; // CadiFilter can be created each call in some systems - public CadiHTTPManip(Access access, Connector con, TrustChecker tc, Object ... additionalTafLurs) throws CadiException { + public CadiHTTPManip(Access access, Connector con, TrustChecker tc, Object ... additionalTafLurs) throws CadiException, LocatorException { synchronized(LOCK) { this.access = access; // Get getter = new AccessGetter(access); diff --git a/misc/env/src/main/java/org/onap/aaf/misc/env/util/Split.java b/misc/env/src/main/java/org/onap/aaf/misc/env/util/Split.java index 57e60091..efb68120 100644 --- a/misc/env/src/main/java/org/onap/aaf/misc/env/util/Split.java +++ b/misc/env/src/main/java/org/onap/aaf/misc/env/util/Split.java @@ -30,7 +30,13 @@ package org.onap.aaf.misc.env.util; */ public class Split { + private static final String[] BLANK = new String[0]; + public static String[] split(char c, String value) { + if(value==null) { + return BLANK; + } + // Count items to preallocate Array (memory alloc is more expensive than counting twice) int count,idx; for(count=1,idx=value.indexOf(c);idx>=0;idx=value.indexOf(c,++idx),++count); @@ -50,6 +56,9 @@ public class Split { } public static String[] splitTrim(char c, String value) { + if(value==null) { + return BLANK; + } // Count items to preallocate Array (memory alloc is more expensive than counting twice) int count,idx; for(count=1,idx=value.indexOf(c);idx>=0;idx=value.indexOf(c,++idx),++count); @@ -69,6 +78,10 @@ public class Split { } public static String[] splitTrim(char c, String value, int size) { + if(value==null) { + return BLANK; + } + int idx; String[] rv = new String[size]; if(size==1) { -- cgit