From 32cdd553a8668e6d03a9cf5b11b360d35a63c87f Mon Sep 17 00:00:00 2001 From: Instrumental Date: Thu, 19 Jul 2018 13:29:32 -0500 Subject: Configuration and Auto-Certificates Issue-ID: AAF-378 Change-Id: Ic820a4e43684a6130f00b28b415a974876099fc3 Signed-off-by: Instrumental --- auth/auth-certman/pom.xml | 8 + .../src/main/java/org/onap/aaf/auth/cm/ca/CA.java | 12 +- .../java/org/onap/aaf/auth/cm/cert/BCFactory.java | 2 +- .../java/org/onap/aaf/auth/cm/cert/CSRMeta.java | 1 + .../org/onap/aaf/auth/cm/facade/FacadeImpl.java | 79 ++- .../org/onap/aaf/auth/cm/service/CMService.java | 550 +++++++++++---------- .../org/onap/aaf/auth/cm/facade/JU_FacadeImpl.java | 22 +- 7 files changed, 348 insertions(+), 326 deletions(-) (limited to 'auth/auth-certman') diff --git a/auth/auth-certman/pom.xml b/auth/auth-certman/pom.xml index 26c3c678..8b1729ec 100644 --- a/auth/auth-certman/pom.xml +++ b/auth/auth-certman/pom.xml @@ -60,6 +60,14 @@ org.onap.aaf.authz aaf-cadi-aaf + + + + org.onap.aaf.authz + aaf-auth-deforg + com.google.code.jscep 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 e840ef56..f1f70a7e 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 @@ -57,20 +57,22 @@ public abstract class CA { private final String name; private final String env; private MessageDigest messageDigest; + private final String permNS; private final String permType; private final ArrayList idDomains; private String[] trustedCAs; private String[] caIssuerDNs; - private List rdns; + private List rdns; protected CA(Access access, String caName, String env) throws IOException, CertException { trustedCAs = new String[4]; // starting array this.name = caName; this.env = env; - permType = access.getProperty(CM_CA_PREFIX + name + ".perm_type",null); + permNS = CM_CA_PREFIX + name; + permType = access.getProperty(permNS + ".perm_type",null); if(permType==null) { - throw new CertException(CM_CA_PREFIX + name + ".perm_type" + MUST_EXIST_TO_CREATE_CSRS_FOR + caName); + throw new CertException(permNS + ".perm_type" + MUST_EXIST_TO_CREATE_CSRS_FOR + caName); } caIssuerDNs = Split.splitTrim(':', access.getProperty(Config.CADI_X509_ISSUERS, null)); @@ -204,6 +206,10 @@ public abstract class CA { } + public String getPermNS() { + return permNS; + } + public String getPermType() { return permType; } 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 70ddd438..e40a7a21 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 @@ -116,7 +116,7 @@ public class BCFactory extends Factory { CertmanValidator v = new CertmanValidator(); if(v.nullOrBlank("cn", csr.cn()) .nullOrBlank("mechID", csr.mechID()) - .nullOrBlank("email", csr.email()) +// .nullOrBlank("email", csr.email()) .err()) { return v.errs(); } else { 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 7d417d5f..f9fcad17 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 @@ -156,6 +156,7 @@ public class CSRMeta { Date start = gc.getTime(); gc.add(GregorianCalendar.DAY_OF_MONTH,2); Date end = gc.getTime(); + @SuppressWarnings("deprecation") X509v3CertificateBuilder xcb = new X509v3CertificateBuilder( x500Name(), new BigInteger(12,random), // replace with Serialnumber scheme 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 794f63a6..98fdf11b 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 @@ -32,16 +32,6 @@ import static org.onap.aaf.auth.layer.Result.ERR_Security; import static org.onap.aaf.auth.layer.Result.OK; import java.io.IOException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.cert.Certificate; -import java.security.cert.CertificateException; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -58,8 +48,6 @@ 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.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; @@ -232,10 +220,17 @@ public abstract class FacadeImpl extends org.onap.aaf. @Override public Result check(AuthzTrans trans, HttpServletResponse resp, String perm) throws IOException { String[] p = Split.split('|',perm); - if(p.length!=3) { - return Result.err(Result.ERR_BadData,"Invalid Perm String"); + AAFPermission ap; + switch(p.length) { + case 3: + ap = new AAFPermission(null, p[0],p[1],p[2]); + break; + case 4: + ap = new AAFPermission(p[0],p[1],p[2],p[3]); + break; + default: + return Result.err(Result.ERR_BadData,"Invalid Perm String"); } - AAFPermission ap = new AAFPermission(p[0],p[1],p[2]); if(certman.aafLurPerm.fish(trans.getUserPrincipal(), ap)) { resp.setContentType(voidResp); resp.getOutputStream().write(0); @@ -360,33 +355,33 @@ public abstract class FacadeImpl extends org.onap.aaf. // return Result.ok(); } - private KeyStore keystore(AuthzTrans trans, CertResp cr, String[] trustChain, String name, char[] cap) throws KeyStoreException, CertificateException, APIException, IOException, CertException, NoSuchAlgorithmException { - KeyStore jks = KeyStore.getInstance("jks"); - jks.load(null, cap); - - // Get the Cert(s)... Might include Trust store - List lcerts = new ArrayList<>(); - lcerts.add(cr.asCertString()); - for(String s : trustChain) { - lcerts.add(s); - } - - Collection certColl = Factory.toX509Certificate(lcerts); - X509Certificate[] certs = new X509Certificate[certColl.size()]; - certColl.toArray(certs); - KeyStore.ProtectionParameter protParam = new KeyStore.PasswordProtection(cap); - - PrivateKey pk = Factory.toPrivateKey(trans, cr.privateString()); - KeyStore.PrivateKeyEntry pkEntry = - new KeyStore.PrivateKeyEntry(pk, new Certificate[] {certs[0]}); - jks.setEntry(name, pkEntry, protParam); - - int i=0; - for(X509Certificate x509 : certs) { - jks.setCertificateEntry("cert_"+ ++i, x509); - } - return jks; - } +// private KeyStore keystore(AuthzTrans trans, CertResp cr, String[] trustChain, String name, char[] cap) throws KeyStoreException, CertificateException, APIException, IOException, CertException, NoSuchAlgorithmException { +// KeyStore jks = KeyStore.getInstance("jks"); +// jks.load(null, cap); +// +// // Get the Cert(s)... Might include Trust store +// List lcerts = new ArrayList<>(); +// lcerts.add(cr.asCertString()); +// for(String s : trustChain) { +// lcerts.add(s); +// } +// +// Collection certColl = Factory.toX509Certificate(lcerts); +// X509Certificate[] certs = new X509Certificate[certColl.size()]; +// certColl.toArray(certs); +// KeyStore.ProtectionParameter protParam = new KeyStore.PasswordProtection(cap); +// +// PrivateKey pk = Factory.toPrivateKey(trans, cr.privateString()); +// KeyStore.PrivateKeyEntry pkEntry = +// new KeyStore.PrivateKeyEntry(pk, new Certificate[] {certs[0]}); +// jks.setEntry(name, pkEntry, protParam); +// +// int i=0; +// for(X509Certificate x509 : certs) { +// jks.setCertificateEntry("cert_"+ ++i, x509); +// } +// return jks; +// } @Override public Result renewCert(AuthzTrans trans, HttpServletRequest req, HttpServletResponse resp, boolean withTrust) { 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 376ae1b1..f9cd060b 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 @@ -58,156 +58,170 @@ import org.onap.aaf.auth.org.Organization; import org.onap.aaf.auth.org.Organization.Identity; import org.onap.aaf.auth.org.OrganizationException; import org.onap.aaf.cadi.Hash; +import org.onap.aaf.cadi.Permission; import org.onap.aaf.cadi.aaf.AAFPermission; +import org.onap.aaf.cadi.config.Config; 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; - public class CMService { // If we add more CAs, may want to parameterize private static final int STD_RENEWAL = 30; private static final int MAX_RENEWAL = 60; private static final int MIN_RENEWAL = 10; - + public static final String REQUEST = "request"; + public static final String IGNORE_IPS = "ignoreIPs"; public static final String RENEW = "renew"; public static final String DROP = "drop"; - public static final String IPS = "ips"; public static final String DOMAIN = "domain"; - private static final String CERTMAN = ".certman"; - private static final String ACCESS = ".access"; - + private static final String CERTMAN = "certman"; + private static final String ACCESS = "access"; + private static final String[] NO_NOTES = new String[0]; + private final Permission root_read_permission; private final CertDAO certDAO; private final CredDAO credDAO; private final ArtiDAO artiDAO; private AAF_CM certman; -// @SuppressWarnings("unchecked") + // @SuppressWarnings("unchecked") public CMService(final AuthzTrans trans, AAF_CM certman) throws APIException, IOException { - // Jonathan 4/2015 SessionFilter unneeded... DataStax already deals with Multithreading well - - HistoryDAO hd = new HistoryDAO(trans, certman.cluster, CassAccess.KEYSPACE); + // Jonathan 4/2015 SessionFilter unneeded... DataStax already deals with + // Multithreading well + + HistoryDAO hd = new HistoryDAO(trans, certman.cluster, CassAccess.KEYSPACE); CacheInfoDAO cid = new CacheInfoDAO(trans, hd); certDAO = new CertDAO(trans, hd, cid); credDAO = new CredDAO(trans, hd, cid); artiDAO = new ArtiDAO(trans, hd, cid); this.certman = certman; + + root_read_permission=new AAFPermission( + trans.getProperty(Config.AAF_ROOT_NS, Config.AAF_ROOT_NS_DEF), + "access", + "*", + "read" + ); } - - public Result requestCert(final AuthzTrans trans,final Result req, final CA ca) { - if(req.isOK()) { - if(req.value.fqdns.isEmpty()) { - return Result.err(Result.ERR_BadData,"No Machines passed in Request"); + public Result requestCert(final AuthzTrans trans, final Result req, final CA ca) { + if (req.isOK()) { + + if (req.value.fqdns.isEmpty()) { + return Result.err(Result.ERR_BadData, "No Machines passed in Request"); } - + String key = req.value.fqdns.get(0); - + // Policy 6: Requester must be granted Change permission in Namespace requested String mechNS = FQI.reverseDomain(req.value.mechid); - if(mechNS==null) { - return Result.err(Status.ERR_Denied, "%s does not reflect a valid AAF Namespace",req.value.mechid); - } - - - // Disallow non-AAF CA without special permission - if(!"aaf".equals(ca.getName()) && !trans.fish( new AAFPermission(mechNS+CERTMAN, ca.getName(), REQUEST))) { - return Result.err(Status.ERR_Denied, "'%s' does not have permission to request Certificates from Certificate Authority '%s'", - trans.user(),ca.getName()); + if (mechNS == null) { + return Result.err(Status.ERR_Denied, "%s does not reflect a valid AAF Namespace", req.value.mechid); } List notes = null; List fqdns = new ArrayList<>(req.value.fqdns); - - + String email = null; try { Organization org = trans.org(); - + + boolean ignoreIPs = trans.fish(new AAFPermission(mechNS,CERTMAN, ca.getName(), IGNORE_IPS)); + InetAddress primary = null; // Organize incoming information to get to appropriate Artifact - if(!fqdns.isEmpty()) { + if (!fqdns.isEmpty()) { // Accept domain wild cards, but turn into real machines // Need *domain.com:real.machine.domain.com:san.machine.domain.com:... - if(fqdns.get(0).startsWith("*")) { // Domain set - if(!trans.fish(new AAFPermission(ca.getPermType(), ca.getName(), DOMAIN))) { - return Result.err(Result.ERR_Denied, "Domain based Authorizations (" + fqdns.get(0) + ") requires Exception"); + if (fqdns.get(0).startsWith("*")) { // Domain set + if (!trans.fish(new AAFPermission(null,ca.getPermType(), ca.getName(), DOMAIN))) { + return Result.err(Result.ERR_Denied, + "Domain based Authorizations (" + fqdns.get(0) + ") requires Exception"); } - - //TODO check for Permission in Add Artifact? + + // TODO check for Permission in Add Artifact? String domain = fqdns.get(0).substring(1); fqdns.remove(0); - if(fqdns.isEmpty()) { - return Result.err(Result.ERR_Denied, "Requests using domain require machine declaration"); - } - - InetAddress ia = InetAddress.getByName(fqdns.get(0)); - if(ia==null) { - return Result.err(Result.ERR_Denied, "Request not made from matching IP matching domain"); - } else if(ia.getHostName().endsWith(domain)) { - primary = ia; - } - - } else { - for(String cn : req.value.fqdns) { + if (fqdns.isEmpty()) { + return Result.err(Result.ERR_Denied, "Requests using domain require machine declaration"); + } + + if (!ignoreIPs) { + InetAddress ia = InetAddress.getByName(fqdns.get(0)); + if (ia == null) { + return Result.err(Result.ERR_Denied, + "Request not made from matching IP matching domain"); + } else if (ia.getHostName().endsWith(domain)) { + primary = ia; + } + } + + } else { + for (String cn : req.value.fqdns) { try { InetAddress[] ias = InetAddress.getAllByName(cn); Set potentialSanNames = new HashSet<>(); - for(InetAddress ia1 : ias) { + for (InetAddress ia1 : ias) { InetAddress ia2 = InetAddress.getByAddress(ia1.getAddress()); - if(primary==null && ias.length==1 && trans.ip().equals(ia1.getHostAddress())) { + if (primary == null && ias.length == 1 && trans.ip().equals(ia1.getHostAddress())) { primary = ia1; - } else if(!cn.equals(ia1.getHostName()) && !ia2.getHostName().equals(ia2.getHostAddress())) { + } else if (!cn.equals(ia1.getHostName()) + && !ia2.getHostName().equals(ia2.getHostAddress())) { potentialSanNames.add(ia1.getHostName()); } } } catch (UnknownHostException e1) { - return Result.err(Result.ERR_BadData,"There is no DNS lookup for %s",cn); + return Result.err(Result.ERR_BadData, "There is no DNS lookup for %s", cn); } - + } } } - - if(primary==null) { - return Result.err(Result.ERR_Denied, "Request not made from matching IP (%s)",trans.ip()); + + final String host; + if(ignoreIPs) { + host = req.value.fqdns.get(0); + } else if (primary == null) { + return Result.err(Result.ERR_Denied, "Request not made from matching IP (%s)", trans.ip()); + } else { + host = primary.getHostAddress(); } - + ArtiDAO.Data add = null; - Result> ra = artiDAO.read(trans, req.value.mechid,primary.getHostAddress()); - if(ra.isOKhasData()) { - if(add==null) { + Result> ra = artiDAO.read(trans, req.value.mechid, host); + if (ra.isOKhasData()) { + if (add == null) { add = ra.value.get(0); // single key } } else { - ra = artiDAO.read(trans, req.value.mechid,key); - if(ra.isOKhasData()) { // is the Template available? - add = ra.value.get(0); - add.machine=primary.getHostName(); - for(String s : fqdns) { - if(!s.equals(add.machine)) { - add.sans(true).add(s); - } - } - Result rc = artiDAO.create(trans, add); // Create new Artifact from Template - if(rc.notOK()) { - return Result.err(rc); - } - } else { - add = ra.value.get(0); - } + ra = artiDAO.read(trans, req.value.mechid, key); + if (ra.isOKhasData()) { // is the Template available? + add = ra.value.get(0); + add.machine = host; + for (String s : fqdns) { + if (!s.equals(add.machine)) { + add.sans(true).add(s); + } + } + Result rc = artiDAO.create(trans, add); // Create new Artifact from Template + if (rc.notOK()) { + return Result.err(rc); + } + } else { + add = ra.value.get(0); + } } - + // Add Artifact listed FQDNs - if(add.sans!=null) { - for(String s : add.sans) { - if(!fqdns.contains(s)) { + if (add.sans != null) { + for (String s : add.sans) { + if (!fqdns.contains(s)) { fqdns.add(s); } } @@ -215,134 +229,142 @@ public class CMService { // Policy 2: If Config marked as Expired, do not create or renew Date now = new Date(); - if(add.expires!=null && now.after(add.expires)) { - return Result.err(Result.ERR_Policy,"Configuration for %s %s is expired %s",add.mechid,add.machine,Chrono.dateFmt.format(add.expires)); + if (add.expires != null && now.after(add.expires)) { + return Result.err(Result.ERR_Policy, "Configuration for %s %s is expired %s", add.mechid, + add.machine, Chrono.dateFmt.format(add.expires)); } - + // Policy 3: MechID must be current Identity muser = org.getIdentity(trans, add.mechid); - if(muser == null) { - return Result.err(Result.ERR_Policy,"MechID must exist in %s",org.getName()); + if (muser == null) { + return Result.err(Result.ERR_Policy, "MechID must exist in %s", org.getName()); } - + // Policy 4: Sponsor must be current Identity ouser = muser.responsibleTo(); - if(ouser==null) { - return Result.err(Result.ERR_Policy,"%s does not have a current sponsor at %s",add.mechid,org.getName()); - } else if(!ouser.isFound() || ouser.mayOwn()!=null) { - return Result.err(Result.ERR_Policy,"%s reports that %s cannot be responsible for %s",org.getName(),trans.user()); + if (ouser == null) { + return Result.err(Result.ERR_Policy, "%s does not have a current sponsor at %s", add.mechid, + org.getName()); + } else if (!ouser.isFound() || ouser.mayOwn() != null) { + return Result.err(Result.ERR_Policy, "%s reports that %s cannot be responsible for %s", + org.getName(), trans.user()); } - + // Set Email from most current Sponsor email = ouser.email(); - + // Policy 5: keep Artifact data current - if(!ouser.fullID().equals(add.sponsor)) { + if (!ouser.fullID().equals(add.sponsor)) { add.sponsor = ouser.fullID(); artiDAO.update(trans, add); } - - // Policy 7: Caller must be the MechID or have specifically delegated permissions - if(!(trans.user().equals(req.value.mechid) || trans.fish(new AAFPermission(mechNS + CERTMAN, ca.getName() , REQUEST)))) { - return Result.err(Status.ERR_Denied, "%s must have access to modify x509 certs in NS %s",trans.user(),mechNS); + + // Policy 7: Caller must be the MechID or have specifically delegated + // permissions + if (!(trans.user().equals(req.value.mechid) + || trans.fish(new AAFPermission(mechNS,CERTMAN, ca.getName(), REQUEST)))) { + return Result.err(Status.ERR_Denied, "%s must have access to modify x509 certs in NS %s", + trans.user(), mechNS); } - + // Make sure Primary is the first in fqdns - if(fqdns.size()>1) { - for(int i=0;i 1) { + for (int i = 0; i < fqdns.size(); ++i) { + if(primary==null) { + trans.error().log("CMService var primary is null"); + } else { + String fg = fqdns.get(i); + if (fg!=null && fg.equals(primary.getHostName())) { + if (i != 0) { + String tmp = fqdns.get(0); + fqdns.set(0, primary.getHostName()); + fqdns.set(i, tmp); + } } } } } } catch (Exception e) { + e.printStackTrace(); trans.error().log(e); - return Result.err(Status.ERR_Denied,"MechID Sponsorship cannot be determined at this time. Try later"); + return Result.err(Status.ERR_Denied, + "AppID Sponsorship cannot be determined at this time. Try later."); } - + CSRMeta csrMeta; try { - csrMeta = BCFactory.createCSRMeta( - ca, - req.value.mechid, - email, - fqdns); + csrMeta = BCFactory.createCSRMeta(ca, req.value.mechid, email, fqdns); X509andChain x509ac = ca.sign(trans, csrMeta); - if(x509ac==null) { - return Result.err(Result.ERR_ActionNotCompleted,"x509 Certificate not signed by CA"); + if (x509ac == null) { + return Result.err(Result.ERR_ActionNotCompleted, "x509 Certificate not signed by CA"); } trans.info().printf("X509 Subject: %s", x509ac.getX509().getSubjectDN()); - + X509Certificate x509 = x509ac.getX509(); CertDAO.Data cdd = new CertDAO.Data(); - cdd.ca=ca.getName(); - cdd.serial=x509.getSerialNumber(); - cdd.id=req.value.mechid; - cdd.x500=x509.getSubjectDN().getName(); - cdd.x509=Factory.toString(trans, x509); + cdd.ca = ca.getName(); + cdd.serial = x509.getSerialNumber(); + cdd.id = req.value.mechid; + cdd.x500 = x509.getSubjectDN().getName(); + cdd.x509 = Factory.toString(trans, x509); certDAO.create(trans, cdd); - + CredDAO.Data crdd = new CredDAO.Data(); crdd.other = Question.random.nextInt(); - crdd.cred=getChallenge256SaltedHash(csrMeta.challenge(),crdd.other); + crdd.cred = getChallenge256SaltedHash(csrMeta.challenge(), crdd.other); crdd.expires = x509.getNotAfter(); crdd.id = req.value.mechid; crdd.ns = Question.domain2ns(crdd.id); crdd.type = CredDAO.CERT_SHA256_RSA; credDAO.create(trans, crdd); - - CertResp cr = new CertResp(trans, ca, x509, csrMeta, x509ac.getTrustChain(),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); - return Result.err(Result.ERR_ActionNotCompleted,e.getMessage()); + return Result.err(Result.ERR_ActionNotCompleted, e.getMessage()); } } else { return Result.err(req); } } - public Result renewCert(AuthzTrans trans, Result renew) { - if(renew.isOK()) { - return Result.err(Result.ERR_NotImplemented,"Not implemented yet"); + public Result renewCert(AuthzTrans trans, Result renew) { + if (renew.isOK()) { + return Result.err(Result.ERR_NotImplemented, "Not implemented yet"); } else { return Result.err(renew); - } + } } public Result dropCert(AuthzTrans trans, Result drop) { - if(drop.isOK()) { - return Result.err(Result.ERR_NotImplemented,"Not implemented yet"); + if (drop.isOK()) { + return Result.err(Result.ERR_NotImplemented, "Not implemented yet"); } else { return Result.err(drop); - } + } } public Result> readCertsByMechID(AuthzTrans trans, String mechID) { // Policy 1: To Read, must have NS Read or is Sponsor String ns = Question.domain2ns(mechID); try { - if( trans.user().equals(mechID) - || trans.fish(new AAFPermission(ns + ACCESS, "*", "read")) - || (trans.org().validate(trans,Organization.Policy.OWNS_MECHID,null,mechID))==null) { + if (trans.user().equals(mechID) || trans.fish(new AAFPermission(ns,ACCESS, "*", "read")) + || (trans.org().validate(trans, Organization.Policy.OWNS_MECHID, null, mechID)) == null) { return certDAO.readID(trans, mechID); } else { - return Result.err(Result.ERR_Denied,"%s is not the ID, Sponsor or NS Owner/Admin for %s at %s", - trans.user(),mechID,trans.org().getName()); + return Result.err(Result.ERR_Denied, "%s is not the ID, Sponsor or NS Owner/Admin for %s at %s", + trans.user(), mechID, trans.org().getName()); } - } catch(OrganizationException e) { + } catch (OrganizationException e) { return Result.err(e); } } public Result requestPersonalCert(AuthzTrans trans, CA ca) { - if(ca.inPersonalDomains(trans.getUserPrincipal())) { + if (ca.inPersonalDomains(trans.getUserPrincipal())) { Organization org = trans.org(); - + // Policy 1: MechID must be current Identity ouser; try { @@ -351,39 +373,36 @@ public class CMService { trans.error().log(e1); ouser = null; } - if(ouser == null) { - return Result.err(Result.ERR_Policy,"Requesting User must exist in %s",org.getName()); + if (ouser == null) { + return Result.err(Result.ERR_Policy, "Requesting User must exist in %s", org.getName()); } - + // Set Email from most current Sponsor - + CSRMeta csrMeta; try { - csrMeta = BCFactory.createPersonalCSRMeta( - ca, - trans.user(), - ouser.email()); + csrMeta = BCFactory.createPersonalCSRMeta(ca, trans.user(), ouser.email()); X509andChain x509ac = ca.sign(trans, csrMeta); - if(x509ac==null) { - return Result.err(Result.ERR_ActionNotCompleted,"x509 Certificate not signed by CA"); + if (x509ac == null) { + return Result.err(Result.ERR_ActionNotCompleted, "x509 Certificate not signed by CA"); } X509Certificate x509 = x509ac.getX509(); CertDAO.Data cdd = new CertDAO.Data(); - cdd.ca=ca.getName(); - cdd.serial=x509.getSerialNumber(); - cdd.id=trans.user(); - cdd.x500=x509.getSubjectDN().getName(); - cdd.x509=Factory.toString(trans, x509); + cdd.ca = ca.getName(); + cdd.serial = x509.getSerialNumber(); + cdd.id = trans.user(); + cdd.x500 = x509.getSubjectDN().getName(); + cdd.x509 = Factory.toString(trans, x509); certDAO.create(trans, cdd); - + CertResp cr = new CertResp(trans, ca, x509, csrMeta, x509ac.getTrustChain(), compileNotes(null)); return Result.ok(cr); } catch (Exception e) { trans.error().log(e); - return Result.err(Result.ERR_ActionNotCompleted,e.getMessage()); + return Result.err(Result.ERR_ActionNotCompleted, e.getMessage()); } } else { - return Result.err(Result.ERR_Denied,trans.user()," not supported for CA",ca.getName()); + return Result.err(Result.ERR_Denied, trans.user(), " not supported for CA", ca.getName()); } } @@ -392,71 +411,69 @@ public class CMService { ////////////// public Result createArtifact(AuthzTrans trans, List list) { CertmanValidator v = new CertmanValidator().artisRequired(list, 1); - if(v.err()) { - return Result.err(Result.ERR_BadData,v.errs()); + if (v.err()) { + return Result.err(Result.ERR_BadData, v.errs()); } - for(ArtiDAO.Data add : list) { + for (ArtiDAO.Data add : list) { try { // Policy 1: MechID must exist in Org Identity muser = trans.org().getIdentity(trans, add.mechid); - if(muser == null) { - return Result.err(Result.ERR_Denied,"%s is not valid for %s", add.mechid,trans.org().getName()); + if (muser == null) { + return Result.err(Result.ERR_Denied, "%s is not valid for %s", add.mechid, trans.org().getName()); } - + // Policy 2: MechID must have valid Organization Owner Identity emailUser; - if(muser.isPerson()) { + if (muser.isPerson()) { emailUser = muser; } else { Identity ouser = muser.responsibleTo(); - if(ouser == null) { - return Result.err(Result.ERR_Denied,"%s is not a valid Sponsor for %s at %s", - trans.user(),add.mechid,trans.org().getName()); + if (ouser == null) { + return Result.err(Result.ERR_Denied, "%s is not a valid Sponsor for %s at %s", trans.user(), + add.mechid, trans.org().getName()); } // Policy 3: Calling ID must be MechID Owner - if(!trans.user().equals(ouser.fullID())) { - return Result.err(Result.ERR_Denied,"%s is not the Sponsor for %s at %s", - trans.user(),add.mechid,trans.org().getName()); + if (!trans.user().startsWith(ouser.id())) { + return Result.err(Result.ERR_Denied, "%s is not the Sponsor for %s at %s", trans.user(), + add.mechid, trans.org().getName()); } emailUser = ouser; } - - // Policy 4: Renewal Days are between 10 and 60 (constants, may be parameterized) - if(add.renewDaysMAX_RENEWAL) { + } else if (add.renewDays > MAX_RENEWAL) { add.renewDays = MAX_RENEWAL; } - + // Policy 5: If Notify is blank, set to Owner's Email - if(add.notify==null || add.notify.length()==0) { - add.notify = "mailto:"+emailUser.email(); + if (add.notify == null || add.notify.length() == 0) { + add.notify = "mailto:" + emailUser.email(); } - + // Policy 6: Only do Domain by Exception - if(add.machine.startsWith("*")) { // Domain set + if (add.machine.startsWith("*")) { // Domain set CA ca = certman.getCA(add.ca); - - if(!trans.fish(new AAFPermission(ca.getPermType(), add.ca, DOMAIN))) { - return Result.err(Result.ERR_Denied,"Domain Artifacts (%s) requires specific Permission", - add.machine); + if (!trans.fish(new AAFPermission(ca.getPermNS(),ca.getPermType(), add.ca, DOMAIN))) { + return Result.err(Result.ERR_Denied, "Domain Artifacts (%s) requires specific Permission", + add.machine); } } // Set Sponsor from Golden Source add.sponsor = emailUser.fullID(); - - + } catch (OrganizationException e) { return Result.err(e); } // Add to DB Result rv = artiDAO.create(trans, add); // TODO come up with Partial Reporting Scheme, or allow only one at a time. - if(rv.notOK()) { + if (rv.notOK()) { return Result.err(rv); } } @@ -465,40 +482,45 @@ public class CMService { public Result> readArtifacts(AuthzTrans trans, ArtiDAO.Data add) throws OrganizationException { CertmanValidator v = new CertmanValidator().keys(add); - if(v.err()) { - return Result.err(Result.ERR_BadData,v.errs()); + if (v.err()) { + return Result.err(Result.ERR_BadData, v.errs()); } Result> data = artiDAO.read(trans, add); - if(data.notOKorIsEmpty()) { + if (data.notOKorIsEmpty()) { return data; } add = data.value.get(0); - if( trans.user().equals(add.mechid) - || trans.fish(new AAFPermission(add.ns + ACCESS, "*", "read")) - || trans.fish(new AAFPermission(add.ns+CERTMAN,add.ca,"read")) - || trans.fish(new AAFPermission(add.ns+CERTMAN,add.ca,"request")) - || (trans.org().validate(trans,Organization.Policy.OWNS_MECHID,null,add.mechid))==null) { + if (trans.user().equals(add.mechid) + || trans.fish(root_read_permission, + new AAFPermission(add.ns,ACCESS, "*", "read"), + new AAFPermission(add.ns,CERTMAN, add.ca, "read"), + new AAFPermission(add.ns,CERTMAN, add.ca, "request")) + || (trans.org().validate(trans, Organization.Policy.OWNS_MECHID, null, add.mechid)) == null) { return data; } else { - return Result.err(Result.ERR_Denied,"%s is not %s, is not the sponsor, and doesn't have delegated permission.",trans.user(),add.mechid,add.ns+".certman|"+add.ca+"|read or ...|request"); // note: reason is set by 2nd case, if 1st case misses + return Result.err(Result.ERR_Denied, + "%s is not %s, is not the sponsor, and doesn't have delegated permission.", trans.user(), + add.mechid, add.ns + ".certman|" + add.ca + "|read or ...|request"); // note: reason is set by 2nd + // case, if 1st case misses } } - public Result> readArtifactsByMechID(AuthzTrans trans, String mechid) throws OrganizationException { + public Result> readArtifactsByMechID(AuthzTrans trans, String mechid) + throws OrganizationException { CertmanValidator v = new CertmanValidator(); v.nullOrBlank("mechid", mechid); - if(v.err()) { - return Result.err(Result.ERR_BadData,v.errs()); + if (v.err()) { + return Result.err(Result.ERR_BadData, v.errs()); } String ns = FQI.reverseDomain(mechid); - + String reason; - if(trans.fish(new AAFPermission(ns + ACCESS, "*", "read")) - || (reason=trans.org().validate(trans,Organization.Policy.OWNS_MECHID,null,mechid))==null) { + if (trans.fish(new AAFPermission(ns, ACCESS, "*", "read")) + || (reason = trans.org().validate(trans, Organization.Policy.OWNS_MECHID, null, mechid)) == null) { return artiDAO.readByMechID(trans, mechid); } else { - return Result.err(Result.ERR_Denied,reason); // note: reason is set by 2nd case, if 1st case misses + return Result.err(Result.ERR_Denied, reason); // note: reason is set by 2nd case, if 1st case misses } } @@ -506,10 +528,10 @@ public class CMService { public Result> readArtifactsByMachine(AuthzTrans trans, String machine) { CertmanValidator v = new CertmanValidator(); v.nullOrBlank("machine", machine); - if(v.err()) { - return Result.err(Result.ERR_BadData,v.errs()); + if (v.err()) { + return Result.err(Result.ERR_BadData, v.errs()); } - + // TODO do some checks? Result> rv = artiDAO.readByMachine(trans, machine); @@ -519,43 +541,43 @@ public class CMService { public Result> readArtifactsByNs(AuthzTrans trans, String ns) { CertmanValidator v = new CertmanValidator(); v.nullOrBlank("ns", ns); - if(v.err()) { - return Result.err(Result.ERR_BadData,v.errs()); + if (v.err()) { + return Result.err(Result.ERR_BadData, v.errs()); } - + // TODO do some checks? - return artiDAO.readByNs(trans, ns); + return artiDAO.readByNs(trans, ns); } - public Result updateArtifact(AuthzTrans trans, List list) throws OrganizationException { CertmanValidator v = new CertmanValidator(); v.artisRequired(list, 1); - if(v.err()) { - return Result.err(Result.ERR_BadData,v.errs()); + if (v.err()) { + return Result.err(Result.ERR_BadData, v.errs()); } - + // Check if requesting User is Sponsor - //TODO - Shall we do one, or multiples? - for(ArtiDAO.Data add : list) { + // TODO - Shall we do one, or multiples? + for (ArtiDAO.Data add : list) { // Policy 1: MechID must exist in Org Identity muser = trans.org().getIdentity(trans, add.mechid); - if(muser == null) { - return Result.err(Result.ERR_Denied,"%s is not valid for %s", add.mechid,trans.org().getName()); + if (muser == null) { + return Result.err(Result.ERR_Denied, "%s is not valid for %s", add.mechid, trans.org().getName()); } - + // Policy 2: MechID must have valid Organization Owner Identity ouser = muser.responsibleTo(); - if(ouser == null) { - return Result.err(Result.ERR_Denied,"%s is not a valid Sponsor for %s at %s", - trans.user(),add.mechid,trans.org().getName()); + if (ouser == null) { + return Result.err(Result.ERR_Denied, "%s is not a valid Sponsor for %s at %s", trans.user(), add.mechid, + trans.org().getName()); } - // Policy 3: Renewal Days are between 10 and 60 (constants, may be parameterized) - if(add.renewDaysMAX_RENEWAL) { + } else if (add.renewDays > MAX_RENEWAL) { add.renewDays = MAX_RENEWAL; } @@ -564,101 +586,99 @@ public class CMService { add.sponsor = ouser.fullID(); // Policy 5: If Notify is blank, set to Owner's Email - if(add.notify==null || add.notify.length()==0) { - add.notify = "mailto:"+ouser.email(); + if (add.notify == null || add.notify.length() == 0) { + add.notify = "mailto:" + ouser.email(); } // Policy 6: Only do Domain by Exception - if(add.machine.startsWith("*")) { // Domain set + if (add.machine.startsWith("*")) { // Domain set CA ca = certman.getCA(add.ca); - if(ca==null) { + if (ca == null) { return Result.err(Result.ERR_BadData, "CA is required in Artifact"); } - if(!trans.fish(new AAFPermission(ca.getPermType(), add.ca, DOMAIN))) { - return Result.err(Result.ERR_Denied,"Domain Artifacts (%s) requires specific Permission", - add.machine); + if (!trans.fish(new AAFPermission(null,ca.getPermType(), add.ca, DOMAIN))) { + return Result.err(Result.ERR_Denied, "Domain Artifacts (%s) requires specific Permission", + add.machine); } } // Policy 7: only Owner may update info - if(trans.user().equals(add.sponsor)) { + if (trans.user().startsWith(ouser.id())) { return artiDAO.update(trans, add); } else { - return Result.err(Result.ERR_Denied,"%s may not update info for %s",trans.user(),muser.fullID()); + return Result.err(Result.ERR_Denied, "%s may not update info for %s", trans.user(), muser.fullID()); } } - return Result.err(Result.ERR_BadData,"No Artifacts to update"); + return Result.err(Result.ERR_BadData, "No Artifacts to update"); } - + public Result deleteArtifact(AuthzTrans trans, String mechid, String machine) throws OrganizationException { CertmanValidator v = new CertmanValidator(); - v.nullOrBlank("mechid", mechid) - .nullOrBlank("machine", machine); - if(v.err()) { - return Result.err(Result.ERR_BadData,v.errs()); + v.nullOrBlank("mechid", mechid).nullOrBlank("machine", machine); + if (v.err()) { + return Result.err(Result.ERR_BadData, v.errs()); } Result> rlad = artiDAO.read(trans, mechid, machine); - if(rlad.notOKorIsEmpty()) { - return Result.err(Result.ERR_NotFound,"Artifact for %s %s does not exist.",mechid,machine); + if (rlad.notOKorIsEmpty()) { + return Result.err(Result.ERR_NotFound, "Artifact for %s %s does not exist.", mechid, machine); } - - return deleteArtifact(trans,rlad.value.get(0)); + + return deleteArtifact(trans, rlad.value.get(0)); } - + private Result deleteArtifact(AuthzTrans trans, ArtiDAO.Data add) throws OrganizationException { - // Policy 1: Record should be delete able only by Existing Sponsor. - String sponsor=null; + // Policy 1: Record should be delete able only by Existing Sponsor. + String sponsor = null; Identity muser = trans.org().getIdentity(trans, add.mechid); - if(muser != null) { + if (muser != null) { Identity ouser = muser.responsibleTo(); - if(ouser!=null) { + if (ouser != null) { sponsor = ouser.fullID(); } } - // Policy 1.a: If Sponsorship is deleted in system of Record, then + // Policy 1.a: If Sponsorship is deleted in system of Record, then // accept deletion by sponsor in Artifact Table - if(sponsor==null) { + if (sponsor == null) { sponsor = add.sponsor; } - + String ns = FQI.reverseDomain(add.mechid); - if(trans.fish(new AAFPermission(ns + ACCESS, "*", "write")) - || trans.user().equals(sponsor)) { + if (trans.fish(new AAFPermission(ns,ACCESS, "*", "write")) || trans.user().equals(sponsor)) { return artiDAO.delete(trans, add, false); } - return Result.err(Result.ERR_Denied, "%1 is not allowed to delete this item",trans.user()); + return Result.err(Result.ERR_Denied, "%1 is not allowed to delete this item", trans.user()); } public Result deleteArtifact(AuthzTrans trans, List list) { CertmanValidator v = new CertmanValidator().artisRequired(list, 1); - if(v.err()) { - return Result.err(Result.ERR_BadData,v.errs()); + if (v.err()) { + return Result.err(Result.ERR_BadData, v.errs()); } try { boolean partial = false; - Result result=null; - for(ArtiDAO.Data add : list) { + Result result = null; + for (ArtiDAO.Data add : list) { result = deleteArtifact(trans, add); - if(result.notOK()) { + if (result.notOK()) { partial = true; } } - if(result == null) { - result = Result.err(Result.ERR_BadData,"No Artifacts to delete"); - } else if(partial) { + if (result == null) { + result = Result.err(Result.ERR_BadData, "No Artifacts to delete"); + } else if (partial) { result.partialContent(true); } return result; - } catch(Exception e) { + } catch (Exception e) { return Result.err(e); } } private String[] compileNotes(List notes) { String[] rv; - if(notes==null) { + if (notes == null) { rv = NO_NOTES; } else { rv = new String[notes.size()]; diff --git a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/facade/JU_FacadeImpl.java b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/facade/JU_FacadeImpl.java index dbfaaeef..27ac04e5 100644 --- a/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/facade/JU_FacadeImpl.java +++ b/auth/auth-certman/src/test/java/org/onap/aaf/auth/cm/facade/JU_FacadeImpl.java @@ -21,7 +21,7 @@ ******************************************************************************/ package org.onap.aaf.auth.cm.facade; -import static org.junit.Assert.*; +import static org.junit.Assert.assertNotNull; import static org.mockito.Mockito.CALLS_REAL_METHODS; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -31,31 +31,23 @@ import java.io.IOException; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; -import javax.xml.namespace.QName; -import javax.xml.validation.Schema; import org.junit.Before; -import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mockito; import org.mockito.runners.MockitoJUnitRunner; import org.onap.aaf.auth.cm.AAF_CM; -import org.onap.aaf.auth.cm.facade.FacadeImpl; import org.onap.aaf.auth.cm.mapper.Mapper; import org.onap.aaf.auth.cm.service.CMService; import org.onap.aaf.auth.env.AuthzEnv; import org.onap.aaf.auth.env.AuthzTrans; import org.onap.aaf.auth.layer.Result; import org.onap.aaf.cadi.aaf.AAFPermission; -import org.onap.aaf.cadi.aaf.v2_0.AAFLurPerm; import org.onap.aaf.misc.env.APIException; import org.onap.aaf.misc.env.Data; import org.onap.aaf.misc.env.LogTarget; import org.onap.aaf.misc.env.TimeTaken; -import org.onap.aaf.misc.env.Trans; -import org.onap.aaf.misc.rosetta.env.RosettaDF; -import org.onap.aaf.misc.rosetta.env.RosettaData; @RunWith(MockitoJUnitRunner.class) @@ -126,42 +118,42 @@ public class JU_FacadeImpl { @Test public void check() throws IOException { - AAFPermission ap = new AAFPermission("str1","str3","str2"); + AAFPermission ap = new AAFPermission("str0","str1","str3","str2"); String perms = ap.getInstance(); assertNotNull(hImpl.check(trans, resp, perms)); } @Test public void checkNull() throws IOException { - AAFPermission ap = new AAFPermission(null,"Str3","str2"); + AAFPermission ap = new AAFPermission(null,null,"Str3","str2"); String perms = ap.getInstance(); assertNotNull(hImpl.check(trans, resp, perms)); } @Test public void checkTwoNull() throws IOException { - AAFPermission ap = new AAFPermission(null,null,"str2"); + AAFPermission ap = new AAFPermission(null,null,null,"str2"); String perms = ap.getInstance(); assertNotNull(fImpl.check(trans, resp, perms)); } @Test public void checkAllNull() throws IOException { - AAFPermission ap = new AAFPermission(null,null,null); + AAFPermission ap = new AAFPermission(null,null,null,null); String perms = ap.getInstance(); assertNotNull(fImpl.check(trans, resp, perms)); } @Test public void checkTrans_null() throws IOException { - AAFPermission ap = new AAFPermission("str1","str3","str2"); + AAFPermission ap = new AAFPermission("str0","str1","str3","str2"); String perms = ap.getInstance(); assertNotNull(hImpl.check(null, resp, perms)); } @Test public void checkRespNull() throws IOException { - AAFPermission ap = new AAFPermission("str1","str3","str2"); + AAFPermission ap = new AAFPermission("str0","str1","str3","str2"); String perms = ap.getInstance(); assertNotNull(hImpl.check(trans, null, perms)); } -- cgit 1.2.3-korg