Update aai-parent in babel to 1.13.3
[aai/babel.git] / src / test / java / org / onap / aai / babel / TestMicroServiceAuth.java
1 /**
2  * ============LICENSE_START=======================================================
3  * org.onap.aai
4  * ================================================================================
5  * Copyright (c) 2017-2019 AT&T Intellectual Property. All rights reserved.
6  * Copyright (c) 2017-2019 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
22 package org.onap.aai.babel;
23
24 import static org.hamcrest.CoreMatchers.is;
25 import static org.hamcrest.MatcherAssert.assertThat;
26 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
27 import static org.junit.jupiter.api.Assertions.assertThrows;
28 import static org.junit.jupiter.api.Assertions.assertTrue;
29
30 import java.io.File;
31 import java.io.FileWriter;
32 import java.io.IOException;
33 import java.util.concurrent.TimeUnit;
34 import org.json.JSONArray;
35 import org.json.JSONException;
36 import org.json.JSONObject;
37 import org.junit.jupiter.api.Assertions;
38 import org.junit.jupiter.api.BeforeEach;
39 import org.junit.jupiter.api.Test;
40 import org.onap.aai.auth.AAIAuthException;
41 import org.onap.aai.auth.AAIMicroServiceAuth;
42 import org.onap.aai.auth.AAIMicroServiceAuthCore;
43 import org.onap.aai.babel.config.BabelAuthConfig;
44 import org.springframework.mock.web.MockHttpServletRequest;
45
46 /**
47  * Tests {@link AAIMicroServiceAuth}.
48  */
49
50 public class TestMicroServiceAuth {
51
52     private static final String VALID_ADMIN_USER = "cn=common-name, ou=org-unit, o=org, l=location, st=state, c=us";
53     private static final String TEST_POLICY_FILE = "auth_policy.json";
54
55     @BeforeEach
56     public void setup() {
57         System.setProperty("CONFIG_HOME", "src/test/resources");
58     }
59
60     /**
61      * Test authorization of a request when authentication is disabled.
62      *
63      * @throws AAIAuthException
64      *             if the test creates invalid Auth Policy roles
65      */
66     @Test
67     public void testAuthenticationDisabled() throws AAIAuthException {
68         BabelAuthConfig babelAuthConfig = new BabelAuthConfig();
69         babelAuthConfig.setAuthenticationDisable(true);
70         AAIMicroServiceAuth auth = new AAIMicroServiceAuth(babelAuthConfig);
71         assertThat(auth.validateRequest(null, new MockHttpServletRequest(), null, "any/uri"), is(true));
72     }
73
74     /**
75      * Temporarily invalidate the default policy file and then try to initialize the authorization class using the name
76      * of a policy file that does not exist.
77      *
78      * @throws AAIAuthException
79      *             if the Auth policy file cannot be loaded
80      */
81     @Test
82     public void missingPolicyFile() throws AAIAuthException {
83         assertThrows(AAIAuthException.class, () -> {
84             String defaultFile = AAIMicroServiceAuthCore.getDefaultAuthFileName();
85             try {
86                 AAIMicroServiceAuthCore.setDefaultAuthFileName("invalid.default.file");
87                 BabelAuthConfig babelServiceAuthConfig = new BabelAuthConfig();
88                 babelServiceAuthConfig.setAuthPolicyFile("invalid.file.name");
89                 new AAIMicroServiceAuth(babelServiceAuthConfig);
90             } finally {
91                 AAIMicroServiceAuthCore.setDefaultAuthFileName(defaultFile);
92             }
93         });
94     }
95
96     /**
97      * Temporarily invalidate the default policy file and then try to initialize the authorization class using a null
98      * policy file name.
99      *
100      * @throws AAIAuthException
101      *             if the Auth policy file cannot be loaded
102      */
103     @Test
104     public void testNullPolicyFile() throws AAIAuthException {
105         assertThrows(AAIAuthException.class, () -> {
106             String defaultFile = AAIMicroServiceAuthCore.getDefaultAuthFileName();
107             try {
108                 AAIMicroServiceAuthCore.setDefaultAuthFileName("invalid.default.file");
109                 BabelAuthConfig babelServiceAuthConfig = new BabelAuthConfig();
110                 babelServiceAuthConfig.setAuthPolicyFile(null);
111                 new AAIMicroServiceAuth(babelServiceAuthConfig);
112             } finally {
113                 AAIMicroServiceAuthCore.setDefaultAuthFileName(defaultFile);
114             }
115         });
116     }
117
118     /**
119      * Test reloading of the auth policy file after this file has been deleted.
120      *
121      * @throws AAIAuthException
122      *             if the test creates invalid Auth Policy roles
123      * @throws JSONException
124      *             if this test creates an invalid JSON object
125      * @throws IOException
126      *             for I/O failures, e.g. when creating the temporary auth policy file
127      */
128     @Test
129     public void testReloadDeletedFile() throws AAIAuthException, JSONException, IOException {
130         File file = createTestPolicyFile();
131         AAIMicroServiceAuthCore.init(file.getAbsolutePath());
132         assertThat(file.delete(), is(true));
133         try {
134             AAIMicroServiceAuthCore.reloadUsers();
135             Assertions.fail("Expected an AAIAuthException to be thrown");
136         } catch (AAIAuthException e) {
137             assertTrue(true);
138         }
139     }
140
141     /**
142      * Test reloading of the auth policy file after this file has been made invalid.
143      *
144      * @throws AAIAuthException
145      *             if the test creates invalid Auth Policy roles
146      * @throws JSONException
147      *             if this test creates an invalid JSON object
148      * @throws IOException
149      *             for I/O failures, e.g. when creating the temporary auth policy file
150      */
151     @Test
152     public void testReloadInvalidFile() throws AAIAuthException, JSONException, IOException {
153         assertThrows(AAIAuthException.class, () -> {
154             File file = createTestPolicyFile();
155             AAIMicroServiceAuthCore.init(file.getAbsolutePath());
156             writeToFile(file, "not valid JSON content");
157             AAIMicroServiceAuthCore.reloadUsers();
158         });
159     }
160
161     /**
162      * Test loading of a temporary file created with the specified roles.
163      *
164      * @throws AAIAuthException
165      *             if the test creates invalid Auth Policy roles
166      * @throws IOException
167      *             for I/O failures
168      * @throws JSONException
169      *             if this test creates an invalid JSON object
170      */
171     @Test
172     public void createLocalAuthFile() throws JSONException, AAIAuthException, IOException {
173         createAuthService();
174         assertThat(AAIMicroServiceAuthCore.authorize("nosuchuser", "method:func"), is(false));
175         assertThat(AAIMicroServiceAuthCore.authorize("user", "method:func"), is(true));
176     }
177
178     /**
179      * Test re-loading of users by changing the contents of a temporary file.
180      *
181      * @throws JSONException
182      *             if this test creates an invalid JSON object
183      * @throws AAIAuthException
184      *             if the test creates invalid Auth Policy roles
185      * @throws IOException
186      *             for I/O failures
187      * @throws InterruptedException
188      *             if interrupted while sleeping
189      */
190     @Test
191     public void createLocalAuthFileOnChange()
192             throws JSONException, AAIAuthException, IOException, InterruptedException {
193         assertDoesNotThrow(() -> {
194             File file = createTestPolicyFile();
195
196             BabelAuthConfig babelAuthConfig = new BabelAuthConfig();
197             babelAuthConfig.setAuthPolicyFile(file.getAbsolutePath());
198             new AAIMicroServiceAuth(babelAuthConfig);
199
200             // Make changes to the temp file
201             writeToFile(file, "");
202
203             // Wait for the file to be reloaded
204             TimeUnit.SECONDS.sleep(3);
205
206             AAIMicroServiceAuthCore.cleanup();
207         });
208     }
209
210     /**
211      * Test that the default policy file is loaded when a non-existent file is passed to the authorization class.
212      *
213      * @throws AAIAuthException
214      *             if the Auth Policy cannot be loaded
215      */
216     @Test
217     public void createAuthFromDefaultFile() throws AAIAuthException {
218         BabelAuthConfig babelServiceAuthConfig = new BabelAuthConfig();
219         babelServiceAuthConfig.setAuthPolicyFile("non-existent-file");
220         AAIMicroServiceAuth auth = new AAIMicroServiceAuth(babelServiceAuthConfig);
221         // The default policy will have been loaded
222         assertAdminUserAuthorisation(auth, VALID_ADMIN_USER);
223     }
224
225     /**
226      * Test that the default policy file is loaded when a non-existent file is passed to the authorisation class and
227      * CONFIG_HOME is not set.
228      *
229      * @throws AAIAuthException
230      *             if the Auth Policy cannot be loaded
231      */
232     @Test
233     public void createAuthFromDefaultFileAppHome() throws AAIAuthException {
234         assertDoesNotThrow(() -> {
235             System.clearProperty("CONFIG_HOME");
236             System.setProperty("APP_HOME", "src/test/resources");
237             BabelAuthConfig babelServiceAuthConfig = new BabelAuthConfig();
238             babelServiceAuthConfig.setAuthPolicyFile("non-existent-file");
239             new AAIMicroServiceAuth(babelServiceAuthConfig);
240             // The default policy will have been loaded from APP_HOME/appconfig
241         });
242         // The default policy will have been loaded from APP_HOME/appconfig
243     }
244
245     /**
246      * Test loading of the policy file relative to CONFIG_HOME.
247      *
248      * @throws AAIAuthException
249      *             if the Auth Policy cannot be loaded
250      */
251     @Test
252     public void createAuth() throws AAIAuthException {
253         AAIMicroServiceAuth auth = createStandardAuth();
254         assertAdminUserAuthorisation(auth, VALID_ADMIN_USER);
255     }
256
257     @Test
258     public void testAuthUser() throws AAIAuthException {
259         createStandardAuth();
260         assertThat(AAIMicroServiceAuthCore.authorize(VALID_ADMIN_USER, "GET:actions"), is(true));
261         assertThat(AAIMicroServiceAuthCore.authorize(VALID_ADMIN_USER, "WRONG:action"), is(false));
262     }
263
264     @Test
265     public void testValidateRequest() throws AAIAuthException {
266         AAIMicroServiceAuth auth = createStandardAuth();
267         assertThat(auth.validateRequest(null, new MockHttpServletRequest(), null, "app/v1/babel"), is(false));
268     }
269
270     private AAIMicroServiceAuth createStandardAuth() throws AAIAuthException {
271         BabelAuthConfig babelServiceAuthConfig = new BabelAuthConfig();
272         babelServiceAuthConfig.setAuthPolicyFile(TEST_POLICY_FILE);
273         return new AAIMicroServiceAuth(babelServiceAuthConfig);
274     }
275
276
277     /**
278      * Create a temporary JSON file using some valid test roles.
279      *
280      * @return the new temporary file
281      * @throws IOException
282      *             for I/O errors
283      */
284     private File createTestPolicyFile() throws JSONException, IOException {
285         return createTempPolicyFile(createRoleObject("role", createUserObject("user"), createFunctionObject("func")));
286     }
287
288     /**
289      * Create a test Auth policy JSON file and pass this to the Auth Service.
290      *
291      * @param roles
292      *            the Auth policy JSON content
293      * @return a new Auth Service configured with the supplied roles
294      * @throws IOException
295      *             for I/O failures
296      * @throws AAIAuthException
297      *             if the auth policy file cannot be loaded
298      * @throws JSONException
299      *             if this test creates an invalid JSON object
300      */
301     private AAIMicroServiceAuth createAuthService() throws AAIAuthException, IOException, JSONException {
302         File file = createTestPolicyFile();
303         BabelAuthConfig babelAuthConfig = new BabelAuthConfig();
304         babelAuthConfig.setAuthPolicyFile(file.getAbsolutePath());
305         return new AAIMicroServiceAuth(babelAuthConfig);
306     }
307
308     /**
309      * Create a temporary JSON file using the supplied roles.
310      *
311      * @param roles
312      *            the roles to use to populate the new file
313      * @return the new temporary file
314      * @throws IOException
315      *             for I/O errors
316      */
317     private File createTempPolicyFile(JSONObject roles) throws IOException {
318         File file = File.createTempFile("auth-policy", "json");
319         file.deleteOnExit();
320         writeToFile(file, roles.toString());
321         return file;
322     }
323
324     /**
325      * Write String content to a file, flush and close.
326      *
327      * @param file
328      *            the file to write to
329      * @param text
330      *            the String content to write to the file
331      * @throws IOException
332      *             if the file cannot be opened for writing, or an I/O error occurs
333      */
334     private void writeToFile(File file, String text) throws IOException {
335         FileWriter fileWriter = new FileWriter(file);
336         fileWriter.write(text);
337         fileWriter.flush();
338         fileWriter.close();
339     }
340
341     /**
342      * Assert authorization results for an admin user based on the test policy file.
343      *
344      * @param auth
345      *            the Auth Service to test
346      * @param adminUser
347      *            admin username
348      * @throws AAIAuthException
349      *             if the Auth Service is not initialized
350      */
351     private void assertAdminUserAuthorisation(AAIMicroServiceAuth auth, String adminUser) throws AAIAuthException {
352         assertThat(AAIMicroServiceAuthCore.authorize(adminUser, "GET:actions"), is(true));
353         assertThat(AAIMicroServiceAuthCore.authorize(adminUser, "POST:actions"), is(true));
354         assertThat(AAIMicroServiceAuthCore.authorize(adminUser, "PUT:actions"), is(true));
355         assertThat(AAIMicroServiceAuthCore.authorize(adminUser, "DELETE:actions"), is(true));
356     }
357
358     private JSONArray createFunctionObject(String functionName) throws JSONException {
359         JSONArray functionsArray = new JSONArray();
360         JSONObject func = new JSONObject();
361         func.put("name", functionName);
362         func.put("methods", createMethodObject("method"));
363         functionsArray.put(func);
364         return functionsArray;
365     }
366
367     private JSONArray createMethodObject(String methodName) throws JSONException {
368         JSONArray methodsArray = new JSONArray();
369         JSONObject method = new JSONObject();
370         method.put("name", methodName);
371         methodsArray.put(method);
372         return methodsArray;
373     }
374
375     private JSONArray createUserObject(String username) throws JSONException {
376         JSONArray usersArray = new JSONArray();
377         JSONObject user = new JSONObject();
378         user.put("username", username);
379         usersArray.put(user);
380         return usersArray;
381     }
382
383     private JSONObject createRoleObject(String roleName, JSONArray usersArray, JSONArray functionsArray)
384             throws JSONException {
385         JSONObject role = new JSONObject();
386         role.put("name", roleName);
387         role.put("functions", functionsArray);
388         role.put("users", usersArray);
389
390         JSONArray rolesArray = new JSONArray();
391         rolesArray.put(role);
392
393         JSONObject roles = new JSONObject();
394         roles.put("roles", rolesArray);
395         return roles;
396     }
397
398 }