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)

Reply via email to