X-Git-Url: https://gerrit.onap.org/r/gitweb?a=blobdiff_plain;f=shiro%2Fsrc%2Fmain%2Fjava%2Forg%2Fonap%2Faaf%2Fcadi%2Fshiro%2FAAFRealm.java;h=818ec9e888aedf80688e9dff8ec1b5c7cdde75d4;hb=4a3962dec1da8d43e0db225d42fa4d57e338e1d6;hp=3577c13025e5ad1c328d4d52de242f739c328190;hpb=355cda9893529070169e4814158924d1d14094f8;p=aaf%2Fcadi.git 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 3577c13..818ec9e 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 @@ -23,13 +23,17 @@ package org.onap.aaf.cadi.shiro; import java.io.IOException; import java.security.Principal; import java.util.ArrayList; -import java.util.HashSet; +import java.util.Collections; import java.util.List; +import java.util.Map; +import java.util.Map.Entry; +import java.util.TreeMap; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.UsernamePasswordToken; +import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.onap.aaf.cadi.Access.Level; @@ -38,101 +42,234 @@ import org.onap.aaf.cadi.LocatorException; import org.onap.aaf.cadi.Permission; import org.onap.aaf.cadi.PropAccess; import org.onap.aaf.cadi.Symm; +import org.onap.aaf.cadi.aaf.AAFPermission; import org.onap.aaf.cadi.aaf.v2_0.AAFAuthn; import org.onap.aaf.cadi.aaf.v2_0.AAFCon; import org.onap.aaf.cadi.aaf.v2_0.AAFLurPerm; import org.onap.aaf.cadi.config.Config; import org.onap.aaf.cadi.filter.MapBathConverter; import org.onap.aaf.cadi.util.CSV; +import org.onap.aaf.cadi.util.Split; import org.onap.aaf.misc.env.APIException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/* + * Note: Shiro Realm document + * https://shiro.apache.org/realm.html + */ public class AAFRealm extends AuthorizingRealm { public static final String AAF_REALM = "AAFRealm"; + private static final Logger logger = LoggerFactory.getLogger(AAFRealm.class); - private PropAccess access; - private AAFCon acon; - private AAFAuthn authn; - private HashSet> supports; - private AAFLurPerm authz; - private MapBathConverter mbc; + // Package on purpose + static Singleton singleton = Singleton.singleton(); + public static class Singleton { + public AAFCon acon; + public AAFAuthn authn; + public AAFLurPerm authz; +// private Set> supports; + + private MapBathConverter mbc; + private Map idMap; + private Singleton() { + logger.info("Creating AAFRealm.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(access,csv)); + access.log(Level.INFO, "MapBathConversion enabled with file ",csv); + idMap = Collections.synchronizedMap(new TreeMap()); + // Load + for(Entry 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); + } + } + idMap.put(oldID,newID); + } + } catch (IOException e) { + access.log(e); + } + } + } catch (APIException | CadiException | LocatorException e) { + String msg = "Cannot initiate AAFRealm"; + access.log(Level.ERROR,e,msg); + throw new RuntimeException(msg,e); + } + } + + // There is only one of these. If there are more, put back +// supports = Collections.synchronizedSet(new HashSet<>()); +// 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.error(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.error(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 WARN: + 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(); + } + } + return false; + } + }; + } + /** * * 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; - 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.INIT,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.printf(Level.INIT, "MapBathConversion enabled with file %s\n",csv); - } catch (IOException e) { - access.log(e); - } - } - } catch (APIException | CadiException | LocatorException e) { - String msg = "Cannot initiate AAFRealm"; - access.log(Level.INIT,msg,e.getMessage()); - throw new RuntimeException(msg,e); - } - } - supports = new HashSet>(); - supports.add(UsernamePasswordToken.class); - } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { - access.log(Level.DEBUG, "AAFRealm.doGetAuthenticationInfo",token); - + logger.debug("AAFRealm.doGetAuthenticationInfo"); final UsernamePasswordToken upt = (UsernamePasswordToken)token; - String user = upt.getUsername(); - String password=new String(upt.getPassword()); - if(mbc!=null) { + final String user = upt.getUsername(); + String authUser = user; + final String password=new String(upt.getPassword()); + String authPassword = password; + 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(':'); if(colon>=0) { - user = bath.substring(0, colon); - password = bath.substring(colon+1); + authUser = bath.substring(0, colon); + authPassword = bath.substring(colon+1); } } } catch (IOException e) { - access.log(e); - } + singleton.access.log(e); + } } String err; try { - err = authn.validate(user,password); + 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"; - access.log(e, err); + singleton.access.log(e,"Credential cannot be validated"); } - if(err != null) { - access.log(Level.DEBUG, err); - throw new AuthenticationException(err); - } - return new AAFAuthenticationInfo( - access, + singleton.access, user, password ); @@ -140,6 +277,7 @@ public class AAFRealm extends AuthorizingRealm { @Override protected void assertCredentialsMatch(AuthenticationToken atoken, AuthenticationInfo ai)throws AuthenticationException { + logger.debug("AAFRealm.assertCredentialsMatch"); if(ai instanceof AAFAuthenticationInfo) { if(!((AAFAuthenticationInfo)ai).matches(atoken)) { throw new AuthenticationException("Credentials do not match"); @@ -149,21 +287,33 @@ public class AAFRealm extends AuthorizingRealm { } } - @Override protected AAFAuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { - access.log(Level.DEBUG, "AAFRealm.doGetAuthenthorizationInfo"); + logger.debug("AAFRealm.doGetAuthorizationInfo"); Principal bait = (Principal)principals.getPrimaryPrincipal(); + Principal newBait = bait; + if(singleton.idMap!=null) { + final String newID = singleton.idMap.get(bait.getName()); + if(newID!=null) { + singleton.access.printf(Level.INFO,"Successful authentication Translation %s to %s",bait.getName(), newID); + newBait = new Principal() { + @Override + public String getName() { + return newID; + } + }; + } + } List pond = new ArrayList<>(); - authz.fishAll(bait,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()); + // Only one was being loaded. If more are needed uncomment the multi-class mode + return token instanceof UsernamePasswordToken; +// return singleton.supports.contains(token.getClass()); } @Override @@ -171,4 +321,58 @@ public class AAFRealm extends AuthorizingRealm { return AAF_REALM; } + private AAFPermission aafPerm(String permission) { + String[] pa = Split.splitTrim('|', permission); + switch(pa.length) { + case 3: + return new AAFPermission(null,pa[0],pa[1],pa[2]); + case 4: + return new AAFPermission(pa[0],pa[1],pa[2],pa[3]); + default: + return null; + } + } +/* + @Override + public boolean isPermitted(PrincipalCollection principals, String permission) { + logger.debug("AAFRealm.isPermitted(principals,permission)"); + AAFPermission ap = aafPerm(permission); + if(ap!=null) { + return singleton.authz.fish((Principal)principals.getPrimaryPrincipal(), ap); + } + return false; + } + + @Override + protected boolean isPermitted(org.apache.shiro.authz.Permission permission, AuthorizationInfo info) { + logger.debug("AAFRealm.isPermitted(shiro.Permission,AuthorizationInfo)"); + if(info instanceof AAFAuthorizationInfo) { + AAFPermission ap = aafPerm(permission.toString()); + if(ap!=null) { + return singleton.authz.fish(((AAFAuthorizationInfo)info).principal(), ap); + } + return false; + } + return super.isPermitted(permission, info); + } + + @Override + protected boolean[] isPermitted(List permissions, AuthorizationInfo info) { + logger.debug("AAFRealm.isPermitted(List,AuthorizationInfo)"); + if(info instanceof AAFAuthorizationInfo) { + boolean rv[] = new boolean[permissions.size()]; + int i=0; + for(org.apache.shiro.authz.Permission sp : permissions) { + AAFPermission ap = aafPerm(sp.toString()); + if(ap!=null) { + rv[i++]=singleton.authz.fish(((AAFAuthorizationInfo)info).principal(), ap); + } else { + rv[i++]=false; + } + } + return rv; + } + return super.isPermitted(permissions, info); + } +*/ }