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