Add Multi-Realm class handling
[aaf/cadi.git] / shiro / src / main / java / org / onap / aaf / cadi / shiro / AAFRealm.java
index 3577c13..52bf354 100644 (file)
@@ -23,8 +23,12 @@ 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.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentSkipListSet;
 
 import org.apache.shiro.authc.AuthenticationException;
 import org.apache.shiro.authc.AuthenticationInfo;
@@ -45,94 +49,216 @@ 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.misc.env.APIException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 public class AAFRealm extends AuthorizingRealm {
        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 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);
+                                                                       }
+                                                               }
+                                                               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);
+                               }
+                       }
+                       supports = new ConcurrentSkipListSet<>();
+                       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.
         *  
         */
-       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<Class<? extends AuthenticationToken>>();
-               supports.add(UsernamePasswordToken.class);
-       }
 
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
-               access.log(Level.DEBUG, "AAFRealm.doGetAuthenticationInfo",token);
-               
                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,30 +266,45 @@ public class AAFRealm extends AuthorizingRealm {
 
        @Override
        protected void assertCredentialsMatch(AuthenticationToken atoken, AuthenticationInfo ai)throws AuthenticationException {
+               
                if(ai instanceof AAFAuthenticationInfo) {
                        if(!((AAFAuthenticationInfo)ai).matches(atoken)) {
                                throw new AuthenticationException("Credentials do not match");
                        }
+                       
                } else {
                        throw new AuthenticationException("AuthenticationInfo is not an AAFAuthenticationInfo");
+               
                }
        }
 
 
+
+
        @Override
        protected AAFAuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
-               access.log(Level.DEBUG, "AAFRealm.doGetAuthenthorizationInfo");
                Principal bait = (Principal)principals.getPrimaryPrincipal();
+               Principal newBait = bait;
+               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
+                                       public String getName() {
+                                               return newID;
+                                       }
+                               };
+                       }
+               }
                List<Permission> 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());
+               return singleton.supports.contains(token.getClass());
        }
 
        @Override