KNOX-659 - Default Keystore Details in Pac4j Provider SAML Config to Gateway Identity
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/Pac4jMessages.java b/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/Pac4jMessages.java
index b3526ae..51be6a0 100644
--- a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/Pac4jMessages.java
+++ b/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/Pac4jMessages.java
@@ -40,4 +40,8 @@
 
   @Message( level = MessageLevel.ERROR, text = "Unable to generate a password for encryption")
   public void unableToGenerateAPasswordForEncryption(Exception e);
+
+  @Message( level = MessageLevel.INFO, text = 
+      "No private key passphrase alias found. Defaulting to master. Exception encountered: {0}")
+  public void noPrivateKeyPasshraseProvisioned(Exception e);
 }
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/filter/Pac4jDispatcherFilter.java b/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/filter/Pac4jDispatcherFilter.java
index 65a42cc..da446ab 100644
--- a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/filter/Pac4jDispatcherFilter.java
+++ b/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/filter/Pac4jDispatcherFilter.java
@@ -21,6 +21,8 @@
 import org.apache.hadoop.gateway.pac4j.Pac4jMessages;
 import org.apache.hadoop.gateway.pac4j.session.KnoxSessionStore;
 import org.apache.hadoop.gateway.services.GatewayServices;
+import org.apache.hadoop.gateway.services.security.KeystoreService;
+import org.apache.hadoop.gateway.services.security.MasterService;
 import org.apache.hadoop.gateway.services.security.AliasService;
 import org.apache.hadoop.gateway.services.security.AliasServiceException;
 import org.apache.hadoop.gateway.services.security.CryptoService;
@@ -73,20 +75,24 @@
   private CallbackFilter callbackFilter;
 
   private RequiresAuthenticationFilter requiresAuthenticationFilter;
+  private MasterService masterService = null;
+  private KeystoreService keystoreService = null;
+  private AliasService aliasService = null;
 
   @Override
   public void init( FilterConfig filterConfig ) throws ServletException {
     // JWT service
     final ServletContext context = filterConfig.getServletContext();
     CryptoService cryptoService = null;
-    AliasService aliasService = null;
     String clusterName = null;
     if (context != null) {
       GatewayServices services = (GatewayServices) context.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
       clusterName = (String) context.getAttribute(GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE);
       if (services != null) {
+        keystoreService = (KeystoreService) services.getService(GatewayServices.KEYSTORE_SERVICE);
         cryptoService = (CryptoService) services.getService(GatewayServices.CRYPTO_SERVICE);
         aliasService = (AliasService) services.getService(GatewayServices.ALIAS_SERVICE);
+        masterService = (MasterService) services.getService("MasterService");
       }
     }
     // crypto service, alias service and cluster name are mandatory
@@ -124,6 +130,7 @@
       // get clients from the init parameters
       final Map<String, String> properties = new HashMap<>();
       final Enumeration<String> names = filterConfig.getInitParameterNames();
+      addDefaultConfig(clientNameParameter, properties);
       while (names.hasMoreElements()) {
         final String key = names.nextElement();
         properties.put(key, filterConfig.getInitParameter(key));
@@ -152,6 +159,35 @@
     ConfigSingleton.setConfig(config);
   }
 
+  private void addDefaultConfig(String clientNameParameter, Map<String, String> properties) {
+    // add default saml params
+    if (clientNameParameter.contains("SAML2Client")) {
+      properties.put(PropertiesConfigFactory.SAML_KEYSTORE_PATH,
+          keystoreService.getKeystorePath());
+
+      properties.put(PropertiesConfigFactory.SAML_KEYSTORE_PASSWORD,
+          new String(masterService.getMasterSecret()));
+
+      // check for provisioned alias for private key
+      char[] gip = null;
+      try {
+        gip = aliasService.getGatewayIdentityPassphrase();
+      }
+      catch(AliasServiceException ase) {
+        log.noPrivateKeyPasshraseProvisioned(ase);
+      }
+      if (gip != null) {
+        properties.put(PropertiesConfigFactory.SAML_PRIVATE_KEY_PASSWORD,
+            new String(gip));
+      }
+      else {
+        // no alias provisioned then use the master
+        properties.put(PropertiesConfigFactory.SAML_PRIVATE_KEY_PASSWORD,
+            new String(masterService.getMasterSecret()));
+      }
+    }
+  }
+
   @Override
   public void doFilter( ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
 
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/DefaultGatewayServices.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/DefaultGatewayServices.java
index fe4125a..4455078 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/DefaultGatewayServices.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/DefaultGatewayServices.java
@@ -61,6 +61,7 @@
     ks = new DefaultKeystoreService();
     ks.setMasterService(ms);
     ks.init(config, options);
+    services.put(KEYSTORE_SERVICE, ks);
     
     DefaultAliasService alias = new DefaultAliasService();
     alias.setKeystoreService(ks);
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultKeystoreService.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultKeystoreService.java
index 8d91c65..4500230 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultKeystoreService.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultKeystoreService.java
@@ -48,7 +48,7 @@
 
   private static final String dnTemplate = "CN={0},OU=Test,O=Hadoop,L=Test,ST=Test,C=US";
   private static final String CREDENTIALS_SUFFIX = "-credentials.jceks";
-  private static final String GATEWAY_KEYSTORE = "gateway.jks";
+  public static final String GATEWAY_KEYSTORE = "gateway.jks";
   private static final String CERT_GEN_MODE = "hadoop.gateway.cert.gen.mode";
   private static final String CERT_GEN_MODE_LOCALHOST = "localhost";
   private static final String CERT_GEN_MODE_HOSTNAME = "hostname";
@@ -77,7 +77,7 @@
 
   @Override
   public void createKeystoreForGateway() throws KeystoreServiceException {
-    String filename = keyStoreDir + GATEWAY_KEYSTORE;
+    String filename = getKeystorePath();
     createKeystore(filename, "JKS");
   }
 
@@ -149,26 +149,30 @@
 
   @Override
   public boolean isCredentialStoreForClusterAvailable(String clusterName) throws KeystoreServiceException {
+    boolean rc = false;
     final File  keyStoreFile = new File( keyStoreDir + clusterName + CREDENTIALS_SUFFIX  );
     try {
-      return isKeystoreAvailable(keyStoreFile, "JCEKS");
+      rc = isKeystoreAvailable(keyStoreFile, "JCEKS");
     } catch (KeyStoreException e) {
       throw new KeystoreServiceException(e);
     } catch (IOException e) {
       throw new KeystoreServiceException(e);
     }
+    return rc;
   }
 
   @Override
   public boolean isKeystoreForGatewayAvailable() throws KeystoreServiceException {
+    boolean rc = false;
     final File  keyStoreFile = new File( keyStoreDir + GATEWAY_KEYSTORE  );
     try {
-      return isKeystoreAvailable(keyStoreFile, "JKS");
+      rc = isKeystoreAvailable(keyStoreFile, "JKS");
     } catch (KeyStoreException e) {
       throw new KeystoreServiceException(e);
     } catch (IOException e) {
       throw new KeystoreServiceException(e);
     }
+    return rc;
   }
 
   @Override
@@ -242,9 +246,7 @@
     return credential;
   }
 
-  /* (non-Javadoc)
-   * @see org.apache.hadoop.gateway.services.security.KeystoreService#removeCredentialForCluster(java.lang.String, java.lang.String, java.security.KeyStore)
-   */
+
   @Override
   public void removeCredentialForCluster(String clusterName, String alias) throws KeystoreServiceException {
     KeyStore ks = getCredentialStoreForCluster(clusterName);
@@ -262,4 +264,9 @@
       LOG.failedToRemoveCredentialForCluster(clusterName, e);
     }
   }
+
+  @Override
+  public String getKeystorePath() {
+    return keyStoreDir + GATEWAY_KEYSTORE;
+  }
 }
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreService.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreService.java
index 04a35f4..6ed8990 100644
--- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreService.java
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/KeystoreService.java
@@ -45,4 +45,6 @@
   public void removeCredentialForCluster(String clusterName, String alias) throws KeystoreServiceException;
 
   public char[] getCredentialForCluster(String clusterName, String alias) throws KeystoreServiceException;
+
+  public String getKeystorePath();
 }