Configuration and Auto-Certificates
[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                 for(Permission p : pond) {
102                         if (handles(bait) && p instanceof LocalPermission) { // local Users only have LocalPermissions
103                                 User<LocalPermission> user = getUser(bait);
104                                 if (user != null) {
105                                         return user.contains((LocalPermission)p);
106                                 }
107                         }
108                 }
109                 return false;
110         }
111
112         // We do not want to expose the actual Group, so make a copy.
113         public void fishAll(Principal bait, List<Permission> perms) {
114                 if (handles(bait)) {
115                         User<LocalPermission> user = getUser(bait);
116                         if (user != null) {
117                                 user.copyPermsTo(perms);
118                         }
119                 }
120         }
121
122         /* (non-Javadoc)
123          * @see org.onap.aaf.cadi.Lur#handles(java.security.Principal)
124          */
125         @Override
126         public boolean handles(Principal principal) {
127                 if (principal == null) {
128                         return false;
129                 }
130                 return principal.getName().endsWith(supportedRealm);
131         }
132
133         @Override
134         public boolean handlesExclusively(Permission ... pond) {
135                 boolean rv = false;
136                 for (Permission p : pond) {
137                         if(rv=supportingGroups.contains(p.getKey())) {
138                                 break;
139                         }
140                 }
141                 return rv;
142         }
143
144         /* (non-Javadoc)
145          * @see org.onap.aaf.cadi.Lur#createPerm(java.lang.String)
146          */
147         @Override
148         public Permission createPerm(String p) {
149                 return new LocalPermission(p);
150         }
151         
152         private void parseUserProperties(String userProperties) throws IOException {
153                 // For each User name...
154                 for (String userProperty : userProperties.trim().split(SEMI)) {
155                         String[] userInfo = userProperty.split(COLON, 2);
156                         String[] userPass = userInfo[0].split(PERCENT, 2);
157                         String userName = userPass[0];
158
159                         byte[] password = null;
160                         if (userPass.length > 1) {
161                                 password = access.decrypt(userPass[1], true).getBytes();
162                                 if (userName.indexOf('@') < 0) {
163                                         userName += '@' + access.getProperty(Config.AAF_DEFAULT_REALM, Config.getDefaultRealm());
164                                 }
165                         }
166                         User<LocalPermission> usr;
167                         usr = new User<>(new ConfigPrincipal(userName, password));
168                         addUser(usr);
169                         access.log(Level.INIT, "Local User:", usr.principal);
170
171                         if (userInfo.length > 1) {
172                                 Map<String, Permission> newMap = usr.newMap();
173                                 for (String group : userInfo[1].split(COMMA)) {
174                                         supportingGroups.add(group);
175                                         usr.add(newMap, new LocalPermission(group));
176                                 }
177                                 usr.setMap(newMap);
178                         }
179                 }
180         }
181
182         
183         private void parseGroupProperties(String groupProperties) throws IOException {
184                 // For each Group name...
185                 for (String group : groupProperties.trim().split(SEMI)) {
186                         String[] groups = group.split(COLON, 2);
187                         if (groups.length <= 1) {
188                                 continue;
189                         }
190                         supportingGroups.add(groups[0]);
191                         LocalPermission p = new LocalPermission(groups[0]);
192
193                         // Add all users (known by comma separators)
194                         for (String groupMember : groups[1].split(COMMA)) {
195                                 // look for password, if so, put in passMap
196                                 String[] userPass = groupMember.split(PERCENT, 2);
197                                 String userName = userPass[0];
198                                 if (userName.indexOf('@') < 0) {
199                                         userName += '@' + access.getProperty(Config.AAF_DEFAULT_REALM, Config.getDefaultRealm());
200                                 }
201
202                                 User<LocalPermission> usr = null;
203                                 byte[] password = null;
204                                 if (userPass.length > 1) {
205                                         password = access.decrypt(userPass[1], true).getBytes();
206                                 }
207                                 usr = getUser(userName, password);
208                                 if (usr == null) {
209                                         usr = new User<>(new ConfigPrincipal(userName, password));
210                                         addUser(usr);
211                                 }
212                                 else {
213                                         usr.principal = new ConfigPrincipal(userName, password);
214                                 }
215                                 usr.add(p);
216                                 access.log(Level.INIT, "Local User:", usr.principal);
217                         }
218                 }
219         }
220
221 }