diff options
author | Instrumental <jonathan.gathman@att.com> | 2019-02-22 13:52:58 -0600 |
---|---|---|
committer | Instrumental <jonathan.gathman@att.com> | 2019-02-22 14:13:53 -0600 |
commit | 4a698c2e3d926fd69673eea8b15a78bc7770a29c (patch) | |
tree | dca2f806dd535916a4b62c840cb3c2853a848e5c /shiro/src | |
parent | ac7cd3ac1cd79eff3a8e20e23e5a550fb68b8af2 (diff) |
Add Multi-Realm class handling
Also, improve Logging
Issue-ID: AAF-771
Change-Id: I4cf286b5c474596f5e824e5204598cf0c1bb014c
Signed-off-by: Instrumental <jonathan.gathman@att.com>
Diffstat (limited to 'shiro/src')
5 files changed, 194 insertions, 118 deletions
diff --git a/shiro/src/main/java/org/onap/aaf/cadi/shiro/AAFAuthenticationInfo.java b/shiro/src/main/java/org/onap/aaf/cadi/shiro/AAFAuthenticationInfo.java index beb9707..99e387d 100644 --- a/shiro/src/main/java/org/onap/aaf/cadi/shiro/AAFAuthenticationInfo.java +++ b/shiro/src/main/java/org/onap/aaf/cadi/shiro/AAFAuthenticationInfo.java @@ -24,20 +24,17 @@ import java.nio.ByteBuffer; import java.security.NoSuchAlgorithmException; import java.security.SecureRandom; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.PrincipalCollection; import org.onap.aaf.cadi.Access; +import org.onap.aaf.cadi.Access.Level; import org.onap.aaf.cadi.Hash; public class AAFAuthenticationInfo implements AuthenticationInfo { private static final long serialVersionUID = -1502704556864321020L; - final static Logger logger = LoggerFactory.getLogger(AAFAuthenticationInfo.class); - // We assume that Shiro is doing Memory Only, and this salt is not needed cross process private final static int salt = new SecureRandom().nextInt(); @@ -50,15 +47,16 @@ public class AAFAuthenticationInfo implements AuthenticationInfo { apc = new AAFPrincipalCollection(username); hash = getSaltedCred(password); } + @Override public byte[] getCredentials() { -// logger.info("AAFAuthenticationInfo.getCredentials"); + access.log(Level.DEBUG, "AAFAuthenticationInfo.getCredentials"); return hash; } @Override public PrincipalCollection getPrincipals() { -// logger.info( "AAFAuthenticationInfo.getPrincipals"); + access.log(Level.DEBUG, "AAFAuthenticationInfo.getPrincipals"); return apc; } @@ -67,7 +65,7 @@ public class AAFAuthenticationInfo implements AuthenticationInfo { UsernamePasswordToken upt = (UsernamePasswordToken)atoken; if(apc.getPrimaryPrincipal().getName().equals(upt.getPrincipal())) { byte[] newhash = getSaltedCred(new String(upt.getPassword())); - logger.info("Successful authentication attempt by " +upt.getPrincipal()); + access.printf(Level.INFO,"Successful authentication attempt by %s",upt.getPrincipal()); if(newhash.length==hash.length) { for(int i=0;i<hash.length;++i) { if(hash[i]!=newhash[i]) { @@ -77,6 +75,8 @@ public class AAFAuthenticationInfo implements AuthenticationInfo { return true; } } + } else { + access.printf(Level.ERROR, "AAFAuthenticationInfo received non-AAF token %s (%s)",atoken.getPrincipal(),atoken.getClass().getName()); } return false; } diff --git a/shiro/src/main/java/org/onap/aaf/cadi/shiro/AAFAuthorizationInfo.java b/shiro/src/main/java/org/onap/aaf/cadi/shiro/AAFAuthorizationInfo.java index 4b0993b..fc0f4ff 100644 --- a/shiro/src/main/java/org/onap/aaf/cadi/shiro/AAFAuthorizationInfo.java +++ b/shiro/src/main/java/org/onap/aaf/cadi/shiro/AAFAuthorizationInfo.java @@ -29,8 +29,6 @@ import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.Permission; import org.onap.aaf.cadi.Access; import org.onap.aaf.cadi.Access.Level; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * We treat "roles" and "permissions" in a similar way for first pass. @@ -41,8 +39,6 @@ import org.slf4j.LoggerFactory; public class AAFAuthorizationInfo implements AuthorizationInfo { private static final long serialVersionUID = -4805388954462426018L; - final static Logger logger = LoggerFactory.getLogger(AAFAuthorizationInfo.class); - private Access access; private Principal bait; private List<org.onap.aaf.cadi.Permission> pond; @@ -55,7 +51,6 @@ public class AAFAuthorizationInfo implements AuthorizationInfo { this.pond = pond; sPerms=null; oPerms=null; - } public Principal principal() { @@ -64,7 +59,7 @@ public class AAFAuthorizationInfo implements AuthorizationInfo { @Override public Collection<Permission> getObjectPermissions() { -// logger.info("AAFAuthorizationInfo.getObjectPermissions"); + access.log(Level.DEBUG, "AAFAuthorizationInfo.getObjectPermissions"); synchronized(bait) { if(oPerms == null) { oPerms = new ArrayList<Permission>(); @@ -73,29 +68,25 @@ public class AAFAuthorizationInfo implements AuthorizationInfo { } } } - - return oPerms; } @Override public Collection<String> getRoles() { -// logger.info("AAFAuthorizationInfo.getRoles"); + access.log(Level.INFO,"AAFAuthorizationInfo.getRoles"); // Until we decide to make Roles available, tie into String based permissions. return getStringPermissions(); } @Override public Collection<String> getStringPermissions() { - -// logger.info("AAFAuthorizationInfo.getStringPermissions"); + access.log(Level.INFO,"AAFAuthorizationInfo.getStringPermissions"); synchronized(bait) { if(sPerms == null) { sPerms = new ArrayList<String>(); for(org.onap.aaf.cadi.Permission p : pond) { sPerms.add(p.getKey().replace("|",":")); - logger.info("the user has " +p.getKey()); - + access.printf(Level.INFO,"the user has %s",p.getKey()); } } } diff --git a/shiro/src/main/java/org/onap/aaf/cadi/shiro/AAFPrincipalCollection.java b/shiro/src/main/java/org/onap/aaf/cadi/shiro/AAFPrincipalCollection.java index 15fad53..3998aa5 100644 --- a/shiro/src/main/java/org/onap/aaf/cadi/shiro/AAFPrincipalCollection.java +++ b/shiro/src/main/java/org/onap/aaf/cadi/shiro/AAFPrincipalCollection.java @@ -27,15 +27,12 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Set; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import org.apache.shiro.subject.PrincipalCollection; public class AAFPrincipalCollection implements PrincipalCollection { private static final long serialVersionUID = 558246013419818831L; - private static final Logger logger = LoggerFactory.getLogger(AAFPrincipalCollection.class); private static final Set<String> realmSet; private final Principal principal; private List<Principal> list=null; diff --git a/shiro/src/main/java/org/onap/aaf/cadi/shiro/AAFRealm.java b/shiro/src/main/java/org/onap/aaf/cadi/shiro/AAFRealm.java index 0fc962f..52bf354 100644 --- a/shiro/src/main/java/org/onap/aaf/cadi/shiro/AAFRealm.java +++ b/shiro/src/main/java/org/onap/aaf/cadi/shiro/AAFRealm.java @@ -21,17 +21,15 @@ package org.onap.aaf.cadi.shiro; import java.io.IOException; -import java.io.PrintStream; import java.security.Principal; import java.util.ArrayList; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.TreeMap; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentSkipListSet; - -import org.apache.log4j.PropertyConfigurator; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; @@ -55,93 +53,186 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class AAFRealm extends AuthorizingRealm { - - final static Logger logger = LoggerFactory.getLogger(AAFRealm.class); - public static final String AAF_REALM = "AAFRealm"; + private static final Logger logger = LoggerFactory.getLogger(AAFRealm.class); + private static Singleton singleton = Singleton.singleton(); - private PropAccess access; - private AAFCon<?> acon; - private AAFAuthn<?> authn; - private HashSet<Class<? extends AuthenticationToken>> supports; - private AAFLurPerm authz; - private MapBathConverter mbc; - private Map<String,String> idMap; - - - /** - * - * There appears to be no configuration objects or references available for CADI to start with. - * - */ - public AAFRealm () { - access = new PropAccess(); // pick up cadi_prop_files from VM_Args - mbc = null; - idMap = null; - String cadi_prop_files = access.getProperty(Config.CADI_PROP_FILES); - if(cadi_prop_files==null) { - String msg = Config.CADI_PROP_FILES + " in VM Args is required to initialize AAFRealm."; - logger.info(msg); - throw new RuntimeException(msg); - } else { - try { - acon = AAFCon.newInstance(access); - authn = acon.newAuthn(); - authz = acon.newLur(authn); - - final String csv = access.getProperty(Config.CADI_BATH_CONVERT); - if(csv!=null) { - try { - mbc = new MapBathConverter(access, new CSV(csv)); - logger.info("MapBathConversion enabled with file "+csv); - idMap = new TreeMap<String,String>(); - // Load - for(Entry<String, String> es : mbc.map().entrySet()) { - String oldID = es.getKey(); - if(oldID.startsWith("Basic ")) { - oldID = Symm.base64noSplit.decode(oldID.substring(6)); - int idx = oldID.indexOf(':'); - if(idx>=0) { - oldID = oldID.substring(0, idx); + private static class Singleton { + private AAFCon<?> acon; + private AAFAuthn<?> authn; + private Set<Class<? extends AuthenticationToken>> supports; + private AAFLurPerm authz; + private MapBathConverter mbc; + private Map<String,String> idMap; + private Singleton() { + mbc = null; + idMap = null; + String cadi_prop_files = access.getProperty(Config.CADI_PROP_FILES); + if(cadi_prop_files==null) { + String msg = Config.CADI_PROP_FILES + " in VM Args is required to initialize AAFRealm."; + access.log(Level.INFO,msg); + throw new RuntimeException(msg); + } else { + try { + acon = AAFCon.newInstance(access); + authn = acon.newAuthn(); + authz = acon.newLur(authn); + + final String csv = access.getProperty(Config.CADI_BATH_CONVERT); + if(csv!=null) { + try { + mbc = new MapBathConverter(access, new CSV(csv)); + access.log(Level.INFO, "MapBathConversion enabled with file ",csv); + idMap = new ConcurrentHashMap<String,String>(); + // Load + for(Entry<String, String> es : mbc.map().entrySet()) { + String oldID = es.getKey(); + if(oldID.startsWith("Basic ")) { + oldID = Symm.base64noSplit.decode(oldID.substring(6)); + int idx = oldID.indexOf(':'); + if(idx>=0) { + oldID = oldID.substring(0, idx); + } } - } - String newID = es.getValue(); - if(newID.startsWith("Basic ")) { - newID = Symm.base64noSplit.decode(newID.substring(6)); - int idx = newID.indexOf(':'); - if(idx>=0) { - newID = newID.substring(0, idx); + String newID = es.getValue(); + if(newID.startsWith("Basic ")) { + newID = Symm.base64noSplit.decode(newID.substring(6)); + int idx = newID.indexOf(':'); + if(idx>=0) { + newID = newID.substring(0, idx); + } } + idMap.put(oldID,newID); + } - idMap.put(oldID,newID); - + } catch (IOException e) { + access.log(e); } - } catch (IOException e) { - logger.info(e.getMessage(), e); } + } catch (APIException | CadiException | LocatorException e) { + String msg = "Cannot initiate AAFRealm"; + access.log(Level.ERROR,e,msg); + throw new RuntimeException(msg,e); } - } catch (APIException | CadiException | LocatorException e) { - String msg = "Cannot initiate AAFRealm"; - logger.info(msg + " "+ e.getMessage(), e); - throw new RuntimeException(msg,e); } + supports = new ConcurrentSkipListSet<>(); + supports.add(UsernamePasswordToken.class); } - supports = new HashSet<Class<? extends AuthenticationToken>>(); - supports.add(UsernamePasswordToken.class); - } + + public static synchronized Singleton singleton() { + if(singleton==null) { + singleton = new Singleton(); + } + return singleton; + } + + // pick up cadi_prop_files from VM_Args + private final PropAccess access = new PropAccess() { + @Override + public void log(Exception e, Object... elements) { + logger.error(buildMsg(Level.ERROR, elements).toString(),e); + } + + @Override + public void log(Level level, Object... elements) { + if(willLog(level)) { + String str = buildMsg(level, elements).toString(); + switch(level) { + case WARN: + case AUDIT: + logger.warn(str); + break; + case DEBUG: + logger.debug(str); + break; + case ERROR: + logger.warn(str); + break; + case INFO: + case INIT: + logger.info(str); + break; + case NONE: + break; + case TRACE: + logger.trace(str); + break; + } + } + } + + @Override + public void printf(Level level, String fmt, Object... elements) { + if(willLog(level)) { + String str = String.format(fmt, elements); + switch(level) { + case WARN: + case AUDIT: + logger.warn(str); + break; + case DEBUG: + logger.debug(str); + break; + case ERROR: + logger.warn(str); + break; + case INFO: + case INIT: + logger.info(str); + break; + case NONE: + break; + case TRACE: + logger.trace(str); + break; + } + } + } + + @Override + public boolean willLog(Level level) { + if(super.willLog(level)) { + switch(level) { + case AUDIT: + return logger.isWarnEnabled(); + case DEBUG: + return logger.isDebugEnabled(); + case ERROR: + return logger.isErrorEnabled(); + case INFO: + case INIT: + return logger.isInfoEnabled(); + case NONE: + return false; + case TRACE: + return logger.isTraceEnabled(); + case WARN: + return logger.isWarnEnabled(); + + } + } + return false; + } + }; + } + + /** + * + * There appears to be no configuration objects or references available for CADI to start with. + * + */ @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { - logger.info("AAFRealm.doGetAuthenticationInfo :"+token); final UsernamePasswordToken upt = (UsernamePasswordToken)token; final String user = upt.getUsername(); String authUser = user; final String password=new String(upt.getPassword()); String authPassword = password; - if(mbc!=null) { + if(singleton.mbc!=null) { try { final String oldBath = "Basic " + Symm.base64noSplit.encode(user+':'+password); - String bath = mbc.convert(access, oldBath); + String bath = singleton.mbc.convert(singleton.access, oldBath); if(bath!=oldBath) { bath = Symm.base64noSplit.decode(bath.substring(6)); int colon = bath.indexOf(':'); @@ -151,26 +242,23 @@ public class AAFRealm extends AuthorizingRealm { } } } catch (IOException e) { - - logger.info(e.getMessage(), e); - + singleton.access.log(e); } } String err; try { - err = authn.validate(authUser,authPassword); + err = singleton.authn.validate(authUser,authPassword); + if(err != null) { + singleton.access.log(Level.INFO, err); + throw new AuthenticationException(err); + } + } catch (IOException e) { - err = "Credential cannot be validated"; - logger.info(e.getMessage(), e); + singleton.access.log(e,"Credential cannot be validated"); } - if(err != null) { - logger.info(err); - throw new AuthenticationException(err); - } - return new AAFAuthenticationInfo( - access, + singleton.access, user, password ); @@ -182,7 +270,6 @@ public class AAFRealm extends AuthorizingRealm { if(ai instanceof AAFAuthenticationInfo) { if(!((AAFAuthenticationInfo)ai).matches(atoken)) { throw new AuthenticationException("Credentials do not match"); - } } else { @@ -198,9 +285,9 @@ public class AAFRealm extends AuthorizingRealm { protected AAFAuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { Principal bait = (Principal)principals.getPrimaryPrincipal(); Principal newBait = bait; - if(idMap!=null) { - final String newID = idMap.get(bait.getName()); - logger.info("Successful authentication attempt by " +bait.getName()); + if(singleton.idMap!=null) { + final String newID = singleton.idMap.get(bait.getName()); + singleton.access.printf(Level.INFO,"Successful authentication attempt by %s",bait.getName()); if(newID!=null) { newBait = new Principal() { @Override @@ -211,14 +298,13 @@ public class AAFRealm extends AuthorizingRealm { } } List<Permission> pond = new ArrayList<>(); - authz.fishAll(newBait,pond); - return new AAFAuthorizationInfo(access,bait,pond); - + singleton.authz.fishAll(newBait,pond); + return new AAFAuthorizationInfo(singleton.access,bait,pond); } @Override public boolean supports(AuthenticationToken token) { - return supports.contains(token.getClass()); + return singleton.supports.contains(token.getClass()); } @Override diff --git a/shiro/src/test/java/org/onap/aaf/cadi/shiro/test/JU_AAFRealm.java b/shiro/src/test/java/org/onap/aaf/cadi/shiro/test/JU_AAFRealm.java index 281f8ad..f49ecb4 100644 --- a/shiro/src/test/java/org/onap/aaf/cadi/shiro/test/JU_AAFRealm.java +++ b/shiro/src/test/java/org/onap/aaf/cadi/shiro/test/JU_AAFRealm.java @@ -27,18 +27,20 @@ import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.Permission; import org.apache.shiro.subject.PrincipalCollection; +import org.junit.Test; import org.onap.aaf.cadi.aaf.AAFPermission; +import org.onap.aaf.cadi.config.Config; import org.onap.aaf.cadi.shiro.AAFRealm; import org.onap.aaf.cadi.shiro.AAFShiroPermission; import junit.framework.Assert; public class JU_AAFRealm { -/* - @Test + public void test() { // NOTE This is a live test. This JUnit needs to be built with "Mock" before it can be // an official JUNIT + try { System.setProperty(Config.CADI_PROP_FILES, "/opt/app/osaaf/local/org.onap.aai.props"); TestAAFRealm ar = new TestAAFRealm(); @@ -61,7 +63,7 @@ public class JU_AAFRealm { Assert.fail(); } } - */ + private void testAPerm(boolean expect, AuthorizationInfo azi, String ns, String type, String instance, String action) { AAFShiroPermission testPerm = new AAFShiroPermission(new AAFPermission(ns,type,instance,action,new ArrayList<String>())); |