Improved logging for VNF image extraction
[aai/babel.git] / src / main / java / org / onap / aai / auth / AAIMicroServiceAuthCore.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
6  * Copyright © 2017-2018 European Software Marketing Ltd.
7  * ================================================================================
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *       http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  * ============LICENSE_END=========================================================
20  */
21 package org.onap.aai.auth;
22
23 import com.fasterxml.jackson.core.JsonProcessingException;
24 import com.fasterxml.jackson.databind.JsonNode;
25 import com.fasterxml.jackson.databind.ObjectMapper;
26 import java.io.File;
27 import java.io.FileNotFoundException;
28 import java.io.IOException;
29 import java.util.ArrayList;
30 import java.util.Date;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Map.Entry;
35 import java.util.Timer;
36 import java.util.TimerTask;
37 import java.util.concurrent.TimeUnit;
38 import org.onap.aai.babel.logging.ApplicationMsgs;
39 import org.onap.aai.babel.logging.LogHelper;
40
41 /** Authentication and authorization by user and role. */
42 public class AAIMicroServiceAuthCore {
43
44     private static LogHelper applicationLogger = LogHelper.INSTANCE;
45
46     private static final String CONFIG_HOME = System.getProperty("CONFIG_HOME");
47
48     public static final String FILESEP =
49             (System.getProperty("file.separator") == null) ? "/" : System.getProperty("file.separator");
50     public static final String APPCONFIG_DIR =
51             (CONFIG_HOME == null) ? System.getProperty("APP_HOME") + FILESEP + "appconfig" : CONFIG_HOME;
52
53     private static String appConfigAuthDir = APPCONFIG_DIR + FILESEP + "auth";
54     private static String defaultAuthFileName = appConfigAuthDir + FILESEP + "auth_policy.json";
55
56     private static boolean usersInitialized = false;
57     private static HashMap<String, AAIAuthUser> users;
58     private static boolean timerSet = false;
59     private static Timer timer = null;
60     private static String policyAuthFileName;
61
62     public enum HTTP_METHODS {
63         GET,
64         PUT,
65         DELETE,
66         HEAD,
67         POST
68     }
69
70     // Don't instantiate
71     private AAIMicroServiceAuthCore() {}
72
73     public static String getDefaultAuthFileName() {
74         return defaultAuthFileName;
75     }
76
77     public static void setDefaultAuthFileName(String defaultAuthFileName) {
78         AAIMicroServiceAuthCore.defaultAuthFileName = defaultAuthFileName;
79     }
80
81     public static synchronized void init(String authPolicyFile) throws AAIAuthException {
82         try {
83             policyAuthFileName = AAIMicroServiceAuthCore.getConfigFile(authPolicyFile);
84         } catch (IOException e) {
85             applicationLogger.debug("Exception while retrieving policy file.");
86             applicationLogger.error(ApplicationMsgs.PROCESS_REQUEST_ERROR, e);
87             throw new AAIAuthException(e.getMessage());
88         }
89         if (policyAuthFileName == null) {
90             throw new AAIAuthException("Auth policy file could not be found" + CONFIG_HOME + APPCONFIG_DIR);
91         }
92         AAIMicroServiceAuthCore.reloadUsers();
93
94         TimerTask task = new FileWatcher(new File(policyAuthFileName)) {
95             @Override
96             protected void onChange(File file) {
97                 // here we implement the onChange
98                 applicationLogger.debug("File " + file.getName() + " has been changed!");
99                 try {
100                     AAIMicroServiceAuthCore.reloadUsers();
101                 } catch (AAIAuthException e) {
102                     applicationLogger.error(ApplicationMsgs.PROCESS_REQUEST_ERROR, e);
103                 }
104                 applicationLogger.debug("File " + file.getName() + " has been reloaded!");
105             }
106         };
107
108         if (!timerSet) {
109             timerSet = true;
110             timer = new Timer();
111             long period = TimeUnit.SECONDS.toMillis(1);
112             timer.schedule(task, new Date(), period);
113             applicationLogger.debug("Config Watcher Interval = " + period);
114         }
115     }
116
117     public static void cleanup() {
118         timer.cancel();
119     }
120
121     public static String getConfigFile(String authPolicyFile) throws IOException {
122         File authFile = new File(authPolicyFile);
123         if (authFile.exists()) {
124             return authFile.getCanonicalPath();
125         }
126         authFile = new File(appConfigAuthDir + FILESEP + authPolicyFile);
127         if (authFile.exists()) {
128             return authFile.getCanonicalPath();
129         }
130         if (defaultAuthFileName != null) {
131             authFile = new File(defaultAuthFileName);
132             if (authFile.exists()) {
133                 return defaultAuthFileName;
134             }
135         }
136         return null;
137     }
138
139     public static synchronized void reloadUsers() throws AAIAuthException {
140         users = new HashMap<>();
141
142         ObjectMapper mapper = new ObjectMapper();
143         try {
144             applicationLogger.debug("Reading from " + policyAuthFileName);
145             JsonNode rootNode = mapper.readTree(new File(policyAuthFileName));
146             for (JsonNode roleNode : rootNode.path("roles")) {
147                 String roleName = roleNode.path("name").asText();
148                 AAIAuthRole r = new AAIAuthRole();
149                 installFunctionOnRole(roleNode.path("functions"), roleName, r);
150                 assignRoleToUsers(roleNode.path("users"), roleName, r);
151             }
152         } catch (FileNotFoundException e) {
153             throw new AAIAuthException("Auth policy file could not be found", e);
154         } catch (JsonProcessingException e) {
155             throw new AAIAuthException("Error processing Auth policy file ", e);
156         } catch (IOException e) {
157             throw new AAIAuthException("Error reading Auth policy file", e);
158         }
159
160         usersInitialized = true;
161     }
162
163     private static void installFunctionOnRole(JsonNode functionsNode, String roleName, AAIAuthRole r) {
164         for (JsonNode functionNode : functionsNode) {
165             String function = functionNode.path("name").asText();
166             JsonNode methodsNode = functionNode.path("methods");
167             boolean hasMethods = false;
168             for (JsonNode method_node : methodsNode) {
169                 String methodName = method_node.path("name").asText();
170                 hasMethods = true;
171                 String func = methodName + ":" + function;
172                 applicationLogger.debug("Installing function " + func + " on role " + roleName);
173                 r.addAllowedFunction(func);
174             }
175
176             if (!hasMethods) {
177                 for (HTTP_METHODS meth : HTTP_METHODS.values()) {
178                     String func = meth.toString() + ":" + function;
179                     applicationLogger.debug("Installing (all methods) " + func + " on role " + roleName);
180                     r.addAllowedFunction(func);
181                 }
182             }
183         }
184     }
185
186     private static void assignRoleToUsers(JsonNode usersNode, String roleName, AAIAuthRole r) {
187         for (JsonNode userNode : usersNode) {
188             String name = userNode.path("username").asText().toLowerCase();
189             AAIAuthUser user;
190             if (users.containsKey(name)) {
191                 user = users.get(name);
192             } else {
193                 user = new AAIAuthUser();
194             }
195             applicationLogger.debug("Assigning " + roleName + " to user " + name);
196             user.setUser(name);
197             user.addRole(roleName, r);
198             users.put(name, user);
199         }
200     }
201
202     public static class AAIAuthUser {
203         private String username;
204         private HashMap<String, AAIAuthRole> roles;
205
206         public AAIAuthUser() {
207             this.roles = new HashMap<>();
208         }
209
210         public String getUser() {
211             return this.username;
212         }
213
214         public Map<String, AAIAuthRole> getRoles() {
215             return this.roles;
216         }
217
218         public void addRole(String roleName, AAIAuthRole r) {
219             this.roles.put(roleName, r);
220         }
221
222         public boolean checkAllowed(String checkFunc) {
223             for (Entry<String, AAIAuthRole> role_entry : roles.entrySet()) {
224                 AAIAuthRole role = role_entry.getValue();
225                 if (role.hasAllowedFunction(checkFunc)) {
226                     return true;
227                 }
228             }
229             return false;
230         }
231
232         public void setUser(String myuser) {
233             this.username = myuser;
234         }
235     }
236
237     public static class AAIAuthRole {
238
239         private List<String> allowedFunctions;
240
241         public AAIAuthRole() {
242             this.allowedFunctions = new ArrayList<>();
243         }
244
245         public void addAllowedFunction(String func) {
246             this.allowedFunctions.add(func);
247         }
248
249         public void delAllowedFunction(String delFunc) {
250             if (this.allowedFunctions.contains(delFunc)) {
251                 this.allowedFunctions.remove(delFunc);
252             }
253         }
254
255         public boolean hasAllowedFunction(String afunc) {
256             return this.allowedFunctions.contains(afunc);
257         }
258     }
259
260     public static boolean authorize(String username, String authFunction) throws AAIAuthException {
261         if (!usersInitialized || users == null) {
262             throw new AAIAuthException("Auth module not initialized");
263         }
264         if (users.containsKey(username)) {
265             if (users.get(username).checkAllowed(authFunction)) {
266                 logAuthenticationResult(username, authFunction, "AUTH ACCEPTED");
267                 return true;
268             } else {
269                 logAuthenticationResult(username, authFunction, "AUTH FAILED");
270                 return false;
271             }
272         } else {
273             logAuthenticationResult(username, authFunction, "User not found");
274             return false;
275         }
276     }
277
278     private static void logAuthenticationResult(String username, String authFunction, String result) {
279         applicationLogger.debug(result + ": " + username + " on function " + authFunction);
280     }
281 }