浏览代码

YARN-10814. Fallback to RandomSecretProvider if the secret file is empty. Contributed by Tamas Domok

Szilard Nemeth 3 年之前
父节点
当前提交
224b42108d

+ 2 - 2
hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/server/AuthenticationFilter.java

@@ -237,8 +237,8 @@ public class AuthenticationFilter implements Filter {
         provider.init(config, ctx, validity);
         provider.init(config, ctx, validity);
       } catch (Exception e) {
       } catch (Exception e) {
         if (!disallowFallbackToRandomSecretProvider) {
         if (!disallowFallbackToRandomSecretProvider) {
-          LOG.info("Unable to initialize FileSignerSecretProvider, " +
-                       "falling back to use random secrets.");
+          LOG.warn("Unable to initialize FileSignerSecretProvider, " +
+              "falling back to use random secrets. Reason: " + e.getMessage());
           provider = new RandomSignerSecretProvider();
           provider = new RandomSignerSecretProvider();
           provider.init(config, ctx, validity);
           provider.init(config, ctx, validity);
         } else {
         } else {

+ 11 - 16
hadoop-common-project/hadoop-auth/src/main/java/org/apache/hadoop/security/authentication/util/FileSignerSecretProvider.java

@@ -13,15 +13,15 @@
  */
  */
 package org.apache.hadoop.security.authentication.util;
 package org.apache.hadoop.security.authentication.util;
 
 
-import org.apache.hadoop.thirdparty.com.google.common.base.Charsets;
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.classification.InterfaceStability;
 import org.apache.hadoop.classification.InterfaceStability;
 import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
 import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
-import org.apache.hadoop.security.authentication.util.SignerSecretProvider;
 
 
 import javax.servlet.ServletContext;
 import javax.servlet.ServletContext;
 import java.io.*;
 import java.io.*;
-import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.Properties;
 import java.util.Properties;
 
 
 /**
 /**
@@ -43,29 +43,24 @@ public class FileSignerSecretProvider extends SignerSecretProvider {
     String signatureSecretFile = config.getProperty(
     String signatureSecretFile = config.getProperty(
         AuthenticationFilter.SIGNATURE_SECRET_FILE, null);
         AuthenticationFilter.SIGNATURE_SECRET_FILE, null);
 
 
-    Reader reader = null;
     if (signatureSecretFile != null) {
     if (signatureSecretFile != null) {
-      try {
+      try (Reader reader = new InputStreamReader(Files.newInputStream(
+              Paths.get(signatureSecretFile)), StandardCharsets.UTF_8)) {
         StringBuilder sb = new StringBuilder();
         StringBuilder sb = new StringBuilder();
-        reader = new InputStreamReader(
-            new FileInputStream(signatureSecretFile), Charsets.UTF_8);
         int c = reader.read();
         int c = reader.read();
         while (c > -1) {
         while (c > -1) {
           sb.append((char) c);
           sb.append((char) c);
           c = reader.read();
           c = reader.read();
         }
         }
-        secret = sb.toString().getBytes(Charset.forName("UTF-8"));
+
+        secret = sb.toString().getBytes(StandardCharsets.UTF_8);
+        if (secret.length == 0) {
+          throw new RuntimeException("No secret in signature secret file: "
+             + signatureSecretFile);
+        }
       } catch (IOException ex) {
       } catch (IOException ex) {
         throw new RuntimeException("Could not read signature secret file: " +
         throw new RuntimeException("Could not read signature secret file: " +
             signatureSecretFile);
             signatureSecretFile);
-      } finally {
-        if (reader != null) {
-          try {
-            reader.close();
-          } catch (IOException e) {
-            // nothing to do
-          }
-        }
       }
       }
     }
     }
 
 

+ 28 - 0
hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/server/TestAuthenticationFilter.java

@@ -305,6 +305,34 @@ public class TestAuthenticationFilter {
       filter.destroy();
       filter.destroy();
     }
     }
   }
   }
+
+  @Test
+  public void testEmptySecretFileFallbacksToRandomSecret() throws Exception {
+    AuthenticationFilter filter = new AuthenticationFilter();
+    try {
+      FilterConfig config = Mockito.mock(FilterConfig.class);
+      Mockito.when(config.getInitParameter(
+              AuthenticationFilter.AUTH_TYPE)).thenReturn("simple");
+      File secretFile = File.createTempFile("test_empty_secret", ".txt");
+      secretFile.deleteOnExit();
+      Assert.assertTrue(secretFile.exists());
+      Mockito.when(config.getInitParameter(
+              AuthenticationFilter.SIGNATURE_SECRET_FILE))
+              .thenReturn(secretFile.getAbsolutePath());
+      Mockito.when(config.getInitParameterNames()).thenReturn(
+              new Vector<>(Arrays.asList(AuthenticationFilter.AUTH_TYPE,
+                      AuthenticationFilter.SIGNATURE_SECRET_FILE)).elements());
+      ServletContext context = Mockito.mock(ServletContext.class);
+      Mockito.when(context.getAttribute(
+              AuthenticationFilter.SIGNER_SECRET_PROVIDER_ATTRIBUTE))
+              .thenReturn(null);
+      Mockito.when(config.getServletContext()).thenReturn(context);
+      filter.init(config);
+      Assert.assertTrue(filter.isRandomSecret());
+    } finally {
+      filter.destroy();
+    }
+  }
   
   
   @Test
   @Test
   public void testInitCaseSensitivity() throws Exception {
   public void testInitCaseSensitivity() throws Exception {

+ 27 - 0
hadoop-common-project/hadoop-auth/src/test/java/org/apache/hadoop/security/authentication/util/TestFileSignerSecretProvider.java

@@ -16,12 +16,16 @@ package org.apache.hadoop.security.authentication.util;
 import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
 import org.apache.hadoop.security.authentication.server.AuthenticationFilter;
 import org.junit.Assert;
 import org.junit.Assert;
 import org.junit.Test;
 import org.junit.Test;
+import org.junit.function.ThrowingRunnable;
 
 
 import java.io.File;
 import java.io.File;
 import java.io.FileWriter;
 import java.io.FileWriter;
 import java.io.Writer;
 import java.io.Writer;
 import java.util.Properties;
 import java.util.Properties;
 
 
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
 public class TestFileSignerSecretProvider {
 public class TestFileSignerSecretProvider {
 
 
   @Test
   @Test
@@ -48,4 +52,27 @@ public class TestFileSignerSecretProvider {
     Assert.assertEquals(1, allSecrets.length);
     Assert.assertEquals(1, allSecrets.length);
     Assert.assertArrayEquals(secretValue.getBytes(), allSecrets[0]);
     Assert.assertArrayEquals(secretValue.getBytes(), allSecrets[0]);
   }
   }
+
+  @Test
+  public void testEmptySecretFileThrows() throws Exception {
+    File secretFile = File.createTempFile("test_empty_secret", ".txt");
+    assertTrue(secretFile.exists());
+
+    FileSignerSecretProvider secretProvider
+            = new FileSignerSecretProvider();
+    Properties secretProviderProps = new Properties();
+    secretProviderProps.setProperty(
+            AuthenticationFilter.SIGNATURE_SECRET_FILE,
+            secretFile.getAbsolutePath());
+
+    Exception exception =
+        assertThrows(RuntimeException.class, new ThrowingRunnable() {
+          @Override
+          public void run() throws Throwable {
+            secretProvider.init(secretProviderProps, null, -1);
+          }
+        });
+    assertTrue(exception.getMessage().startsWith(
+        "No secret in signature secret file:"));
+  }
 }
 }