05b4d784dabe258832a726945b7a14f6268f9066
[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.security.Principal;
25 import java.util.ArrayList;
26 import java.util.HashSet;
27 import java.util.List;
28 import java.util.Map;
29 import java.util.Map.Entry;
30 import java.util.TreeMap;
31
32 import org.apache.shiro.authc.AuthenticationException;
33 import org.apache.shiro.authc.AuthenticationInfo;
34 import org.apache.shiro.authc.AuthenticationToken;
35 import org.apache.shiro.authc.UsernamePasswordToken;
36 import org.apache.shiro.realm.AuthorizingRealm;
37 import org.apache.shiro.subject.PrincipalCollection;
38 import org.onap.aaf.cadi.Access.Level;
39 import org.onap.aaf.cadi.CadiException;
40 import org.onap.aaf.cadi.LocatorException;
41 import org.onap.aaf.cadi.Permission;
42 import org.onap.aaf.cadi.PropAccess;
43 import org.onap.aaf.cadi.Symm;
44 import org.onap.aaf.cadi.aaf.v2_0.AAFAuthn;
45 import org.onap.aaf.cadi.aaf.v2_0.AAFCon;
46 import org.onap.aaf.cadi.aaf.v2_0.AAFLurPerm;
47 import org.onap.aaf.cadi.config.Config;
48 import org.onap.aaf.cadi.filter.MapBathConverter;
49 import org.onap.aaf.cadi.util.CSV;
50 import org.onap.aaf.misc.env.APIException;
51
52 public class AAFRealm extends AuthorizingRealm {
53         public static final String AAF_REALM = "AAFRealm";
54         
55         private PropAccess access;
56         private AAFCon<?> acon;
57         private AAFAuthn<?> authn;
58         private HashSet<Class<? extends AuthenticationToken>> supports;
59         private AAFLurPerm authz;
60         private MapBathConverter mbc;
61         private Map<String,String> idMap;
62         
63
64         /**
65          * 
66          * There appears to be no configuration objects or references available for CADI to start with.
67          *  
68          */
69         public AAFRealm () {
70                 access = new PropAccess(); // pick up cadi_prop_files from VM_Args
71                 mbc = null;
72                 idMap = null;
73                 String cadi_prop_files = access.getProperty(Config.CADI_PROP_FILES);
74                 if(cadi_prop_files==null) {
75                         String msg = Config.CADI_PROP_FILES + " in VM Args is required to initialize AAFRealm.";
76                         access.log(Level.INIT,msg);
77                         throw new RuntimeException(msg);
78                 } else {
79                         try {
80                                 acon = AAFCon.newInstance(access);
81                                 authn = acon.newAuthn();
82                                 authz = acon.newLur(authn);
83                                 
84                                 final String csv = access.getProperty(Config.CADI_BATH_CONVERT);
85                                 if(csv!=null) {
86                                         try {
87                                                 mbc = new MapBathConverter(access, new CSV(csv));
88                                                 access.printf(Level.INIT, "MapBathConversion enabled with file %s\n",csv);
89                                                 idMap = new TreeMap<String,String>();
90                                                 // Load 
91                                                 for(Entry<String, String> es : mbc.map().entrySet()) {
92                                                         String oldID = es.getKey();
93                                                         if(oldID.startsWith("Basic ")) {
94                                                                 oldID = Symm.base64noSplit.decode(oldID.substring(6));
95                                                                 int idx = oldID.indexOf(':');
96                                                                 if(idx>=0) {
97                                                                         oldID = oldID.substring(0, idx);
98                                                                 }
99                                                         }
100                                                         String newID = es.getValue();
101                                                         if(newID.startsWith("Basic ")) {
102                                                                 newID = Symm.base64noSplit.decode(newID.substring(6));
103                                                                 int idx = newID.indexOf(':');
104                                                                 if(idx>=0) {
105                                                                         newID = newID.substring(0, idx);
106                                                                 }
107                                                         }
108                                                         idMap.put(oldID,newID);
109                                                 }
110                                         } catch (IOException e) {
111                                                 access.log(e);
112                                         }
113                                 }
114                         } catch (APIException | CadiException | LocatorException e) {
115                                 String msg = "Cannot initiate AAFRealm";
116                                 access.log(Level.INIT,msg,e.getMessage());
117                                 throw new RuntimeException(msg,e);
118                         }
119                 }
120                 supports = new HashSet<Class<? extends AuthenticationToken>>();
121                 supports.add(UsernamePasswordToken.class);
122         }
123
124         @Override
125         protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
126                 access.log(Level.DEBUG, "AAFRealm.doGetAuthenticationInfo",token);
127                 
128                 final UsernamePasswordToken upt = (UsernamePasswordToken)token;
129                 final String user = upt.getUsername();
130                 String authUser = user; 
131                 final String password=new String(upt.getPassword());
132                 String authPassword = password;
133                 if(mbc!=null) {
134                         try {
135                                 final String oldBath = "Basic " + Symm.base64noSplit.encode(user+':'+password);
136                                 String bath = mbc.convert(access, oldBath);
137                                 if(bath!=oldBath) {
138                                         bath = Symm.base64noSplit.decode(bath.substring(6));
139                                         int colon = bath.indexOf(':');
140                                         if(colon>=0) {
141                                                 authUser = bath.substring(0, colon);
142                                                 authPassword = bath.substring(colon+1);
143                                         }
144                                 }
145                         } catch (IOException e) {
146                                 access.log(e);
147                         } 
148                 }
149                 String err;
150                 try {
151                         err = authn.validate(authUser,authPassword);
152                 } catch (IOException e) {
153                         err = "Credential cannot be validated";
154                         access.log(e, err);
155                 }
156                 
157                 if(err != null) {
158                         access.log(Level.DEBUG, err);
159                         throw new AuthenticationException(err);
160                 }
161
162             return new AAFAuthenticationInfo(
163                         access,
164                         user,
165                         password
166             );
167         }
168
169         @Override
170         protected void assertCredentialsMatch(AuthenticationToken atoken, AuthenticationInfo ai)throws AuthenticationException {
171                 if(ai instanceof AAFAuthenticationInfo) {
172                         if(!((AAFAuthenticationInfo)ai).matches(atoken)) {
173                                 throw new AuthenticationException("Credentials do not match");
174                         }
175                 } else {
176                         throw new AuthenticationException("AuthenticationInfo is not an AAFAuthenticationInfo");
177                 }
178         }
179
180
181         @Override
182         protected AAFAuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
183                 access.log(Level.DEBUG, "AAFRealm.doGetAuthenthorizationInfo");
184                 Principal bait = (Principal)principals.getPrimaryPrincipal();
185                 Principal newBait = bait;
186                 if(idMap!=null) {
187                         final String newID = idMap.get(bait.getName());
188                         if(newID!=null) {
189                                 newBait = new Principal() {
190                                         @Override
191                                         public String getName() {
192                                                 return newID;
193                                         }
194                                 };
195                         }
196                 }
197                 List<Permission> pond = new ArrayList<>();
198                 authz.fishAll(newBait,pond);
199                 
200                 return new AAFAuthorizationInfo(access,bait,pond);
201        
202         }
203
204         @Override
205         public boolean supports(AuthenticationToken token) {
206                 return supports.contains(token.getClass());
207         }
208
209         @Override
210         public String getName() {
211                 return AAF_REALM;
212         }
213
214 }