0f9adb94d6cdc2c4e1d797f1f831daaae37905b4
[aaf/authz.git] / cadi / core / src / main / java / org / onap / aaf / cadi / lur / LocalLur.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
22 package org.onap.aaf.cadi.lur;
23
24 import java.io.IOException;
25 import java.security.Principal;
26 import java.util.List;
27 import java.util.Map;
28 import java.util.Set;
29 import java.util.TreeSet;
30
31 import org.onap.aaf.cadi.AbsUserCache;
32 import org.onap.aaf.cadi.Access;
33 import org.onap.aaf.cadi.CredVal;
34 import org.onap.aaf.cadi.Hash;
35 import org.onap.aaf.cadi.Lur;
36 import org.onap.aaf.cadi.Permission;
37 import org.onap.aaf.cadi.User;
38 import org.onap.aaf.cadi.Access.Level;
39 import org.onap.aaf.cadi.config.Config;
40
41 /**
42  * An in-memory Lur that can be configured locally with User info via properties, similar to Tomcat-users.xml mechanisms.
43  *
44  * @author Jonathan
45  *
46  */
47 public final class LocalLur extends AbsUserCache<LocalPermission> implements Lur, CredVal {
48         public static final String SEMI = "\\s*;\\s*";
49         public static final String COLON = "\\s*:\\s*";
50         public static final String COMMA = "\\s*,\\s*";
51         public static final String PERCENT = "\\s*%\\s*";
52
53         // Use to quickly determine whether any given group is supported by this LUR
54         private final Set<String> supportingGroups;
55         private String supportedRealm;
56
57         /**
58          * Construct by building structure, see "build"
59          *
60          * Reconstruct with "build"
61          *
62          * @param userProperties
63          * @param groupProperties
64          * @param decryptor
65          * @throws IOException
66          */
67         public LocalLur(Access access, String userProperties, String groupProperties) throws IOException {
68                 super(access, 0, 0, Integer.MAX_VALUE);  // data doesn't expire
69                 supportedRealm = access.getProperty(Config.BASIC_REALM, "localized");
70                 supportingGroups = new TreeSet<>();
71
72                 if (userProperties != null) {
73                         parseUserProperties(userProperties);
74                 }
75
76                 if (groupProperties != null) {
77                         parseGroupProperties(groupProperties);
78                 }
79         }
80
81         public boolean validate(String user, CredVal.Type type, byte[] cred, Object state) {
82                 if (cred == null) {
83                         return false;
84                 }
85                 User<LocalPermission> usr = getUser(user, cred);
86                 if (usr == null) {
87                         return false;
88                 }
89                 // covers null as well as bad pass
90                 if ((type == Type.PASSWORD) && (usr.principal instanceof ConfigPrincipal)) {;
91                         return Hash.isEqual(cred, ((ConfigPrincipal)usr.principal).getCred());
92                 }
93                 return false;
94         }
95
96         //      @Override
97         public boolean fish(Principal bait, Permission pond) {
98                 if (pond == null) {
99                         return false;
100                 }
101                 if (handles(bait) && pond instanceof LocalPermission) { // local Users only have LocalPermissions
102                         User<LocalPermission> user = getUser(bait);
103                         if (user != null) {
104                                 return user.contains((LocalPermission)pond);
105                         }
106                 }
107                 return false;
108         }
109
110         // We do not want to expose the actual Group, so make a copy.
111         public void fishAll(Principal bait, List<Permission> perms) {
112                 if (handles(bait)) {
113                         User<LocalPermission> user = getUser(bait);
114                         if (user != null) {
115                                 user.copyPermsTo(perms);
116                         }
117                 }
118         }
119
120         /* (non-Javadoc)
121          * @see org.onap.aaf.cadi.Lur#handles(java.security.Principal)
122          */
123         @Override
124         public boolean handles(Principal principal) {
125                 if (principal == null) {
126                         return false;
127                 }
128                 return principal.getName().endsWith(supportedRealm);
129         }
130
131         public boolean handlesExclusively(Permission pond) {
132                 return supportingGroups.contains(pond.getKey());
133         }
134
135         /* (non-Javadoc)
136          * @see org.onap.aaf.cadi.Lur#createPerm(java.lang.String)
137          */
138         @Override
139         public Permission createPerm(String p) {
140                 return new LocalPermission(p);
141         }
142         
143         private void parseUserProperties(String userProperties) throws IOException {
144                 // For each User name...
145                 for (String userProperty : userProperties.trim().split(SEMI)) {
146                         String[] userInfo = userProperty.split(COLON, 2);
147                         String[] userPass = userInfo[0].split(PERCENT, 2);
148                         String userName = userPass[0];
149
150                         byte[] password = null;
151                         if (userPass.length > 1) {
152                                 password = access.decrypt(userPass[1], true).getBytes();
153                                 if (userName.indexOf('@') < 0) {
154                                         userName += '@' + access.getProperty(Config.AAF_DEFAULT_REALM, Config.getDefaultRealm());
155                                 }
156                         }
157                         User<LocalPermission> usr;
158                         usr = new User<>(new ConfigPrincipal(userName, password));
159                         addUser(usr);
160                         access.log(Level.INIT, "Local User:", usr.principal);
161
162                         if (userInfo.length > 1) {
163                                 Map<String, Permission> newMap = usr.newMap();
164                                 for (String group : userInfo[1].split(COMMA)) {
165                                         supportingGroups.add(group);
166                                         usr.add(newMap, new LocalPermission(group));
167                                 }
168                                 usr.setMap(newMap);
169                         }
170                 }
171         }
172
173         
174         private void parseGroupProperties(String groupProperties) throws IOException {
175                 // For each Group name...
176                 for (String group : groupProperties.trim().split(SEMI)) {
177                         String[] groups = group.split(COLON, 2);
178                         if (groups.length <= 1) {
179                                 continue;
180                         }
181                         supportingGroups.add(groups[0]);
182                         LocalPermission p = new LocalPermission(groups[0]);
183
184                         // Add all users (known by comma separators)
185                         for (String groupMember : groups[1].split(COMMA)) {
186                                 // look for password, if so, put in passMap
187                                 String[] userPass = groupMember.split(PERCENT, 2);
188                                 String userName = userPass[0];
189                                 if (userName.indexOf('@') < 0) {
190                                         userName += '@' + access.getProperty(Config.AAF_DEFAULT_REALM, Config.getDefaultRealm());
191                                 }
192
193                                 User<LocalPermission> usr = null;
194                                 byte[] password = null;
195                                 if (userPass.length > 1) {
196                                         password = access.decrypt(userPass[1], true).getBytes();
197                                 }
198                                 usr = getUser(userName, password);
199                                 if (usr == null) {
200                                         usr = new User<>(new ConfigPrincipal(userName, password));
201                                         addUser(usr);
202                                 }
203                                 else {
204                                         usr.principal = new ConfigPrincipal(userName, password);
205                                 }
206                                 usr.add(p);
207                                 access.log(Level.INIT, "Local User:", usr.principal);
208                         }
209                 }
210         }
211
212 }