Update shiro logging and sl4j init
[aaf/cadi.git] / shiro / src / main / java / org / onap / aaf / cadi / shiro / AAFRealm.java
1 /**
2  * ============LICENSE_START====================================================
3  * org.onap.aaf
4  * ===========================================================================
5  * Copyright (c) 2018 AT&T Intellectual Property. All rights reserved.
6  * ===========================================================================
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  * 
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  * 
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  * ============LICENSE_END====================================================
19  *
20  */
21 package org.onap.aaf.cadi.shiro;
22
23 import java.io.IOException;
24 import java.io.PrintStream;
25 import java.security.Principal;
26 import java.util.ArrayList;
27 import java.util.HashSet;
28 import java.util.List;
29 import java.util.Map;
30 import java.util.Map.Entry;
31 import java.util.TreeMap;
32
33 import org.apache.log4j.PropertyConfigurator;
34 import org.apache.shiro.authc.AuthenticationException;
35 import org.apache.shiro.authc.AuthenticationInfo;
36 import org.apache.shiro.authc.AuthenticationToken;
37 import org.apache.shiro.authc.UsernamePasswordToken;
38 import org.apache.shiro.realm.AuthorizingRealm;
39 import org.apache.shiro.subject.PrincipalCollection;
40 import org.onap.aaf.cadi.Access.Level;
41 import org.onap.aaf.cadi.CadiException;
42 import org.onap.aaf.cadi.LocatorException;
43 import org.onap.aaf.cadi.Permission;
44 import org.onap.aaf.cadi.PropAccess;
45 import org.onap.aaf.cadi.Symm;
46 import org.onap.aaf.cadi.aaf.v2_0.AAFAuthn;
47 import org.onap.aaf.cadi.aaf.v2_0.AAFCon;
48 import org.onap.aaf.cadi.aaf.v2_0.AAFLurPerm;
49 import org.onap.aaf.cadi.config.Config;
50 import org.onap.aaf.cadi.filter.MapBathConverter;
51 import org.onap.aaf.cadi.util.CSV;
52 import org.onap.aaf.misc.env.APIException;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55
56 public class AAFRealm extends AuthorizingRealm {
57         
58         final static Logger logger =  LoggerFactory.getLogger(AAFRealm.class);
59         
60         public static final String AAF_REALM = "AAFRealm";
61         
62         private PropAccess access;
63         private AAFCon<?> acon;
64         private AAFAuthn<?> authn;
65         private HashSet<Class<? extends AuthenticationToken>> supports;
66         private AAFLurPerm authz;
67         private MapBathConverter mbc;
68         private Map<String,String> idMap;
69         
70
71         /**
72          * 
73          * There appears to be no configuration objects or references available for CADI to start with.
74          *  
75          */
76         public AAFRealm () {
77                 access = new PropAccess(); // pick up cadi_prop_files from VM_Args
78                 mbc = null;
79                 idMap = null;
80                 String cadi_prop_files = access.getProperty(Config.CADI_PROP_FILES);
81                 if(cadi_prop_files==null) {
82                         String msg = Config.CADI_PROP_FILES + " in VM Args is required to initialize AAFRealm.";
83                         access.log(Level.DEBUG,msg);
84                         throw new RuntimeException(msg);
85                 } else {
86                         try {
87                                 String log4jConfigFile = "./etc/org.ops4j.pax.logging.cfg";
88                                 
89                         PropertyConfigurator.configure(log4jConfigFile);
90                         System.setOut(createLoggingProxy(System.out));
91                         System.setErr(createLoggingProxy(System.err));
92                         } catch(Exception e) {
93                                 e.printStackTrace();
94                         }
95                         //System.out.println("Configuration done");
96                         try {
97                                 acon = AAFCon.newInstance(access);
98                                 authn = acon.newAuthn();
99                                 authz = acon.newLur(authn);
100                                 final String csv = access.getProperty(Config.CADI_BATH_CONVERT);
101                                 if(csv!=null) {
102                                         try {
103                                                 mbc = new MapBathConverter(access, new CSV(csv));
104                                                 logger.info("MapBathConversion enabled with file "+csv);
105                                                 idMap = new TreeMap<String,String>();
106                                                 // Load 
107                                                 for(Entry<String, String> es : mbc.map().entrySet()) {
108                                                         String oldID = es.getKey();
109                                                         if(oldID.startsWith("Basic ")) {
110                                                                 oldID = Symm.base64noSplit.decode(oldID.substring(6));
111                                                                 int idx = oldID.indexOf(':');
112                                                                 if(idx>=0) {
113                                                                         oldID = oldID.substring(0, idx);
114                                                                 }
115                                                         }
116                                                         String newID = es.getValue();
117                                                         if(newID.startsWith("Basic ")) {
118                                                                 newID = Symm.base64noSplit.decode(newID.substring(6));
119                                                                 int idx = newID.indexOf(':');
120                                                                 if(idx>=0) {
121                                                                         newID = newID.substring(0, idx);
122                                                                 }
123                                                         }
124                                                         idMap.put(oldID,newID);
125                                                 }
126                                         } catch (IOException e) {
127 //                                              access.log(e);
128                                         }
129                                 }
130                         } catch (APIException | CadiException | LocatorException e) {
131                                 String msg = "Cannot initiate AAFRealm";
132                                 access.log(Level.INIT,msg,e.getMessage());
133                                 throw new RuntimeException(msg,e);
134                         }
135                 }
136                 supports = new HashSet<Class<? extends AuthenticationToken>>();
137                 supports.add(UsernamePasswordToken.class);
138         }
139         public static PrintStream createLoggingProxy(final PrintStream realPrintStream) {
140         return new PrintStream(realPrintStream) {
141             public void print(final String string) {
142                 realPrintStream.print(string);
143                 logger.info(string);
144             }
145         };
146     }
147
148         @Override
149         protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
150                 final UsernamePasswordToken upt = (UsernamePasswordToken)token;
151                 final String user = upt.getUsername();
152                 String authUser = user; 
153                 final String password=new String(upt.getPassword());
154                 String authPassword = password;
155                 if(mbc!=null) { 
156                         try {
157
158                                 final String oldBath = "Basic " + Symm.base64noSplit.encode(user+':'+password);
159                                 String bath = mbc.convert(access, oldBath);
160                                 if(bath!=oldBath) {
161                                         bath = Symm.base64noSplit.decode(bath.substring(6));
162                                         int colon = bath.indexOf(':');
163                                         if(colon>=0) {
164                                                 authUser = bath.substring(0, colon);
165                                                 authPassword = bath.substring(colon+1); 
166                                                 access.log(Level.DEBUG, authUser,"user authenticated");
167                                                 access.log(Level.DEBUG, authn.validate(authUser,authPassword));
168                                         }
169                                 }
170                         } catch (IOException e) {
171                                 access.log(e);
172                         } 
173                 }
174                 String err;
175                 try {
176                         err = authn.validate(authUser,authPassword);
177                 } catch (IOException e) {
178                         err = "Credential cannot be validated";
179                         access.log(Level.DEBUG, e, err);
180                 }
181                 
182                 if(err != null) {
183                         access.log(Level.DEBUG, err, " - Credential cannot be validated");
184                         throw new AuthenticationException(err);
185                 }
186
187             return new AAFAuthenticationInfo(
188                         access,
189                         user,
190                         password
191                         
192             );
193             
194         }
195
196         @Override
197         protected void assertCredentialsMatch(AuthenticationToken atoken, AuthenticationInfo ai)throws AuthenticationException {
198                 if(ai instanceof AAFAuthenticationInfo) {
199                         if(!((AAFAuthenticationInfo)ai).matches(atoken)) {
200                                 throw new AuthenticationException("Credentials do not match");
201                         }
202                 } else {
203                         throw new AuthenticationException("AuthenticationInfo is not an AAFAuthenticationInfo");
204                 }
205         }
206
207
208         @Override
209         protected AAFAuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
210                 Principal bait = (Principal)principals.getPrimaryPrincipal();
211                 Principal newBait = bait;
212                 if(idMap!=null) {
213                         final String newID = idMap.get(bait.getName());
214                         if(newID!=null) {
215                                 newBait = new Principal() {
216                                         @Override
217                                         public String getName() {
218                                                 return newID;
219                                         }
220                                 };
221                         }
222                 }
223                 List<Permission> pond = new ArrayList<>();
224                 authz.fishAll(newBait,pond);
225                 return new AAFAuthorizationInfo(access,bait,pond);
226        
227         }
228
229         @Override
230         public boolean supports(AuthenticationToken token) {
231                 return supports.contains(token.getClass());
232         }
233
234         @Override
235         public String getName() {
236                 return AAF_REALM;
237         }
238
239 }