Repository: oozie Updated Branches: refs/heads/master 8cf8a78d1 -> db15e6d30
OOZIE-3379 [client] Auth token cache file name should include OOZIE_URL (zuston via andras.piros) Project: http://git-wip-us.apache.org/repos/asf/oozie/repo Commit: http://git-wip-us.apache.org/repos/asf/oozie/commit/db15e6d3 Tree: http://git-wip-us.apache.org/repos/asf/oozie/tree/db15e6d3 Diff: http://git-wip-us.apache.org/repos/asf/oozie/diff/db15e6d3 Branch: refs/heads/master Commit: db15e6d30dea13d5c4f78c0bbba96205e16c5981 Parents: 8cf8a78 Author: Andras Piros <[email protected]> Authored: Thu Dec 6 12:50:48 2018 +0100 Committer: Andras Piros <[email protected]> Committed: Thu Dec 6 12:50:48 2018 +0100 ---------------------------------------------------------------------- .../apache/oozie/client/AuthOozieClient.java | 64 ++++-- .../oozie/test/EmbeddedServletContainer.java | 29 ++- .../servlet/TestAuthFilterAuthOozieClient.java | 218 ++++++++++++++----- release-log.txt | 1 + 4 files changed, 233 insertions(+), 79 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/oozie/blob/db15e6d3/client/src/main/java/org/apache/oozie/client/AuthOozieClient.java ---------------------------------------------------------------------- diff --git a/client/src/main/java/org/apache/oozie/client/AuthOozieClient.java b/client/src/main/java/org/apache/oozie/client/AuthOozieClient.java index 3a8b5ab..1371a91 100644 --- a/client/src/main/java/org/apache/oozie/client/AuthOozieClient.java +++ b/client/src/main/java/org/apache/oozie/client/AuthOozieClient.java @@ -29,12 +29,17 @@ import java.io.Writer; import java.lang.management.ManagementFactory; import java.net.HttpURLConnection; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.StandardCopyOption; import java.util.HashMap; import java.util.Map; +import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Charsets; +import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; +import org.apache.commons.codec.binary.Base64; +import org.apache.commons.io.FilenameUtils; import org.apache.hadoop.security.authentication.client.AuthenticatedURL; import org.apache.hadoop.security.authentication.client.AuthenticationException; import org.apache.hadoop.security.authentication.client.Authenticator; @@ -57,12 +62,7 @@ public class AuthOozieClient extends XOozieClient { */ public static final String USE_AUTH_TOKEN_CACHE_SYS_PROP = "oozie.auth.token.cache"; - /** - * File constant that defines the location of the authentication token cache file. - * <p> - * It resolves to <code>${user.home}/.oozie-auth-token</code>. - */ - public static final File AUTH_TOKEN_CACHE_FILE = new File(System.getProperty("user.home"), ".oozie-auth-token"); + public static final int AUTH_TOKEN_CACHE_FILENAME_MAXLENGTH = 255; public enum AuthType { KERBEROS, SIMPLE @@ -71,6 +71,13 @@ public class AuthOozieClient extends XOozieClient { private String authOption = null; /** + * authTokenCacheFile defines the location of the authentication token cache file. + * <p> + * It resolves to <code>${user.home}/.oozie-auth-token-Base64(${oozieUrl})</code>. + */ + private final File authTokenCacheFile; + + /** * Create an instance of the AuthOozieClient. * * @param oozieUrl the Oozie URL @@ -85,9 +92,26 @@ public class AuthOozieClient extends XOozieClient { * @param oozieUrl the Oozie URL * @param authOption the auth option */ + @SuppressFBWarnings(value = "PATH_TRAVERSAL_IN", justification = "FilenameUtils is used to filter user input. JDK8+ is used.") public AuthOozieClient(String oozieUrl, String authOption) { super(oozieUrl); this.authOption = authOption; + String filename = getAuthCacheFileName(oozieUrl); + // just to filter user input + authTokenCacheFile = new File(System.getProperty("user.home"), FilenameUtils.getName(filename)); + if (filename.length() >= AUTH_TOKEN_CACHE_FILENAME_MAXLENGTH && authTokenCacheFile.exists()) { + System.out.println("Warn: the same Oozie auth cache filename exists, filename=" + filename); + } + } + + @VisibleForTesting + public String getAuthCacheFileName(String oozieUrl) { + String encodeBase64OozieUrl = Base64.encodeBase64URLSafeString(oozieUrl.getBytes(StandardCharsets.UTF_8)); + String filename = ".oozie-auth-token-" + encodeBase64OozieUrl; + if (filename.length() >= AUTH_TOKEN_CACHE_FILENAME_MAXLENGTH) { + filename = filename.substring(0, AUTH_TOKEN_CACHE_FILENAME_MAXLENGTH); + } + return filename; } /** @@ -129,7 +153,7 @@ public class AuthOozieClient extends XOozieClient { long expires = getExpirationTime(currentToken); if (expires < System.currentTimeMillis() + 300000) { if (useAuthFile) { - AUTH_TOKEN_CACHE_FILE.delete(); + authTokenCacheFile.delete(); } currentToken = new AuthenticatedURL.Token(); } @@ -143,7 +167,7 @@ public class AuthOozieClient extends XOozieClient { if (conn.getResponseCode() == HttpURLConnection.HTTP_UNAUTHORIZED || conn.getResponseCode() == HttpURLConnection.HTTP_FORBIDDEN) { if (useAuthFile) { - AUTH_TOKEN_CACHE_FILE.delete(); + authTokenCacheFile.delete(); } currentToken = new AuthenticatedURL.Token(); } else { @@ -159,7 +183,7 @@ public class AuthOozieClient extends XOozieClient { AuthenticatedURL.extractToken(conn, currentToken); } catch (AuthenticationException ex) { if (useAuthFile) { - AUTH_TOKEN_CACHE_FILE.delete(); + authTokenCacheFile.delete(); } currentToken = new AuthenticatedURL.Token(); } @@ -174,7 +198,7 @@ public class AuthOozieClient extends XOozieClient { } catch (AuthenticationException ex) { if (useAuthFile) { - AUTH_TOKEN_CACHE_FILE.delete(); + authTokenCacheFile.delete(); } throw new OozieClientException(OozieClientException.AUTHENTICATION, "Could not authenticate, " + ex.getMessage(), ex); @@ -182,7 +206,11 @@ public class AuthOozieClient extends XOozieClient { } // If we got a new token, save it to the cache file - if (useAuthFile && currentToken.isSet() && !currentToken.equals(readToken)) { + // For comparison of currentToken and readToken, please see the details of OOZIE-3396 + // Here, because of Hadoop AuthenticatedURL.Token don't override the equals() method, + // we have to compare the token.toString() + if (useAuthFile && currentToken.isSet() && + (readToken == null || !currentToken.toString().equals(readToken.toString()))) { writeAuthToken(currentToken); } @@ -216,9 +244,9 @@ public class AuthOozieClient extends XOozieClient { */ protected AuthenticatedURL.Token readAuthToken() { AuthenticatedURL.Token authToken = null; - if (AUTH_TOKEN_CACHE_FILE.exists()) { + if (authTokenCacheFile.exists()) { try { - BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(AUTH_TOKEN_CACHE_FILE), + BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(authTokenCacheFile), Charsets.UTF_8)); String line = reader.readLine(); reader.close(); @@ -252,17 +280,17 @@ public class AuthOozieClient extends XOozieClient { Writer writer = new OutputStreamWriter(new FileOutputStream(tmpTokenFile), Charsets.UTF_8); writer.write(authToken.toString()); writer.close(); - Files.move(tmpTokenFile.toPath(), AUTH_TOKEN_CACHE_FILE.toPath(), StandardCopyOption.ATOMIC_MOVE); + Files.move(tmpTokenFile.toPath(), authTokenCacheFile.toPath(), StandardCopyOption.ATOMIC_MOVE); // sets read-write permissions to owner only - AUTH_TOKEN_CACHE_FILE.setReadable(false, false); - AUTH_TOKEN_CACHE_FILE.setReadable(true, true); - AUTH_TOKEN_CACHE_FILE.setWritable(true, true); + authTokenCacheFile.setReadable(false, false); + authTokenCacheFile.setReadable(true, true); + authTokenCacheFile.setWritable(true, true); } catch (IOException ioe) { // if case of any error we just delete the cache, if user-only // write permissions are not properly set a security exception // is thrown and the file will be deleted. - AUTH_TOKEN_CACHE_FILE.delete(); + authTokenCacheFile.delete(); } } http://git-wip-us.apache.org/repos/asf/oozie/blob/db15e6d3/core/src/main/java/org/apache/oozie/test/EmbeddedServletContainer.java ---------------------------------------------------------------------- diff --git a/core/src/main/java/org/apache/oozie/test/EmbeddedServletContainer.java b/core/src/main/java/org/apache/oozie/test/EmbeddedServletContainer.java index fc9d840..2fb099f 100644 --- a/core/src/main/java/org/apache/oozie/test/EmbeddedServletContainer.java +++ b/core/src/main/java/org/apache/oozie/test/EmbeddedServletContainer.java @@ -39,7 +39,8 @@ import java.util.Map; /** * An embedded servlet container for testing purposes. <p> It provides reduced functionality, it supports only - * Servlets. <p> The servlet container is started in a free port. + * Servlets. <p> The servlet container is started in a free port or a specific port which depends on the testing + * purposes. */ public class EmbeddedServletContainer { private Server server; @@ -64,6 +65,11 @@ public class EmbeddedServletContainer { server.setHandler(context); } + public EmbeddedServletContainer(String contextPath, int port) { + this(contextPath); + this.port = port; + } + /** * Add a servlet to the container. * @@ -115,18 +121,33 @@ public class EmbeddedServletContainer { } /** - * Start the servlet container. <p> The container starts on a free port. + * Start the servlet container. <p> The container starts on a free port or a specific port. * * @throws Exception thrown if the container could not start. */ public void start() throws Exception { host = InetAddress.getLocalHost().getHostName(); + port = startServerWithPort(port); + System.out.println("Running embedded servlet container at: http://" + host + ":" + port); + } + + /** + * if port is the default value (-1), this will start on the free port, and this function will return this port + * if port is not -1, this will start on the specific port + * @param port + * @return + * @throws Exception + */ + private int startServerWithPort(int port) throws Exception { + host = InetAddress.getLocalHost().getHostName(); ServerConnector connector = new ServerConnector(server, new HttpConnectionFactory(new HttpConfiguration())); connector.setHost(host); + if (port != -1) { + connector.setPort(port); + } server.setConnectors(new Connector[] { connector }); server.start(); - port = connector.getLocalPort(); - System.out.println("Running embedded servlet container at: http://" + host + ":" + port); + return connector.getLocalPort(); } /** http://git-wip-us.apache.org/repos/asf/oozie/blob/db15e6d3/core/src/test/java/org/apache/oozie/servlet/TestAuthFilterAuthOozieClient.java ---------------------------------------------------------------------- diff --git a/core/src/test/java/org/apache/oozie/servlet/TestAuthFilterAuthOozieClient.java b/core/src/test/java/org/apache/oozie/servlet/TestAuthFilterAuthOozieClient.java index 04fde73..bc469e2 100644 --- a/core/src/test/java/org/apache/oozie/servlet/TestAuthFilterAuthOozieClient.java +++ b/core/src/test/java/org/apache/oozie/servlet/TestAuthFilterAuthOozieClient.java @@ -35,10 +35,13 @@ import org.apache.oozie.test.EmbeddedServletContainer; import org.apache.oozie.test.XTestCase; import org.apache.oozie.util.IOUtils; +import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; +import java.net.InetSocketAddress; +import java.net.Socket; import java.net.URL; import java.net.URLEncoder; import java.nio.charset.Charset; @@ -53,6 +56,11 @@ import java.util.concurrent.Callable; public class TestAuthFilterAuthOozieClient extends XTestCase { private static final String SECRET = "secret"; private EmbeddedServletContainer container; + private int embeddedServletContainerPort; + + public TestAuthFilterAuthOozieClient() { + this.embeddedServletContainerPort = getFreePort(); + } protected String getContextURL() { return container.getContextURL(); @@ -75,7 +83,8 @@ public class TestAuthFilterAuthOozieClient extends XTestCase { return new URL(sb.toString()); } - protected void runTest(Callable<Void> assertions, Configuration additionalConf) throws Exception { + protected File runTest(Callable<Void> assertions, Configuration additionalConf, String contextPath) + throws Exception { Services services = new Services(); try { services.init(); @@ -88,7 +97,10 @@ public class TestAuthFilterAuthOozieClient extends XTestCase { Services.get().setService(ForTestWorkflowStoreService.class); Services.get().setService(MockDagEngineService.class); Services.get().setService(MockCoordinatorEngineService.class); - container = new EmbeddedServletContainer("oozie"); + // the embeddedServletContainer must be instantiated with the same port. On one hand, when testing the + // authCache with the same oozieUrl, this will work. On the other hand, when testing multiple authCache with + // the different oozieUrls, the cacheFileName( container.getContextUrl() ) also will be different. + container = new EmbeddedServletContainer(contextPath, embeddedServletContainerPort); container.addServletEndpoint("/versions", HeaderTestingVersionServlet.class); String version = "/v" + XOozieClient.WS_PROTOCOL_VERSION; container.addServletEndpoint(version + "/admin/*", V1AdminServlet.class); @@ -96,8 +108,8 @@ public class TestAuthFilterAuthOozieClient extends XTestCase { container.addFilter("/*", AuthFilter.class); container.start(); assertions.call(); - } - finally { + return getCacheFile(container.getContextURL()); + } finally { if (container != null) { container.stop(); } @@ -106,6 +118,39 @@ public class TestAuthFilterAuthOozieClient extends XTestCase { } } + private File getCacheFile(String oozieUrl) { + AuthOozieClient authOozieClient = new AuthOozieClient(oozieUrl); + String filename = authOozieClient.getAuthCacheFileName(oozieUrl); + return new File(System.getProperty("user.home"), filename); + } + + /** + * get free port + * @return + */ + private int getFreePort() { + Socket socket = new Socket(); + InetSocketAddress inetAddress = new InetSocketAddress(0); + try { + socket.bind(inetAddress); + if (null == socket || socket.isClosed()) { + return -1; + } + + int port = socket.getLocalPort(); + socket.close(); + return port; + } catch (IOException e) { + System.err.println("Failed to get system free port, caused by: " + e.getMessage()); + } + return -1; + } + + protected File runTest(Callable<Void> assertions, Configuration additionalConf) + throws Exception { + return runTest(assertions, additionalConf, "oozie"); + } + public static class Authenticator4Test extends PseudoAuthenticator { private static boolean USED = false; @@ -162,43 +207,11 @@ public class TestAuthFilterAuthOozieClient extends XTestCase { assertTrue(Authenticator4Test.USED); } - public void testClientAuthTokenCache() throws Exception { - Configuration conf = new Configuration(false); - // This test requires a constant secret. - // In Hadoop 2.5.0, you can set a secret string directly with oozie.authentication.signature.secret and the - // AuthenticationFilter will use it. - // In Hadoop 2.6.0 (HADOOP-10868), this was abstracted out to SecretProviders that have differnet implementations. By - // default, if a String was given for the secret, the StringSignerSecretProvider would be automatically used and - // oozie.authentication.signature.secret would still be loaded. - // In Hadoop 2.7.0 (HADOOP-11748), this automatic behavior was removed for security reasons, and the class was made package - // private and moved to the hadoop-auth test artifact. So, not only can we not simply set - // oozie.authentication.signature.secret, but we also can't manually configure the StringSignerSecretProvider either. - // However, Hadoop 2.7.0 (HADOOP-10670) also added a FileSignerSecretProvider, which we'll use if it exists - try { - if (Class.forName("org.apache.hadoop.security.authentication.util.FileSignerSecretProvider") != null) { - String secretFile = getTestCaseConfDir() + "/auth-secret"; - conf.set("oozie.authentication.signature.secret.file", secretFile); - FileWriter fw = null; - try { - fw = new FileWriter(secretFile); - fw.write(SECRET); - } finally { - if (fw != null) { - fw.close(); - } - } - } - } catch (ClassNotFoundException cnfe) { - // ignore - } - conf.set("oozie.authentication.signature.secret", SECRET); - conf.set("oozie.authentication.simple.anonymous.allowed", "false"); + Configuration conf = getAuthenticationConf(); //not using cache - AuthOozieClient.AUTH_TOKEN_CACHE_FILE.delete(); - assertFalse(AuthOozieClient.AUTH_TOKEN_CACHE_FILE.exists()); - runTest(new Callable<Void>() { + File cacheFile = runTest(new Callable<Void>() { public Void call() throws Exception { String oozieUrl = getContextURL(); String[] args = new String[]{"admin", "-status", "-oozie", oozieUrl}; @@ -206,13 +219,13 @@ public class TestAuthFilterAuthOozieClient extends XTestCase { return null; } }, conf); - assertFalse(AuthOozieClient.AUTH_TOKEN_CACHE_FILE.exists()); + assertFalse(cacheFile.exists()); //using cache setSystemProperty("oozie.auth.token.cache", "true"); - AuthOozieClient.AUTH_TOKEN_CACHE_FILE.delete(); - assertFalse(AuthOozieClient.AUTH_TOKEN_CACHE_FILE.exists()); - runTest(new Callable<Void>() { + cacheFile.delete(); + assertFalse(cacheFile.exists()); + cacheFile = runTest(new Callable<Void>() { public Void call() throws Exception { String oozieUrl = getContextURL(); String[] args = new String[]{"admin", "-status", "-oozie", oozieUrl}; @@ -220,12 +233,12 @@ public class TestAuthFilterAuthOozieClient extends XTestCase { return null; } }, conf); - assertTrue(AuthOozieClient.AUTH_TOKEN_CACHE_FILE.exists()); - String currentCache = IOUtils.getReaderAsString(new FileReader(AuthOozieClient.AUTH_TOKEN_CACHE_FILE), -1); + assertTrue(cacheFile.exists()); + String currentCache = IOUtils.getReaderAsString(new FileReader(cacheFile), -1); //re-using cache setSystemProperty("oozie.auth.token.cache", "true"); - runTest(new Callable<Void>() { + cacheFile = runTest(new Callable<Void>() { public Void call() throws Exception { String oozieUrl = getContextURL(); String[] args = new String[]{"admin", "-status", "-oozie", oozieUrl}; @@ -233,14 +246,14 @@ public class TestAuthFilterAuthOozieClient extends XTestCase { return null; } }, conf); - assertTrue(AuthOozieClient.AUTH_TOKEN_CACHE_FILE.exists()); - String newCache = IOUtils.getReaderAsString(new FileReader(AuthOozieClient.AUTH_TOKEN_CACHE_FILE), -1); + assertTrue(cacheFile.exists()); + String newCache = IOUtils.getReaderAsString(new FileReader(cacheFile), -1); assertEquals(currentCache, newCache); //re-using cache with token that will expire within 5 minutes - currentCache = writeTokenCache(System.currentTimeMillis() + 300000); + currentCache = writeTokenCache(System.currentTimeMillis() + 300000, cacheFile); setSystemProperty("oozie.auth.token.cache", "true"); - runTest(new Callable<Void>() { + cacheFile = runTest(new Callable<Void>() { public Void call() throws Exception { String oozieUrl = getContextURL(); String[] args = new String[]{"admin", "-status", "-oozie", oozieUrl}; @@ -248,14 +261,14 @@ public class TestAuthFilterAuthOozieClient extends XTestCase { return null; } }, conf); - assertTrue(AuthOozieClient.AUTH_TOKEN_CACHE_FILE.exists()); - newCache = IOUtils.getReaderAsString(new FileReader(AuthOozieClient.AUTH_TOKEN_CACHE_FILE), -1); + assertTrue(cacheFile.exists()); + newCache = IOUtils.getReaderAsString(new FileReader(cacheFile), -1); assertFalse("Almost expired token should have been updated but was not", currentCache.equals(newCache)); //re-using cache with expired token - currentCache = writeTokenCache(System.currentTimeMillis() - 1000); + currentCache = writeTokenCache(System.currentTimeMillis() - 1000, cacheFile); setSystemProperty("oozie.auth.token.cache", "true"); - runTest(new Callable<Void>() { + cacheFile = runTest(new Callable<Void>() { public Void call() throws Exception { String oozieUrl = getContextURL(); String[] args = new String[]{"admin", "-status", "-oozie", oozieUrl}; @@ -263,17 +276,81 @@ public class TestAuthFilterAuthOozieClient extends XTestCase { return null; } }, conf); - assertTrue(AuthOozieClient.AUTH_TOKEN_CACHE_FILE.exists()); - newCache = IOUtils.getReaderAsString(new FileReader(AuthOozieClient.AUTH_TOKEN_CACHE_FILE), -1); + assertTrue(cacheFile.exists()); + newCache = IOUtils.getReaderAsString(new FileReader(cacheFile), -1); assertFalse("Expired token should have been updated but was not", currentCache.equals(newCache)); + + setSystemProperty("oozie.auth.token.cache", "true"); + cacheFile.delete(); + assertFalse(cacheFile.exists()); } - private static String writeTokenCache(long expirationTime) throws Exception { + // the authToken will be stored in the different files when the oozieUrl is different. + // the authTokenCache filename is definded by the oozieUrl. + // this will work when the oozieClient connects to the different cluster. + public void testMultipleClientAuthTokenCache() throws Exception { + Configuration conf = getAuthenticationConf(); + setSystemProperty("oozie.auth.token.cache", "true"); + + File cacheFile_1 = serverRunTest(conf, "oozie_1"); + + // with the same oozie host and the same contextPath + File cacheFile_2 = serverRunTest(conf, "oozie_1"); + + String currentCache_1 = IOUtils.getReaderAsString(new FileReader(cacheFile_1), -1); + String currentCache_2 = IOUtils.getReaderAsString(new FileReader(cacheFile_2), -1); + assertEquals("AuthTokenCache with the same oozieUrl should be same but was not", currentCache_1, currentCache_2); + + assertTrue("The cacheFile_2 file should exist but was not", cacheFile_2.exists()); + assertTrue("The cacheFile_1 file should exist but was not", cacheFile_1.exists()); + + // with the same oozie host and with the different contextPath + File cacheFile_3 = serverRunTest(conf, "oozie_3"); + + // verify that the cacheFile will not be deleted + assertTrue("The cacheFile_3 file should exist but was not", cacheFile_3.exists()); + assertTrue("The cacheFile_1 file should exist but was not", cacheFile_1.exists()); + + String currentCache_3 = IOUtils.getReaderAsString(new FileReader(cacheFile_3), -1); + assertNotSame("AuthTokenCache with different oozieUrls should be different but was not", currentCache_1, currentCache_3); + + // with the different oozie host and the different contextPath, this request will fail + File cacheFile_4 = runTest(new Callable<Void>() { + public Void call() throws Exception { + String oozieUrl = getContextURL(); + String[] args = new String[] { "admin", "-status", "-oozie", oozieUrl + "/test"}; + assertNotSame("The request with the no existing url will fail but was not", 0, new OozieCLI().run(args)); + return null; + } + }, conf, "oozie_4"); + + assertFalse("The cache can't exist when the request with the not existing url", cacheFile_4.exists()); + + // remove the cache files + cacheFile_2.delete(); + assertFalse("CacheFile_2 should not exist but was not", cacheFile_2.exists()); + assertFalse("CacheFile_1 should not exist but was not", cacheFile_1.exists()); + cacheFile_3.delete(); + assertFalse("CacheFile_3 should not exist but was not", cacheFile_3.exists()); + } + + private File serverRunTest(Configuration conf, String contextPath) throws Exception { + return runTest(new Callable<Void>() { + public Void call() throws Exception { + String oozieUrl = getContextURL(); + String[] args = new String[] { "admin", "-status", "-oozie", oozieUrl }; + assertEquals("The request will be success but was not", 0, new OozieCLI().run(args)); + return null; + } + }, conf, contextPath); + } + + private static String writeTokenCache(long expirationTime, File cacheFile) throws Exception { AuthenticationToken authToken = new AuthenticationToken(getOozieUser(), getOozieUser(), "simple"); authToken.setExpires(expirationTime); String signedTokenStr = computeSignature(SECRET.getBytes(Charset.forName("UTF-8")), authToken.toString()); signedTokenStr = authToken.toString() + "&s=" + signedTokenStr; - PrintWriter pw = new PrintWriter(AuthOozieClient.AUTH_TOKEN_CACHE_FILE); + PrintWriter pw = new PrintWriter(cacheFile); pw.write(signedTokenStr); pw.close(); return signedTokenStr; @@ -313,4 +390,31 @@ public class TestAuthFilterAuthOozieClient extends XTestCase { } }, null); } + + private Configuration getAuthenticationConf() { + Configuration conf = new Configuration(false); + // This test requires a constant secret. + // In Hadoop 2.5.0, you can set a secret string directly with oozie.authentication.signature.secret and the + // AuthenticationFilter will use it. + // In Hadoop 2.6.0 (HADOOP-10868), this was abstracted out to SecretProviders that have differnet implementations. By + // default, if a String was given for the secret, the StringSignerSecretProvider would be automatically used and + // oozie.authentication.signature.secret would still be loaded. + // In Hadoop 2.7.0 (HADOOP-11748), this automatic behavior was removed for security reasons, and the class was made package + // private and moved to the hadoop-auth test artifact. So, not only can we not simply set + // oozie.authentication.signature.secret, but we also can't manually configure the StringSignerSecretProvider either. + // However, Hadoop 2.7.0 (HADOOP-10670) also added a FileSignerSecretProvider, which we'll use if it exists + try { + if (Class.forName("org.apache.hadoop.security.authentication.util.FileSignerSecretProvider") != null) { + String secretFile = getTestCaseConfDir() + "/auth-secret"; + conf.set("oozie.authentication.signature.secret.file", secretFile); + FileWriter fw = new FileWriter(secretFile); + fw.write(SECRET); + } + } catch (Exception cnfe) { + // ignore + } + conf.set("oozie.authentication.signature.secret", SECRET); + conf.set("oozie.authentication.simple.anonymous.allowed", "false"); + return conf; + } } http://git-wip-us.apache.org/repos/asf/oozie/blob/db15e6d3/release-log.txt ---------------------------------------------------------------------- diff --git a/release-log.txt b/release-log.txt index 8d738b5..501713e 100644 --- a/release-log.txt +++ b/release-log.txt @@ -1,5 +1,6 @@ -- Oozie 5.2.0 release (trunk - unreleased) +OOZIE-3379 [client] Auth token cache file name should include OOZIE_URL (zuston via andras.piros) OOZIE-3397 Improve logging in NotificationXCommand (kmarton) OOZIE-3382 [SSH action] [SSH action] Optimize process streams draining (asalamon74 via andras.piros) OOZIE-3384 [tests] TestWorkflowActionRetryInfoXCommand#testRetryConsoleUrlForked() is flaky (asalamon74 via kmarton)
