Refactor auth classes and add tests
Add new tests to give better coverage of the authorization classes.
Refactor the core class for readability.
Change-Id: I2be467d8f4492249a0c29be8b108bb2bce2818dd
Issue-ID: AAI-2229
Signed-off-by: mark.j.leonard <mark.j.leonard@gmail.com>
diff --git a/src/main/java/org/onap/aai/auth/AAIMicroServiceAuthCore.java b/src/main/java/org/onap/aai/auth/AAIMicroServiceAuthCore.java
index ddbc002..0eec7e1 100644
--- a/src/main/java/org/onap/aai/auth/AAIMicroServiceAuthCore.java
+++ b/src/main/java/org/onap/aai/auth/AAIMicroServiceAuthCore.java
@@ -2,8 +2,8 @@
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
- * Copyright © 2017-2019 AT&T Intellectual Property. All rights reserved.
- * Copyright © 2017-2019 European Software Marketing Ltd.
+ * Copyright (c) 2017-2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (c) 2017-2019 European Software Marketing Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -27,12 +27,14 @@
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import java.util.Map.Entry;
+import java.util.Optional;
import java.util.Timer;
import java.util.TimerTask;
import java.util.concurrent.TimeUnit;
@@ -44,15 +46,15 @@
private static LogHelper applicationLogger = LogHelper.INSTANCE;
- private static final String CONFIG_HOME = System.getProperty("CONFIG_HOME");
-
- public static final String FILESEP =
- (System.getProperty("file.separator") == null) ? "/" : System.getProperty("file.separator");
- public static final String APPCONFIG_DIR =
- (CONFIG_HOME == null) ? System.getProperty("APP_HOME") + FILESEP + "appconfig" : CONFIG_HOME;
-
- private static String appConfigAuthDir = APPCONFIG_DIR + FILESEP + "auth";
- private static String defaultAuthFileName = appConfigAuthDir + FILESEP + "auth_policy.json";
+ /**
+ * The default policy file is expected to be located in either one of
+ * <ul>
+ * <li><code>$CONFIG_HOME/auth_policy.json</code></li>
+ * <li><code>$CONFIG_HOME/auth/auth_policy.json</code></li>
+ * <p>
+ * Note that if <code>CONFIG_HOME</code> is not set then assume it has a value of <code>$APP_HOME/appconfig</code>
+ */
+ private static String defaultAuthFileName = "auth_policy.json";
private static boolean usersInitialized = false;
private static HashMap<String, AAIAuthUser> users;
@@ -83,8 +85,9 @@
applicationLogger.error(ApplicationMsgs.PROCESS_REQUEST_ERROR, e);
throw new AAIAuthException(e.getMessage());
}
+
if (policyAuthFileName == null) {
- throw new AAIAuthException("Auth policy file could not be found" + CONFIG_HOME + APPCONFIG_DIR);
+ throw new AAIAuthException("Auth policy file could not be found");
}
AAIMicroServiceAuthCore.reloadUsers();
@@ -116,21 +119,46 @@
}
public static String getConfigFile(String authPolicyFile) throws IOException {
- File authFile = new File(authPolicyFile);
- if (authFile.exists()) {
- return authFile.getCanonicalPath();
- }
- authFile = new File(appConfigAuthDir + FILESEP + authPolicyFile);
- if (authFile.exists()) {
- return authFile.getCanonicalPath();
- }
- if (defaultAuthFileName != null) {
- authFile = new File(defaultAuthFileName);
- if (authFile.exists()) {
- return defaultAuthFileName;
+ return locateConfigFile(authPolicyFile).orElse(locateConfigFile(defaultAuthFileName).orElse(null));
+ }
+
+ /**
+ * Locate the auth policy file by its name or path.
+ * <ul>
+ * <li>First try to use the absolute path to the file (if provided), or instead locate the path relative to the
+ * current (or user) dir.</li>
+ * <li>If this fails, try resolving the path relative to the configuration home location (either
+ * <code>$CONFIG_HOME</code> or <code>$APP_HOME/appconfig</code>).</li>
+ * <li>If this fails try resolving relative to the <code>auth</code> folder under configuration home.</li>
+ *
+ * @param authPolicyFile
+ * filename or path
+ * @return the Optional canonical path to the located policy file
+ * @throws IOException
+ * if the construction of the canonical pathname requires filesystem queries which cause I/O error(s)
+ */
+ private static Optional<String> locateConfigFile(String authPolicyFile) throws IOException {
+ if (authPolicyFile != null) {
+ List<Path> paths = new ArrayList<>();
+ paths.add(Paths.get("."));
+
+ String configHome = System.getProperty("CONFIG_HOME");
+ if (configHome == null) {
+ configHome = System.getProperty("APP_HOME") + "/appconfig";
+ }
+
+ paths.add(Paths.get(configHome));
+ paths.add(Paths.get(configHome).resolve("auth"));
+
+ for (Path path : paths) {
+ File authFile = path.resolve(authPolicyFile).toFile();
+ if (authFile.exists()) {
+ return Optional.of(authFile.getCanonicalPath());
+ }
}
}
- return null;
+
+ return Optional.empty();
}
public static synchronized void reloadUsers() throws AAIAuthException {
@@ -190,28 +218,18 @@
user = new AAIAuthUser();
}
applicationLogger.debug("Assigning " + roleName + " to user " + name);
- user.setUser(name);
user.addRole(roleName, r);
users.put(name, user);
}
}
public static class AAIAuthUser {
- private String username;
private HashMap<String, AAIAuthRole> roles;
public AAIAuthUser() {
this.roles = new HashMap<>();
}
- public String getUser() {
- return this.username;
- }
-
- public Map<String, AAIAuthRole> getRoles() {
- return this.roles;
- }
-
public void addRole(String roleName, AAIAuthRole r) {
this.roles.put(roleName, r);
}
@@ -225,10 +243,6 @@
}
return false;
}
-
- public void setUser(String myuser) {
- this.username = myuser;
- }
}
public static class AAIAuthRole {
@@ -243,12 +257,6 @@
this.allowedFunctions.add(func);
}
- public void delAllowedFunction(String delFunc) {
- if (this.allowedFunctions.contains(delFunc)) {
- this.allowedFunctions.remove(delFunc);
- }
- }
-
public boolean hasAllowedFunction(String afunc) {
return this.allowedFunctions.contains(afunc);
}
diff --git a/src/main/java/org/onap/aai/babel/config/BabelAuthConfig.java b/src/main/java/org/onap/aai/babel/config/BabelAuthConfig.java
index 21525a1..cae71de 100644
--- a/src/main/java/org/onap/aai/babel/config/BabelAuthConfig.java
+++ b/src/main/java/org/onap/aai/babel/config/BabelAuthConfig.java
@@ -2,8 +2,8 @@
* ============LICENSE_START=======================================================
* org.onap.aai
* ================================================================================
- * Copyright © 2017-2018 AT&T Intellectual Property. All rights reserved.
- * Copyright © 2017-2018 European Software Marketing Ltd.
+ * Copyright (c) 2017-2018 AT&T Intellectual Property. All rights reserved.
+ * Copyright (c) 2017-2018 European Software Marketing Ltd.
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -18,6 +18,7 @@
* limitations under the License.
* ============LICENSE_END=========================================================
*/
+
package org.onap.aai.babel.config;
import org.springframework.beans.factory.annotation.Value;
diff --git a/src/test/java/org/onap/aai/babel/MicroServiceAuthTest.java b/src/test/java/org/onap/aai/babel/MicroServiceAuthTest.java
index b9a8ff9..ef9504b 100644
--- a/src/test/java/org/onap/aai/babel/MicroServiceAuthTest.java
+++ b/src/test/java/org/onap/aai/babel/MicroServiceAuthTest.java
@@ -27,9 +27,11 @@
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
+import java.util.concurrent.TimeUnit;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
+import org.junit.Before;
import org.junit.Test;
import org.onap.aai.auth.AAIAuthException;
import org.onap.aai.auth.AAIMicroServiceAuth;
@@ -46,11 +48,26 @@
private static final String VALID_ADMIN_USER = "cn=common-name, ou=org-unit, o=org, l=location, st=state, c=us";
private static final String authPolicyFile = "auth_policy.json";
- static {
+ @Before
+ public void setup() {
System.setProperty("CONFIG_HOME", "src/test/resources");
}
/**
+ * Test authorization of a request when authentication is disabled.
+ *
+ * @throws AAIAuthException
+ * if the test creates invalid Auth Policy roles
+ */
+ @Test
+ public void testAuthenticationDisabled() throws AAIAuthException {
+ BabelAuthConfig babelAuthConfig = new BabelAuthConfig();
+ babelAuthConfig.setAuthenticationDisable(true);
+ AAIMicroServiceAuth auth = new AAIMicroServiceAuth(babelAuthConfig);
+ assertThat(auth.validateRequest(null, new MockHttpServletRequest(), null, "any/uri"), is(true));
+ }
+
+ /**
* Temporarily invalidate the default policy file and then try to initialize the authorization class using the name
* of a policy file that does not exist.
*
@@ -71,6 +88,26 @@
}
/**
+ * Temporarily invalidate the default policy file and then try to initialize the authorization class using a null
+ * policy file name.
+ *
+ * @throws AAIAuthException
+ * if the Auth policy file cannot be loaded
+ */
+ @Test(expected = AAIAuthException.class)
+ public void testNullPolicyFile() throws AAIAuthException {
+ String defaultFile = AAIMicroServiceAuthCore.getDefaultAuthFileName();
+ try {
+ AAIMicroServiceAuthCore.setDefaultAuthFileName("invalid.default.file");
+ BabelAuthConfig babelServiceAuthConfig = new BabelAuthConfig();
+ babelServiceAuthConfig.setAuthPolicyFile(null);
+ new AAIMicroServiceAuth(babelServiceAuthConfig);
+ } finally {
+ AAIMicroServiceAuthCore.setDefaultAuthFileName(defaultFile);
+ }
+ }
+
+ /**
* Test loading of a temporary file created with the specified roles.
*
* @throws AAIAuthException
@@ -89,6 +126,40 @@
}
/**
+ * Test re-loading of users by changing the contents of a temporary file.
+ *
+ * @throws JSONException
+ * if this test creates an invalid JSON object
+ * @throws AAIAuthException
+ * if the test creates invalid Auth Policy roles
+ * @throws IOException
+ * for I/O failures
+ * @throws InterruptedException
+ * if interrupted while sleeping
+ */
+ @Test
+ public void createLocalAuthFileOnChange()
+ throws JSONException, AAIAuthException, IOException, InterruptedException {
+ JSONObject roles = createRoleObject("role", createUserObject("user"), createFunctionObject("func"));
+ File file = createTempPolicyFile(roles);
+
+ BabelAuthConfig babelAuthConfig = new BabelAuthConfig();
+ babelAuthConfig.setAuthPolicyFile(file.getAbsolutePath());
+ new AAIMicroServiceAuth(babelAuthConfig);
+
+ // Make changes to the temp file
+ FileWriter fileWriter = new FileWriter(file);
+ fileWriter.write("");
+ fileWriter.flush();
+ fileWriter.close();
+
+ // Wait for the file to be reloaded
+ TimeUnit.SECONDS.sleep(3);
+
+ AAIMicroServiceAuthCore.cleanup();
+ }
+
+ /**
* Test that the default policy file is loaded when a non-existent file is passed to the authorisation class.
*
* @throws AAIAuthException
@@ -104,6 +175,23 @@
}
/**
+ * Test that the default policy file is loaded when a non-existent file is passed to the authorisation class and
+ * CONFIG_HOME is not set.
+ *
+ * @throws AAIAuthException
+ * if the Auth Policy cannot be loaded
+ */
+ @Test
+ public void createAuthFromDefaultFileAppHome() throws AAIAuthException {
+ System.clearProperty("CONFIG_HOME");
+ System.setProperty("APP_HOME", "src/test/resources");
+ BabelAuthConfig babelServiceAuthConfig = new BabelAuthConfig();
+ babelServiceAuthConfig.setAuthPolicyFile("non-existent-file");
+ new AAIMicroServiceAuth(babelServiceAuthConfig);
+ // The default policy will have been loaded from APP_HOME/appconfig
+ }
+
+ /**
* Test loading of the policy file relative to CONFIG_HOME.
*
* @throws AAIAuthException
@@ -146,16 +234,29 @@
* if the auth policy file cannot be loaded
*/
private AAIMicroServiceAuth createAuthService(JSONObject roles) throws AAIAuthException, IOException {
+ File file = createTempPolicyFile(roles);
+ BabelAuthConfig babelAuthConfig = new BabelAuthConfig();
+ babelAuthConfig.setAuthPolicyFile(file.getAbsolutePath());
+ return new AAIMicroServiceAuth(babelAuthConfig);
+ }
+
+ /**
+ * Create a temporary JSON file using the supplied roles.
+ *
+ * @param roles
+ * the roles to use to populate the new file
+ * @return the new temporary file
+ * @throws IOException
+ * for I/O errors
+ */
+ private File createTempPolicyFile(JSONObject roles) throws IOException {
File file = File.createTempFile("auth-policy", "json");
file.deleteOnExit();
FileWriter fileWriter = new FileWriter(file);
fileWriter.write(roles.toString());
fileWriter.flush();
fileWriter.close();
-
- BabelAuthConfig babelAuthConfig = new BabelAuthConfig();
- babelAuthConfig.setAuthPolicyFile(file.getAbsolutePath());
- return new AAIMicroServiceAuth(babelAuthConfig);
+ return file;
}
/**
diff --git a/src/test/resources/appconfig/auth/auth_policy.json b/src/test/resources/appconfig/auth/auth_policy.json
new file mode 100644
index 0000000..dc966e0
--- /dev/null
+++ b/src/test/resources/appconfig/auth/auth_policy.json
@@ -0,0 +1,12 @@
+{"roles": [
+ {
+ "name": "nofuncauth",
+ "functions": [{
+ "name": "nofuncutil"
+ }],
+ "users": [{
+ "user": "aai",
+ "pass": "OBF:1u2a1t2v1vgb1s3g1s3m1vgj1t3b1u30"
+ }]
+ }
+]}