Refactor auth classes and add tests
[aai/babel.git] / src / test / java / org / onap / aai / babel / MicroServiceAuthTest.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 MicroServiceAuthTest {
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 authPolicyFile = "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 loading of a temporary file created with the specified roles.
112      *
113      * @throws AAIAuthException
114      *             if the test creates invalid Auth Policy roles
115      * @throws IOException
116      *             for I/O failures
117      * @throws JSONException
118      *             if this test creates an invalid JSON object
119      */
120     @Test
121     public void createLocalAuthFile() throws JSONException, AAIAuthException, IOException {
122         JSONObject roles = createRoleObject("role", createUserObject("user"), createFunctionObject("func"));
123         createAuthService(roles);
124         assertThat(AAIMicroServiceAuthCore.authorize("nosuchuser", "method:func"), is(false));
125         assertThat(AAIMicroServiceAuthCore.authorize("user", "method:func"), is(true));
126     }
127
128     /**
129      * Test re-loading of users by changing the contents of a temporary file.
130      *
131      * @throws JSONException
132      *             if this test creates an invalid JSON object
133      * @throws AAIAuthException
134      *             if the test creates invalid Auth Policy roles
135      * @throws IOException
136      *             for I/O failures
137      * @throws InterruptedException
138      *             if interrupted while sleeping
139      */
140     @Test
141     public void createLocalAuthFileOnChange()
142             throws JSONException, AAIAuthException, IOException, InterruptedException {
143         JSONObject roles = createRoleObject("role", createUserObject("user"), createFunctionObject("func"));
144         File file = createTempPolicyFile(roles);
145
146         BabelAuthConfig babelAuthConfig = new BabelAuthConfig();
147         babelAuthConfig.setAuthPolicyFile(file.getAbsolutePath());
148         new AAIMicroServiceAuth(babelAuthConfig);
149
150         // Make changes to the temp file
151         FileWriter fileWriter = new FileWriter(file);
152         fileWriter.write("");
153         fileWriter.flush();
154         fileWriter.close();
155
156         // Wait for the file to be reloaded
157         TimeUnit.SECONDS.sleep(3);
158
159         AAIMicroServiceAuthCore.cleanup();
160     }
161
162     /**
163      * Test that the default policy file is loaded when a non-existent file is passed to the authorisation class.
164      *
165      * @throws AAIAuthException
166      *             if the Auth Policy cannot be loaded
167      */
168     @Test
169     public void createAuthFromDefaultFile() throws AAIAuthException {
170         BabelAuthConfig babelServiceAuthConfig = new BabelAuthConfig();
171         babelServiceAuthConfig.setAuthPolicyFile("non-existent-file");
172         AAIMicroServiceAuth auth = new AAIMicroServiceAuth(babelServiceAuthConfig);
173         // The default policy will have been loaded
174         assertAdminUserAuthorisation(auth, VALID_ADMIN_USER);
175     }
176
177     /**
178      * Test that the default policy file is loaded when a non-existent file is passed to the authorisation class and
179      * CONFIG_HOME is not set.
180      *
181      * @throws AAIAuthException
182      *             if the Auth Policy cannot be loaded
183      */
184     @Test
185     public void createAuthFromDefaultFileAppHome() throws AAIAuthException {
186         System.clearProperty("CONFIG_HOME");
187         System.setProperty("APP_HOME", "src/test/resources");
188         BabelAuthConfig babelServiceAuthConfig = new BabelAuthConfig();
189         babelServiceAuthConfig.setAuthPolicyFile("non-existent-file");
190         new AAIMicroServiceAuth(babelServiceAuthConfig);
191         // The default policy will have been loaded from APP_HOME/appconfig
192     }
193
194     /**
195      * Test loading of the policy file relative to CONFIG_HOME.
196      *
197      * @throws AAIAuthException
198      *             if the Auth Policy cannot be loaded
199      */
200     @Test
201     public void createAuth() throws AAIAuthException {
202         AAIMicroServiceAuth auth = createStandardAuth();
203         assertAdminUserAuthorisation(auth, VALID_ADMIN_USER);
204     }
205
206     @Test
207     public void testAuthUser() throws AAIAuthException {
208         createStandardAuth();
209         assertThat(AAIMicroServiceAuthCore.authorize(VALID_ADMIN_USER, "GET:actions"), is(true));
210         assertThat(AAIMicroServiceAuthCore.authorize(VALID_ADMIN_USER, "WRONG:action"), is(false));
211     }
212
213     @Test
214     public void testValidateRequest() throws AAIAuthException {
215         AAIMicroServiceAuth auth = createStandardAuth();
216         assertThat(auth.validateRequest(null, new MockHttpServletRequest(), null, "app/v1/babel"), is(false));
217     }
218
219     private AAIMicroServiceAuth createStandardAuth() throws AAIAuthException {
220         BabelAuthConfig babelServiceAuthConfig = new BabelAuthConfig();
221         babelServiceAuthConfig.setAuthPolicyFile(authPolicyFile);
222         return new AAIMicroServiceAuth(babelServiceAuthConfig);
223     }
224
225     /**
226      * Create a test Auth policy JSON file and pass this to the Auth Service.
227      * 
228      * @param roles
229      *            the Auth policy JSON content
230      * @return a new Auth Service configured with the supplied roles
231      * @throws IOException
232      *             for I/O failures
233      * @throws AAIAuthException
234      *             if the auth policy file cannot be loaded
235      */
236     private AAIMicroServiceAuth createAuthService(JSONObject roles) throws AAIAuthException, IOException {
237         File file = createTempPolicyFile(roles);
238         BabelAuthConfig babelAuthConfig = new BabelAuthConfig();
239         babelAuthConfig.setAuthPolicyFile(file.getAbsolutePath());
240         return new AAIMicroServiceAuth(babelAuthConfig);
241     }
242
243     /**
244      * Create a temporary JSON file using the supplied roles.
245      * 
246      * @param roles
247      *            the roles to use to populate the new file
248      * @return the new temporary file
249      * @throws IOException
250      *             for I/O errors
251      */
252     private File createTempPolicyFile(JSONObject roles) throws IOException {
253         File file = File.createTempFile("auth-policy", "json");
254         file.deleteOnExit();
255         FileWriter fileWriter = new FileWriter(file);
256         fileWriter.write(roles.toString());
257         fileWriter.flush();
258         fileWriter.close();
259         return file;
260     }
261
262     /**
263      * Assert authorisation results for an admin user based on the test policy file.
264      *
265      * @param auth
266      *            the Auth Service to test
267      * @param adminUser
268      *            admin username
269      * @throws AAIAuthException
270      *             if the Auth Service is not initialized
271      */
272     private void assertAdminUserAuthorisation(AAIMicroServiceAuth auth, String adminUser) throws AAIAuthException {
273         assertThat(AAIMicroServiceAuthCore.authorize(adminUser, "GET:actions"), is(true));
274         assertThat(AAIMicroServiceAuthCore.authorize(adminUser, "POST:actions"), is(true));
275         assertThat(AAIMicroServiceAuthCore.authorize(adminUser, "PUT:actions"), is(true));
276         assertThat(AAIMicroServiceAuthCore.authorize(adminUser, "DELETE:actions"), is(true));
277     }
278
279     private JSONArray createFunctionObject(String functionName) throws JSONException {
280         JSONArray functionsArray = new JSONArray();
281         JSONObject func = new JSONObject();
282         func.put("name", functionName);
283         func.put("methods", createMethodObject("method"));
284         functionsArray.put(func);
285         return functionsArray;
286     }
287
288     private JSONArray createMethodObject(String methodName) throws JSONException {
289         JSONArray methodsArray = new JSONArray();
290         JSONObject method = new JSONObject();
291         method.put("name", methodName);
292         methodsArray.put(method);
293         return methodsArray;
294     }
295
296     private JSONArray createUserObject(String username) throws JSONException {
297         JSONArray usersArray = new JSONArray();
298         JSONObject user = new JSONObject();
299         user.put("username", username);
300         usersArray.put(user);
301         return usersArray;
302     }
303
304     private JSONObject createRoleObject(String roleName, JSONArray usersArray, JSONArray functionsArray)
305             throws JSONException {
306         JSONObject role = new JSONObject();
307         role.put("name", roleName);
308         role.put("functions", functionsArray);
309         role.put("users", usersArray);
310
311         JSONArray rolesArray = new JSONArray();
312         rolesArray.put(role);
313
314         JSONObject roles = new JSONObject();
315         roles.put("roles", rolesArray);
316         return roles;
317     }
318
319 }