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