You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by mo...@apache.org on 2017/09/01 13:17:07 UTC
[09/64] [partial] knox git commit: KNOX-998 - Refactoring save 1
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/filter/Pac4jDispatcherFilter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/filter/Pac4jDispatcherFilter.java b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/filter/Pac4jDispatcherFilter.java
new file mode 100644
index 0000000..a87c8d0
--- /dev/null
+++ b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/filter/Pac4jDispatcherFilter.java
@@ -0,0 +1,215 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.pac4j.filter;
+
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+import org.apache.knox.gateway.pac4j.Pac4jMessages;
+import org.apache.knox.gateway.pac4j.session.KnoxSessionStore;
+import org.apache.knox.gateway.services.GatewayServices;
+import org.apache.knox.gateway.services.security.KeystoreService;
+import org.apache.knox.gateway.services.security.MasterService;
+import org.apache.knox.gateway.services.security.AliasService;
+import org.apache.knox.gateway.services.security.AliasServiceException;
+import org.apache.knox.gateway.services.security.CryptoService;
+import org.pac4j.config.client.PropertiesConfigFactory;
+import org.pac4j.core.client.Client;
+import org.pac4j.core.config.Config;
+import org.pac4j.core.config.ConfigSingleton;
+import org.pac4j.core.context.J2EContext;
+import org.pac4j.core.context.Pac4jConstants;
+import org.pac4j.core.util.CommonHelper;
+import org.pac4j.http.client.indirect.IndirectBasicAuthClient;
+import org.pac4j.http.credentials.authenticator.test.SimpleTestUsernamePasswordAuthenticator;
+import org.pac4j.j2e.filter.CallbackFilter;
+import org.pac4j.j2e.filter.RequiresAuthenticationFilter;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>This is the main filter for the pac4j provider. The pac4j provider module heavily relies on the j2e-pac4j library (https://github.com/pac4j/j2e-pac4j).</p>
+ * <p>This filter dispatches the HTTP calls between the j2e-pac4j filters:</p>
+ * <ul>
+ * <li>to the {@link CallbackFilter} if the <code>client_name</code> parameter exists: it finishes the authentication process</li>
+ * <li>to the {@link RequiresAuthenticationFilter} otherwise: it starts the authentication process (redirection to the identity provider) if the user is not authenticated</li>
+ * </ul>
+ * <p>It uses the {@link KnoxSessionStore} to manage session data. The generated cookies are defined on a domain name
+ * which can be configured via the domain suffix parameter: <code>pac4j.cookie.domain.suffix</code>.</p>
+ * <p>The callback url must be defined to the current protected url (KnoxSSO service for example) via the parameter: <code>pac4j.callbackUrl</code>.</p>
+ *
+ * @since 0.8.0
+ */
+public class Pac4jDispatcherFilter implements Filter {
+
+ private static Pac4jMessages log = MessagesFactory.get(Pac4jMessages.class);
+
+ public static final String TEST_BASIC_AUTH = "testBasicAuth";
+
+ public static final String PAC4J_CALLBACK_URL = "pac4j.callbackUrl";
+
+ public static final String PAC4J_CALLBACK_PARAMETER = "pac4jCallback";
+
+ private static final String PAC4J_COOKIE_DOMAIN_SUFFIX_PARAM = "pac4j.cookie.domain.suffix";
+
+ 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;
+ 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
+ if (cryptoService == null || aliasService == null || clusterName == null) {
+ log.cryptoServiceAndAliasServiceAndClusterNameRequired();
+ throw new ServletException("The crypto service, alias service and cluster name are required.");
+ }
+ try {
+ aliasService.getPasswordFromAliasForCluster(clusterName, KnoxSessionStore.PAC4J_PASSWORD, true);
+ } catch (AliasServiceException e) {
+ log.unableToGenerateAPasswordForEncryption(e);
+ throw new ServletException("Unable to generate a password for encryption.");
+ }
+
+ // url to SSO authentication provider
+ String pac4jCallbackUrl = filterConfig.getInitParameter(PAC4J_CALLBACK_URL);
+ if (pac4jCallbackUrl == null) {
+ log.ssoAuthenticationProviderUrlRequired();
+ throw new ServletException("Required pac4j callback URL is missing.");
+ }
+ // add the callback parameter to know it's a callback
+ pac4jCallbackUrl = CommonHelper.addParameter(pac4jCallbackUrl, PAC4J_CALLBACK_PARAMETER, "true");
+
+ final Config config;
+ final String clientName;
+ // client name from servlet parameter (mandatory)
+ final String clientNameParameter = filterConfig.getInitParameter(Pac4jConstants.CLIENT_NAME);
+ if (clientNameParameter == null) {
+ log.clientNameParameterRequired();
+ throw new ServletException("Required pac4j clientName parameter is missing.");
+ }
+ if (TEST_BASIC_AUTH.equalsIgnoreCase(clientNameParameter)) {
+ // test configuration
+ final IndirectBasicAuthClient indirectBasicAuthClient = new IndirectBasicAuthClient(new SimpleTestUsernamePasswordAuthenticator());
+ indirectBasicAuthClient.setRealmName("Knox TEST");
+ config = new Config(pac4jCallbackUrl, indirectBasicAuthClient);
+ clientName = "IndirectBasicAuthClient";
+ } else {
+ // 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));
+ }
+ final PropertiesConfigFactory propertiesConfigFactory = new PropertiesConfigFactory(pac4jCallbackUrl, properties);
+ config = propertiesConfigFactory.build();
+ final List<Client> clients = config.getClients().getClients();
+ if (clients == null || clients.size() == 0) {
+ log.atLeastOnePac4jClientMustBeDefined();
+ throw new ServletException("At least one pac4j client must be defined.");
+ }
+ if (CommonHelper.isBlank(clientNameParameter)) {
+ clientName = clients.get(0).getName();
+ } else {
+ clientName = clientNameParameter;
+ }
+ }
+
+ callbackFilter = new CallbackFilter();
+ requiresAuthenticationFilter = new RequiresAuthenticationFilter();
+ requiresAuthenticationFilter.setClientName(clientName);
+ requiresAuthenticationFilter.setConfig(config);
+
+ final String domainSuffix = filterConfig.getInitParameter(PAC4J_COOKIE_DOMAIN_SUFFIX_PARAM);
+ config.setSessionStore(new KnoxSessionStore(cryptoService, clusterName, domainSuffix));
+ 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 {
+
+ final HttpServletRequest request = (HttpServletRequest) servletRequest;
+ final HttpServletResponse response = (HttpServletResponse) servletResponse;
+ final J2EContext context = new J2EContext(request, response, ConfigSingleton.getConfig().getSessionStore());
+
+ // it's a callback from an identity provider
+ if (request.getParameter(PAC4J_CALLBACK_PARAMETER) != null) {
+ // apply CallbackFilter
+ callbackFilter.doFilter(servletRequest, servletResponse, filterChain);
+ } else {
+ // otherwise just apply security and requires authentication
+ // apply RequiresAuthenticationFilter
+ requiresAuthenticationFilter.doFilter(servletRequest, servletResponse, filterChain);
+ }
+ }
+
+ @Override
+ public void destroy() { }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/filter/Pac4jIdentityAdapter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/filter/Pac4jIdentityAdapter.java b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/filter/Pac4jIdentityAdapter.java
new file mode 100644
index 0000000..87d0e8e
--- /dev/null
+++ b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/filter/Pac4jIdentityAdapter.java
@@ -0,0 +1,138 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.pac4j.filter;
+
+import org.apache.hadoop.gateway.audit.api.*;
+import org.apache.knox.gateway.audit.api.Action;
+import org.apache.knox.gateway.audit.api.ActionOutcome;
+import org.apache.knox.gateway.audit.api.Auditor;
+import org.apache.knox.gateway.audit.api.ResourceType;
+import org.apache.knox.gateway.audit.log4j.audit.AuditConstants;
+import org.apache.knox.gateway.filter.AbstractGatewayFilter;
+import org.apache.knox.gateway.security.PrimaryPrincipal;
+import org.apache.knox.gateway.audit.api.AuditService;
+import org.apache.knox.gateway.audit.api.AuditServiceFactory;
+import org.pac4j.core.config.ConfigSingleton;
+import org.pac4j.core.context.J2EContext;
+import org.pac4j.core.profile.ProfileManager;
+import org.pac4j.core.profile.UserProfile;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.security.auth.Subject;
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+/**
+ * <p>This filter retrieves the authenticated user saved by the pac4j provider and injects it into the J2E HTTP request.</p>
+ *
+ * @since 0.8.0
+ */
+public class Pac4jIdentityAdapter implements Filter {
+
+ private static final Logger logger = LoggerFactory.getLogger(Pac4jIdentityAdapter.class);
+
+ private static AuditService auditService = AuditServiceFactory.getAuditService();
+ private static Auditor auditor = auditService.getAuditor(
+ AuditConstants.DEFAULT_AUDITOR_NAME, AuditConstants.KNOX_SERVICE_NAME,
+ AuditConstants.KNOX_COMPONENT_NAME );
+
+ private String testIdentifier;
+
+ @Override
+ public void init( FilterConfig filterConfig ) throws ServletException {
+ }
+
+ public void destroy() {
+ }
+
+ public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
+ throws IOException, ServletException {
+
+ final HttpServletRequest request = (HttpServletRequest) servletRequest;
+ final HttpServletResponse response = (HttpServletResponse) servletResponse;
+ final J2EContext context = new J2EContext(request, response, ConfigSingleton.getConfig().getSessionStore());
+ final ProfileManager manager = new ProfileManager(context);
+ final UserProfile profile = manager.get(true);
+ logger.debug("User authenticated as: {}", profile);
+ manager.remove(true);
+ final String id = profile.getId();
+ testIdentifier = id;
+ PrimaryPrincipal pp = new PrimaryPrincipal(id);
+ Subject subject = new Subject();
+ subject.getPrincipals().add(pp);
+ auditService.getContext().setUsername(id);
+ String sourceUri = (String)request.getAttribute( AbstractGatewayFilter.SOURCE_REQUEST_CONTEXT_URL_ATTRIBUTE_NAME );
+ auditor.audit(Action.AUTHENTICATION, sourceUri, ResourceType.URI, ActionOutcome.SUCCESS);
+
+ doAs(request, response, chain, subject);
+ }
+
+ private void doAs(final ServletRequest request,
+ final ServletResponse response, final FilterChain chain, Subject subject)
+ throws IOException, ServletException {
+ try {
+ Subject.doAs(
+ subject,
+ new PrivilegedExceptionAction<Object>() {
+ public Object run() throws Exception {
+ chain.doFilter(request, response);
+ return null;
+ }
+ }
+ );
+ }
+ catch (PrivilegedActionException e) {
+ Throwable t = e.getCause();
+ if (t instanceof IOException) {
+ throw (IOException) t;
+ }
+ else if (t instanceof ServletException) {
+ throw (ServletException) t;
+ }
+ else {
+ throw new ServletException(t);
+ }
+ }
+ }
+
+ /**
+ * For tests only.
+ */
+ public static void setAuditService(AuditService auditService) {
+ Pac4jIdentityAdapter.auditService = auditService;
+ }
+
+ /**
+ * For tests only.
+ */
+ public static void setAuditor(Auditor auditor) {
+ Pac4jIdentityAdapter.auditor = auditor;
+ }
+
+ /**
+ * For tests only.
+ */
+ public String getTestIdentifier() {
+ return testIdentifier;
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/session/KnoxSessionStore.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/session/KnoxSessionStore.java b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/session/KnoxSessionStore.java
new file mode 100644
index 0000000..6ce002c
--- /dev/null
+++ b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/session/KnoxSessionStore.java
@@ -0,0 +1,120 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.pac4j.session;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.knox.gateway.services.security.CryptoService;
+import org.apache.knox.gateway.services.security.EncryptionResult;
+import org.apache.knox.gateway.util.Urls;
+import org.pac4j.core.context.ContextHelper;
+import org.pac4j.core.context.Cookie;
+import org.pac4j.core.context.WebContext;
+import org.pac4j.core.context.session.SessionStore;
+import org.pac4j.core.exception.TechnicalException;
+import org.pac4j.core.util.JavaSerializationHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.Serializable;
+
+/**
+ * Specific session store where data are saved into cookies (and not in memory).
+ * Each data is encrypted and base64 encoded before being saved as a cookie (for security reasons).
+ *
+ * @since 0.8.0
+ */
+public class KnoxSessionStore implements SessionStore {
+
+ private static final Logger logger = LoggerFactory.getLogger(KnoxSessionStore.class);
+
+ public static final String PAC4J_PASSWORD = "pac4j.password";
+
+ public static final String PAC4J_SESSION_PREFIX = "pac4j.session.";
+
+ private final JavaSerializationHelper javaSerializationHelper;
+
+ private final CryptoService cryptoService;
+
+ private final String clusterName;
+
+ private final String domainSuffix;
+
+ public KnoxSessionStore(final CryptoService cryptoService, final String clusterName, final String domainSuffix) {
+ javaSerializationHelper = new JavaSerializationHelper();
+ this.cryptoService = cryptoService;
+ this.clusterName = clusterName;
+ this.domainSuffix = domainSuffix;
+ }
+
+ public String getOrCreateSessionId(WebContext context) {
+ return null;
+ }
+
+ private Serializable decryptBase64(final String v) {
+ if (v != null && v.length() > 0) {
+ byte[] bytes = Base64.decodeBase64(v);
+ EncryptionResult result = EncryptionResult.fromByteArray(bytes);
+ byte[] clear = cryptoService.decryptForCluster(this.clusterName,
+ PAC4J_PASSWORD,
+ result.cipher,
+ result.iv,
+ result.salt);
+ if (clear != null) {
+ return javaSerializationHelper.unserializeFromBytes(clear);
+ }
+ }
+ return null;
+ }
+
+ public Object get(WebContext context, String key) {
+ final Cookie cookie = ContextHelper.getCookie(context, PAC4J_SESSION_PREFIX + key);
+ Object value = null;
+ if (cookie != null) {
+ value = decryptBase64(cookie.getValue());
+ }
+ logger.debug("Get from session: {} = {}", key, value);
+ return value;
+ }
+
+ private String encryptBase64(final Object o) {
+ if (o == null || o.equals("")) {
+ return null;
+ } else {
+ final byte[] bytes = javaSerializationHelper.serializeToBytes((Serializable) o);
+ EncryptionResult result = cryptoService.encryptForCluster(this.clusterName, PAC4J_PASSWORD, bytes);
+ return Base64.encodeBase64String(result.toByteAray());
+ }
+ }
+
+ public void set(WebContext context, String key, Object value) {
+ logger.debug("Save in session: {} = {}", key, value);
+ final Cookie cookie = new Cookie(PAC4J_SESSION_PREFIX + key, encryptBase64(value));
+ try {
+ String domain = Urls.getDomainName(context.getFullRequestURL(), this.domainSuffix);
+ if (domain == null) {
+ domain = context.getServerName();
+ }
+ cookie.setDomain(domain);
+ } catch (final Exception e) {
+ throw new TechnicalException(e);
+ }
+ cookie.setHttpOnly(true);
+ cookie.setSecure(ContextHelper.isHttpsOrSecure(context));
+ context.addResponseCookie(cookie);
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor b/gateway-provider-security-pac4j/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor
deleted file mode 100644
index 8cde74f..0000000
--- a/gateway-provider-security-pac4j/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor
+++ /dev/null
@@ -1,19 +0,0 @@
-##########################################################################
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-##########################################################################
-
-org.apache.hadoop.gateway.pac4j.deploy.Pac4jFederationProviderContributor
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/main/resources/META-INF/services/org.apache.knox.gateway.deploy.ProviderDeploymentContributor
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/resources/META-INF/services/org.apache.knox.gateway.deploy.ProviderDeploymentContributor b/gateway-provider-security-pac4j/src/main/resources/META-INF/services/org.apache.knox.gateway.deploy.ProviderDeploymentContributor
new file mode 100644
index 0000000..a195d77
--- /dev/null
+++ b/gateway-provider-security-pac4j/src/main/resources/META-INF/services/org.apache.knox.gateway.deploy.ProviderDeploymentContributor
@@ -0,0 +1,19 @@
+##########################################################################
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+##########################################################################
+
+org.apache.knox.gateway.pac4j.deploy.Pac4jFederationProviderContributor
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/test/java/org/apache/hadoop/gateway/pac4j/MockHttpServletRequest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/test/java/org/apache/hadoop/gateway/pac4j/MockHttpServletRequest.java b/gateway-provider-security-pac4j/src/test/java/org/apache/hadoop/gateway/pac4j/MockHttpServletRequest.java
deleted file mode 100644
index b09adc9..0000000
--- a/gateway-provider-security-pac4j/src/test/java/org/apache/hadoop/gateway/pac4j/MockHttpServletRequest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.gateway.pac4j;
-
-import javax.servlet.http.*;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.mockito.Mockito.*;
-
-public class MockHttpServletRequest extends HttpServletRequestWrapper {
-
- private String requestUrl;
- private Cookie[] cookies;
- private String serverName;
- private Map<String, String> parameters = new HashMap<>();
- private Map<String, String> headers = new HashMap<>();
-
- public MockHttpServletRequest() {
- super(mock(HttpServletRequest.class));
- }
-
- @Override
- public Cookie[] getCookies() {
- return cookies;
- }
-
- public void setCookies(final Cookie[] cookies) {
- this.cookies = cookies;
- }
-
- @Override
- public StringBuffer getRequestURL() {
- return new StringBuffer(requestUrl);
- }
-
- public void setRequestURL(final String requestUrl) {
- this.requestUrl = requestUrl;
- }
-
- @Override
- public String getServerName() {
- return serverName;
- }
-
- public void setServerName(final String serverName) {
- this.serverName = serverName;
- }
-
- @Override
- public String getParameter(String name) {
- return parameters.get(name);
- }
-
- public void addParameter(String key, String value) {
- parameters.put(key, value);
- }
-
- @Override
- public String getHeader(String name) {
- return headers.get(name);
- }
-
- public void addHeader(String key, String value) {
- headers.put(key, value);
- }
-
- @Override
- public Object getAttribute(String name) {
- return null;
- }
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/test/java/org/apache/hadoop/gateway/pac4j/MockHttpServletResponse.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/test/java/org/apache/hadoop/gateway/pac4j/MockHttpServletResponse.java b/gateway-provider-security-pac4j/src/test/java/org/apache/hadoop/gateway/pac4j/MockHttpServletResponse.java
deleted file mode 100644
index 11d104c..0000000
--- a/gateway-provider-security-pac4j/src/test/java/org/apache/hadoop/gateway/pac4j/MockHttpServletResponse.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.hadoop.gateway.pac4j;
-
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpServletResponseWrapper;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.mockito.Mockito.*;
-
-public class MockHttpServletResponse extends HttpServletResponseWrapper {
-
- private List<Cookie> cookies = new ArrayList<>();
- private String location;
- private int status = 0;
- private Map<String, String> headers = new HashMap<>();
-
- public MockHttpServletResponse() {
- super(mock(HttpServletResponse.class));
- }
-
- @Override
- public void setHeader(String name, String value) {
- headers.put(name, value);
- }
-
- @Override
- public void addHeader(String name, String value) {
- headers.put(name, value);
- }
-
- public Map<String, String> getHeaders() {
- return headers;
- }
-
- @Override
- public void addCookie(Cookie cookie) {
- cookies.add(cookie);
- }
-
- public List<Cookie> getCookies() {
- return cookies;
- }
-
- @Override
- public void sendRedirect(String location) throws IOException {
- setStatus(302);
- setHeader("Location", location);
- }
-
- @Override
- public void setStatus(int sc) {
- status = sc;
- }
-
- @Override
- public int getStatus() {
- return status;
- }
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/test/java/org/apache/hadoop/gateway/pac4j/Pac4jProviderTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/test/java/org/apache/hadoop/gateway/pac4j/Pac4jProviderTest.java b/gateway-provider-security-pac4j/src/test/java/org/apache/hadoop/gateway/pac4j/Pac4jProviderTest.java
deleted file mode 100644
index 60bf6f8..0000000
--- a/gateway-provider-security-pac4j/src/test/java/org/apache/hadoop/gateway/pac4j/Pac4jProviderTest.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.gateway.pac4j;
-
-import org.apache.hadoop.gateway.audit.api.AuditContext;
-import org.apache.hadoop.gateway.audit.api.AuditService;
-import org.apache.hadoop.gateway.audit.api.Auditor;
-import org.apache.hadoop.gateway.pac4j.filter.Pac4jDispatcherFilter;
-import org.apache.hadoop.gateway.pac4j.filter.Pac4jIdentityAdapter;
-import org.apache.hadoop.gateway.pac4j.session.KnoxSessionStore;
-import org.apache.hadoop.gateway.services.GatewayServices;
-import org.apache.hadoop.gateway.services.security.AliasService;
-import org.apache.hadoop.gateway.services.security.impl.DefaultCryptoService;
-import org.junit.Test;
-import org.pac4j.core.client.Clients;
-import org.pac4j.core.context.Pac4jConstants;
-import org.pac4j.http.client.indirect.IndirectBasicAuthClient;
-
-import javax.servlet.*;
-import javax.servlet.http.*;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import static org.mockito.Mockito.*;
-import static org.junit.Assert.*;
-
-/**
- * This class simulates a full authentication process using pac4j.
- */
-public class Pac4jProviderTest {
-
- private static final String LOCALHOST = "127.0.0.1";
- private static final String HADOOP_SERVICE_URL = "https://" + LOCALHOST + ":8443/gateway/sandox/webhdfs/v1/tmp?op=LISTSTATUS";
- private static final String KNOXSSO_SERVICE_URL = "https://" + LOCALHOST + ":8443/gateway/idp/api/v1/websso";
- private static final String PAC4J_CALLBACK_URL = KNOXSSO_SERVICE_URL;
- private static final String ORIGINAL_URL = "originalUrl";
- private static final String CLUSTER_NAME = "knox";
- private static final String PAC4J_PASSWORD = "pwdfortest";
- private static final String CLIENT_CLASS = IndirectBasicAuthClient.class.getSimpleName();
- private static final String USERNAME = "jleleu";
-
- @Test
- public void test() throws Exception {
- final AliasService aliasService = mock(AliasService.class);
- when(aliasService.getPasswordFromAliasForCluster(CLUSTER_NAME, KnoxSessionStore.PAC4J_PASSWORD, true)).thenReturn(PAC4J_PASSWORD.toCharArray());
- when(aliasService.getPasswordFromAliasForCluster(CLUSTER_NAME, KnoxSessionStore.PAC4J_PASSWORD)).thenReturn(PAC4J_PASSWORD.toCharArray());
-
- final DefaultCryptoService cryptoService = new DefaultCryptoService();
- cryptoService.setAliasService(aliasService);
-
- final GatewayServices services = mock(GatewayServices.class);
- when(services.getService(GatewayServices.CRYPTO_SERVICE)).thenReturn(cryptoService);
- when(services.getService(GatewayServices.ALIAS_SERVICE)).thenReturn(aliasService);
-
- final ServletContext context = mock(ServletContext.class);
- when(context.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE)).thenReturn(services);
- when(context.getAttribute(GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE)).thenReturn(CLUSTER_NAME);
-
- final FilterConfig config = mock(FilterConfig.class);
- when(config.getServletContext()).thenReturn(context);
- when(config.getInitParameter(Pac4jDispatcherFilter.PAC4J_CALLBACK_URL)).thenReturn(PAC4J_CALLBACK_URL);
- when(config.getInitParameter(Pac4jConstants.CLIENT_NAME)).thenReturn(Pac4jDispatcherFilter.TEST_BASIC_AUTH);
-
- final Pac4jDispatcherFilter dispatcher = new Pac4jDispatcherFilter();
- dispatcher.init(config);
- final Pac4jIdentityAdapter adapter = new Pac4jIdentityAdapter();
- adapter.init(config);
- adapter.setAuditor(mock(Auditor.class));
- final AuditService auditService = mock(AuditService.class);
- when(auditService.getContext()).thenReturn(mock(AuditContext.class));
- adapter.setAuditService(auditService);
-
- // step 1: call the KnoxSSO service with an original url pointing to an Hadoop service (redirected by the SSOCookieProvider)
- MockHttpServletRequest request = new MockHttpServletRequest();
- request.setRequestURL(KNOXSSO_SERVICE_URL + "?" + ORIGINAL_URL + "=" + HADOOP_SERVICE_URL);
- request.setCookies(new Cookie[0]);
- request.setServerName(LOCALHOST);
- MockHttpServletResponse response = new MockHttpServletResponse();
- FilterChain filterChain = mock(FilterChain.class);
- dispatcher.doFilter(request, response, filterChain);
- // it should be a redirection to the idp topology
- assertEquals(302, response.getStatus());
- assertEquals(PAC4J_CALLBACK_URL + "?" + Pac4jDispatcherFilter.PAC4J_CALLBACK_PARAMETER + "=true&" + Clients.DEFAULT_CLIENT_NAME_PARAMETER + "=" + CLIENT_CLASS, response.getHeaders().get("Location"));
- // we should have one cookie for the saved requested url
- List<Cookie> cookies = response.getCookies();
- assertEquals(1, cookies.size());
- final Cookie requestedUrlCookie = cookies.get(0);
- assertEquals(KnoxSessionStore.PAC4J_SESSION_PREFIX + Pac4jConstants.REQUESTED_URL, requestedUrlCookie.getName());
-
- // step 2: send credentials to the callback url (callback from the identity provider)
- request = new MockHttpServletRequest();
- request.setCookies(new Cookie[]{requestedUrlCookie});
- request.setRequestURL(PAC4J_CALLBACK_URL + "?" + Pac4jDispatcherFilter.PAC4J_CALLBACK_PARAMETER + "=true&" + Clients.DEFAULT_CLIENT_NAME_PARAMETER + "=" + Clients.DEFAULT_CLIENT_NAME_PARAMETER + "=" + CLIENT_CLASS);
- request.addParameter(Pac4jDispatcherFilter.PAC4J_CALLBACK_PARAMETER, "true");
- request.addParameter(Clients.DEFAULT_CLIENT_NAME_PARAMETER, CLIENT_CLASS);
- request.addHeader("Authorization", "Basic amxlbGV1OmpsZWxldQ==");
- request.setServerName(LOCALHOST);
- response = new MockHttpServletResponse();
- filterChain = mock(FilterChain.class);
- dispatcher.doFilter(request, response, filterChain);
- // it should be a redirection to the original url
- assertEquals(302, response.getStatus());
- assertEquals(KNOXSSO_SERVICE_URL + "?" + ORIGINAL_URL + "=" + HADOOP_SERVICE_URL, response.getHeaders().get("Location"));
- // we should have 3 cookies among with the user profile
- cookies = response.getCookies();
- Map<String, String> mapCookies = new HashMap<>();
- assertEquals(3, cookies.size());
- for (final Cookie cookie : cookies) {
- mapCookies.put(cookie.getName(), cookie.getValue());
- }
- assertNull(mapCookies.get(KnoxSessionStore.PAC4J_SESSION_PREFIX + CLIENT_CLASS + "$attemptedAuthentication"));
- assertNotNull(mapCookies.get(KnoxSessionStore.PAC4J_SESSION_PREFIX + Pac4jConstants.USER_PROFILE));
- assertNull(mapCookies.get(KnoxSessionStore.PAC4J_SESSION_PREFIX + Pac4jConstants.REQUESTED_URL));
-
- // step 3: turn pac4j identity into KnoxSSO identity
- request = new MockHttpServletRequest();
- request.setCookies(cookies.toArray(new Cookie[cookies.size()]));
- request.setRequestURL(KNOXSSO_SERVICE_URL + "?" + ORIGINAL_URL + "=" + HADOOP_SERVICE_URL);
- request.setServerName(LOCALHOST);
- response = new MockHttpServletResponse();
- filterChain = mock(FilterChain.class);
- dispatcher.doFilter(request, response, filterChain);
- assertEquals(0, response.getStatus());
- adapter.doFilter(request, response, filterChain);
- cookies = response.getCookies();
- assertEquals(1, cookies.size());
- final Cookie userProfileCookie = cookies.get(0);
- // the user profile has been cleaned
- assertEquals(KnoxSessionStore.PAC4J_SESSION_PREFIX + Pac4jConstants.USER_PROFILE, userProfileCookie.getName());
- assertNull(userProfileCookie.getValue());
- assertEquals(USERNAME, adapter.getTestIdentifier());
- }
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/test/java/org/apache/knox/gateway/pac4j/MockHttpServletRequest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/test/java/org/apache/knox/gateway/pac4j/MockHttpServletRequest.java b/gateway-provider-security-pac4j/src/test/java/org/apache/knox/gateway/pac4j/MockHttpServletRequest.java
new file mode 100644
index 0000000..7a3a833
--- /dev/null
+++ b/gateway-provider-security-pac4j/src/test/java/org/apache/knox/gateway/pac4j/MockHttpServletRequest.java
@@ -0,0 +1,88 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.pac4j;
+
+import javax.servlet.http.*;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import static org.mockito.Mockito.*;
+
+public class MockHttpServletRequest extends HttpServletRequestWrapper {
+
+ private String requestUrl;
+ private Cookie[] cookies;
+ private String serverName;
+ private Map<String, String> parameters = new HashMap<>();
+ private Map<String, String> headers = new HashMap<>();
+
+ public MockHttpServletRequest() {
+ super(mock(HttpServletRequest.class));
+ }
+
+ @Override
+ public Cookie[] getCookies() {
+ return cookies;
+ }
+
+ public void setCookies(final Cookie[] cookies) {
+ this.cookies = cookies;
+ }
+
+ @Override
+ public StringBuffer getRequestURL() {
+ return new StringBuffer(requestUrl);
+ }
+
+ public void setRequestURL(final String requestUrl) {
+ this.requestUrl = requestUrl;
+ }
+
+ @Override
+ public String getServerName() {
+ return serverName;
+ }
+
+ public void setServerName(final String serverName) {
+ this.serverName = serverName;
+ }
+
+ @Override
+ public String getParameter(String name) {
+ return parameters.get(name);
+ }
+
+ public void addParameter(String key, String value) {
+ parameters.put(key, value);
+ }
+
+ @Override
+ public String getHeader(String name) {
+ return headers.get(name);
+ }
+
+ public void addHeader(String key, String value) {
+ headers.put(key, value);
+ }
+
+ @Override
+ public Object getAttribute(String name) {
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/test/java/org/apache/knox/gateway/pac4j/MockHttpServletResponse.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/test/java/org/apache/knox/gateway/pac4j/MockHttpServletResponse.java b/gateway-provider-security-pac4j/src/test/java/org/apache/knox/gateway/pac4j/MockHttpServletResponse.java
new file mode 100644
index 0000000..07dd255
--- /dev/null
+++ b/gateway-provider-security-pac4j/src/test/java/org/apache/knox/gateway/pac4j/MockHttpServletResponse.java
@@ -0,0 +1,82 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.knox.gateway.pac4j;
+
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.mockito.Mockito.*;
+
+public class MockHttpServletResponse extends HttpServletResponseWrapper {
+
+ private List<Cookie> cookies = new ArrayList<>();
+ private String location;
+ private int status = 0;
+ private Map<String, String> headers = new HashMap<>();
+
+ public MockHttpServletResponse() {
+ super(mock(HttpServletResponse.class));
+ }
+
+ @Override
+ public void setHeader(String name, String value) {
+ headers.put(name, value);
+ }
+
+ @Override
+ public void addHeader(String name, String value) {
+ headers.put(name, value);
+ }
+
+ public Map<String, String> getHeaders() {
+ return headers;
+ }
+
+ @Override
+ public void addCookie(Cookie cookie) {
+ cookies.add(cookie);
+ }
+
+ public List<Cookie> getCookies() {
+ return cookies;
+ }
+
+ @Override
+ public void sendRedirect(String location) throws IOException {
+ setStatus(302);
+ setHeader("Location", location);
+ }
+
+ @Override
+ public void setStatus(int sc) {
+ status = sc;
+ }
+
+ @Override
+ public int getStatus() {
+ return status;
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/test/java/org/apache/knox/gateway/pac4j/Pac4jProviderTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/test/java/org/apache/knox/gateway/pac4j/Pac4jProviderTest.java b/gateway-provider-security-pac4j/src/test/java/org/apache/knox/gateway/pac4j/Pac4jProviderTest.java
new file mode 100644
index 0000000..606d042
--- /dev/null
+++ b/gateway-provider-security-pac4j/src/test/java/org/apache/knox/gateway/pac4j/Pac4jProviderTest.java
@@ -0,0 +1,150 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.pac4j;
+
+import org.apache.knox.gateway.audit.api.AuditContext;
+import org.apache.knox.gateway.audit.api.AuditService;
+import org.apache.knox.gateway.audit.api.Auditor;
+import org.apache.knox.gateway.pac4j.filter.Pac4jDispatcherFilter;
+import org.apache.knox.gateway.pac4j.filter.Pac4jIdentityAdapter;
+import org.apache.knox.gateway.pac4j.session.KnoxSessionStore;
+import org.apache.knox.gateway.services.GatewayServices;
+import org.apache.knox.gateway.services.security.AliasService;
+import org.apache.knox.gateway.services.security.impl.DefaultCryptoService;
+import org.junit.Test;
+import org.pac4j.core.client.Clients;
+import org.pac4j.core.context.Pac4jConstants;
+import org.pac4j.http.client.indirect.IndirectBasicAuthClient;
+
+import javax.servlet.*;
+import javax.servlet.http.*;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.mockito.Mockito.*;
+import static org.junit.Assert.*;
+
+/**
+ * This class simulates a full authentication process using pac4j.
+ */
+public class Pac4jProviderTest {
+
+ private static final String LOCALHOST = "127.0.0.1";
+ private static final String HADOOP_SERVICE_URL = "https://" + LOCALHOST + ":8443/gateway/sandox/webhdfs/v1/tmp?op=LISTSTATUS";
+ private static final String KNOXSSO_SERVICE_URL = "https://" + LOCALHOST + ":8443/gateway/idp/api/v1/websso";
+ private static final String PAC4J_CALLBACK_URL = KNOXSSO_SERVICE_URL;
+ private static final String ORIGINAL_URL = "originalUrl";
+ private static final String CLUSTER_NAME = "knox";
+ private static final String PAC4J_PASSWORD = "pwdfortest";
+ private static final String CLIENT_CLASS = IndirectBasicAuthClient.class.getSimpleName();
+ private static final String USERNAME = "jleleu";
+
+ @Test
+ public void test() throws Exception {
+ final AliasService aliasService = mock(AliasService.class);
+ when(aliasService.getPasswordFromAliasForCluster(CLUSTER_NAME, KnoxSessionStore.PAC4J_PASSWORD, true)).thenReturn(PAC4J_PASSWORD.toCharArray());
+ when(aliasService.getPasswordFromAliasForCluster(CLUSTER_NAME, KnoxSessionStore.PAC4J_PASSWORD)).thenReturn(PAC4J_PASSWORD.toCharArray());
+
+ final DefaultCryptoService cryptoService = new DefaultCryptoService();
+ cryptoService.setAliasService(aliasService);
+
+ final GatewayServices services = mock(GatewayServices.class);
+ when(services.getService(GatewayServices.CRYPTO_SERVICE)).thenReturn(cryptoService);
+ when(services.getService(GatewayServices.ALIAS_SERVICE)).thenReturn(aliasService);
+
+ final ServletContext context = mock(ServletContext.class);
+ when(context.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE)).thenReturn(services);
+ when(context.getAttribute(GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE)).thenReturn(CLUSTER_NAME);
+
+ final FilterConfig config = mock(FilterConfig.class);
+ when(config.getServletContext()).thenReturn(context);
+ when(config.getInitParameter(Pac4jDispatcherFilter.PAC4J_CALLBACK_URL)).thenReturn(PAC4J_CALLBACK_URL);
+ when(config.getInitParameter(Pac4jConstants.CLIENT_NAME)).thenReturn(Pac4jDispatcherFilter.TEST_BASIC_AUTH);
+
+ final Pac4jDispatcherFilter dispatcher = new Pac4jDispatcherFilter();
+ dispatcher.init(config);
+ final Pac4jIdentityAdapter adapter = new Pac4jIdentityAdapter();
+ adapter.init(config);
+ adapter.setAuditor(mock(Auditor.class));
+ final AuditService auditService = mock(AuditService.class);
+ when(auditService.getContext()).thenReturn(mock(AuditContext.class));
+ adapter.setAuditService(auditService);
+
+ // step 1: call the KnoxSSO service with an original url pointing to an Hadoop service (redirected by the SSOCookieProvider)
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setRequestURL(KNOXSSO_SERVICE_URL + "?" + ORIGINAL_URL + "=" + HADOOP_SERVICE_URL);
+ request.setCookies(new Cookie[0]);
+ request.setServerName(LOCALHOST);
+ MockHttpServletResponse response = new MockHttpServletResponse();
+ FilterChain filterChain = mock(FilterChain.class);
+ dispatcher.doFilter(request, response, filterChain);
+ // it should be a redirection to the idp topology
+ assertEquals(302, response.getStatus());
+ assertEquals(PAC4J_CALLBACK_URL + "?" + Pac4jDispatcherFilter.PAC4J_CALLBACK_PARAMETER + "=true&" + Clients.DEFAULT_CLIENT_NAME_PARAMETER + "=" + CLIENT_CLASS, response.getHeaders().get("Location"));
+ // we should have one cookie for the saved requested url
+ List<Cookie> cookies = response.getCookies();
+ assertEquals(1, cookies.size());
+ final Cookie requestedUrlCookie = cookies.get(0);
+ assertEquals(KnoxSessionStore.PAC4J_SESSION_PREFIX + Pac4jConstants.REQUESTED_URL, requestedUrlCookie.getName());
+
+ // step 2: send credentials to the callback url (callback from the identity provider)
+ request = new MockHttpServletRequest();
+ request.setCookies(new Cookie[]{requestedUrlCookie});
+ request.setRequestURL(PAC4J_CALLBACK_URL + "?" + Pac4jDispatcherFilter.PAC4J_CALLBACK_PARAMETER + "=true&" + Clients.DEFAULT_CLIENT_NAME_PARAMETER + "=" + Clients.DEFAULT_CLIENT_NAME_PARAMETER + "=" + CLIENT_CLASS);
+ request.addParameter(Pac4jDispatcherFilter.PAC4J_CALLBACK_PARAMETER, "true");
+ request.addParameter(Clients.DEFAULT_CLIENT_NAME_PARAMETER, CLIENT_CLASS);
+ request.addHeader("Authorization", "Basic amxlbGV1OmpsZWxldQ==");
+ request.setServerName(LOCALHOST);
+ response = new MockHttpServletResponse();
+ filterChain = mock(FilterChain.class);
+ dispatcher.doFilter(request, response, filterChain);
+ // it should be a redirection to the original url
+ assertEquals(302, response.getStatus());
+ assertEquals(KNOXSSO_SERVICE_URL + "?" + ORIGINAL_URL + "=" + HADOOP_SERVICE_URL, response.getHeaders().get("Location"));
+ // we should have 3 cookies among with the user profile
+ cookies = response.getCookies();
+ Map<String, String> mapCookies = new HashMap<>();
+ assertEquals(3, cookies.size());
+ for (final Cookie cookie : cookies) {
+ mapCookies.put(cookie.getName(), cookie.getValue());
+ }
+ assertNull(mapCookies.get(KnoxSessionStore.PAC4J_SESSION_PREFIX + CLIENT_CLASS + "$attemptedAuthentication"));
+ assertNotNull(mapCookies.get(KnoxSessionStore.PAC4J_SESSION_PREFIX + Pac4jConstants.USER_PROFILE));
+ assertNull(mapCookies.get(KnoxSessionStore.PAC4J_SESSION_PREFIX + Pac4jConstants.REQUESTED_URL));
+
+ // step 3: turn pac4j identity into KnoxSSO identity
+ request = new MockHttpServletRequest();
+ request.setCookies(cookies.toArray(new Cookie[cookies.size()]));
+ request.setRequestURL(KNOXSSO_SERVICE_URL + "?" + ORIGINAL_URL + "=" + HADOOP_SERVICE_URL);
+ request.setServerName(LOCALHOST);
+ response = new MockHttpServletResponse();
+ filterChain = mock(FilterChain.class);
+ dispatcher.doFilter(request, response, filterChain);
+ assertEquals(0, response.getStatus());
+ adapter.doFilter(request, response, filterChain);
+ cookies = response.getCookies();
+ assertEquals(1, cookies.size());
+ final Cookie userProfileCookie = cookies.get(0);
+ // the user profile has been cleaned
+ assertEquals(KnoxSessionStore.PAC4J_SESSION_PREFIX + Pac4jConstants.USER_PROFILE, userProfileCookie.getName());
+ assertNull(userProfileCookie.getValue());
+ assertEquals(USERNAME, adapter.getTestIdentifier());
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/PicketlinkMessages.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/PicketlinkMessages.java b/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/PicketlinkMessages.java
deleted file mode 100644
index c49030f..0000000
--- a/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/PicketlinkMessages.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.gateway.picketlink;
-
-import org.apache.hadoop.gateway.i18n.messages.Message;
-import org.apache.hadoop.gateway.i18n.messages.MessageLevel;
-import org.apache.hadoop.gateway.i18n.messages.Messages;
-import org.apache.hadoop.gateway.i18n.messages.StackTrace;
-
-@Messages(logger="org.apache.hadoop.gateway.picketlink")
-public interface PicketlinkMessages {
-
- @Message( level = MessageLevel.DEBUG, text = "Found Original URL in reequest: {0}")
- public void foundOriginalURLInRequest(String url);
-
- @Message( level = MessageLevel.DEBUG, text = "setting cookie for original-url")
- public void settingCookieForOriginalURL();
-
- @Message( level = MessageLevel.DEBUG, text = "Secure Flag is set to False for cookie")
- public void secureFlagFalseForCookie();
-
- @Message( level = MessageLevel.ERROR, text = "Unable to get the gateway identity passphrase: {0}")
- public void unableToGetGatewayIdentityPassphrase(@StackTrace( level = MessageLevel.DEBUG) Exception e);
-
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/deploy/PicketlinkConf.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/deploy/PicketlinkConf.java b/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/deploy/PicketlinkConf.java
deleted file mode 100644
index 59203c6..0000000
--- a/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/deploy/PicketlinkConf.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.gateway.picketlink.deploy;
-
-/**
- * Provides a serializable configuration file for adding to
- * the webapp as an XML string for picketlink.xml
- *
- */
-public class PicketlinkConf {
- public static final String INDENT = " ";
- public static final String LT_OPEN = "<";
- public static final String LT_CLOSE = "</";
- public static final String GT = ">";
- public static final String GT_CLOSE = "/>";
- public static final String NL = "\n";
- public static final String PICKETLINK_XMLNS = "urn:picketlink:identity-federation:config:2.1";
- public static final String PICKETLINK_SP_XMLNS = "urn:picketlink:identity-federation:config:1.0";
- public static final String C14N_METHOD = "http://www.w3.org/2001/10/xml-exc-c14n#";
- public static final String KEYPROVIDER_ELEMENT = "KeyProvider";
- public static final String KEYPROVIDER_CLASSNAME = "org.picketlink.identity.federation.core.impl.KeyStoreKeyManager";
- public static final String AUTH_HANDLER_CLASSNAME = "org.picketlink.identity.federation.web.handlers.saml2.SAML2AuthenticationHandler";
- public static final String ROLE_GEN_HANDLER_CLASSNAME = "org.picketlink.identity.federation.web.handlers.saml2.RolesGenerationHandler";
- public static final String PICKETLINK_ELEMENT = "PicketLink";
- public static final String PICKETLINKSP_ELEMENT = "PicketLinkSP";
- public static final String HANDLERS_ELEMENT = "Handlers";
- public static final String HANDLER_ELEMENT = "Handler";
- public static final String OPTION_ELEMENT = "Option";
- public static final String VAL_ALIAS_ELEMENT = "ValidatingAlias";
- public static final String AUTH_ELEMENT = "Auth";
-
- private String serverEnvironment = "jetty";
- private String bindingType = "POST";
- private String idpUsesPostingBinding = "true";
- private String supportsSignatures = "true";
- private String identityURL = null;
- private String serviceURL = null;
- private String keystoreURL = null;
- private String keystorePass = null;
- private String signingKeyAlias = null;
- private String signingKeyPass = null;
- private String validatingKeyAlias = null;
- private String validatingKeyValue = null;
- private String nameIDFormat = "urn:oasis:names:tc:SAML:2.0:nameid-format:persistent";
- private String clockSkewMilis = null;
- private String assertionSessionAttributeName = "org.picketlink.sp.assertion";
-
- public String getServerEnvironment() {
- return serverEnvironment;
- }
- public void setServerEnvironment(String serverEnvironment) {
- this.serverEnvironment = serverEnvironment;
- }
- public String getBindingType() {
- return bindingType;
- }
- public void setBindingType(String bindingType) {
- this.bindingType = bindingType;
- }
- public String getIdpUsesPostingBinding() {
- return idpUsesPostingBinding;
- }
- public void setIdpUsesPostingBinding(String idpUsesPostingBinding) {
- this.idpUsesPostingBinding = idpUsesPostingBinding;
- }
- public String getSupportsSignatures() {
- return supportsSignatures;
- }
- public void setSupportsSignatures(String supportsSignatures) {
- this.supportsSignatures = supportsSignatures;
- }
- public String getIdentityURL() {
- return identityURL;
- }
- public void setIdentityURL(String identityURL) {
- this.identityURL = identityURL;
- }
- public String getServiceURL() {
- return serviceURL;
- }
- public void setServiceURL(String serviceURL) {
- this.serviceURL = serviceURL;
- }
- public String getKeystoreURL() {
- return keystoreURL;
- }
- public void setKeystoreURL(String keystoreURL) {
- this.keystoreURL = keystoreURL;
- }
- public String getKeystorePass() {
- return keystorePass;
- }
- public void setKeystorePass(String keystorePass) {
- this.keystorePass = keystorePass;
- }
- public String getSigningKeyAlias() {
- return signingKeyAlias;
- }
- public void setSigningKeyAlias(String signingKeyAlias) {
- this.signingKeyAlias = signingKeyAlias;
- }
- public String getSigningKeyPass() {
- return signingKeyPass;
- }
- public void setSigningKeyPass(String signingKeyPass) {
- this.signingKeyPass = signingKeyPass;
- }
- public String getValidatingKeyAlias() {
- return validatingKeyAlias;
- }
- public void setValidatingAliasKey(String validatingKeyAlias) {
- this.validatingKeyAlias = validatingKeyAlias;
- }
- public String getValidatingKeyValue() {
- return validatingKeyValue;
- }
- public void setValidatingAliasValue(String validatingKeyValue) {
- this.validatingKeyValue = validatingKeyValue;
- }
- public String getNameIDFormat() {
- return nameIDFormat;
- }
- public void setNameIDFormat(String nameIDFormat) {
- this.nameIDFormat = nameIDFormat;
- }
- public String getClockSkewMilis() {
- return clockSkewMilis;
- }
- public void setClockSkewMilis(String clockSkewMilis) {
- this.clockSkewMilis = clockSkewMilis;
- }
- public String getAssertionSessionAttributeName() {
- return assertionSessionAttributeName;
- }
- public void setAssertionSessionAttributeName(
- String assertionSessionAttributeName) {
- this.assertionSessionAttributeName = assertionSessionAttributeName;
- }
- @Override
- public String toString() {
- // THIS IS HORRID REPLACE WITH DOM+TRANSFORM
- StringBuffer xml = new StringBuffer();
- xml.append("<?xml version=\"1.0\" encoding=\"UTF-8\" ?>").append(NL)
- .append(LT_OPEN).append(PICKETLINK_ELEMENT).append(" xmlns=\"").append(PICKETLINK_XMLNS).append("\"" + GT).append(NL)
- .append(INDENT).append(LT_OPEN).append(PICKETLINKSP_ELEMENT).append(" xmlns=\"").append(PICKETLINK_SP_XMLNS + "\"").append(NL)
- .append(INDENT).append(INDENT).append("ServerEnvironment").append("=\"").append(serverEnvironment).append("\"").append(NL)
- .append(INDENT).append(INDENT).append("BindingType").append("=\"").append(bindingType).append("\"").append(NL)
- .append(INDENT).append(INDENT).append("IDPUsesPostBinding").append("=\"").append(idpUsesPostingBinding).append("\"").append(NL)
- .append(INDENT).append(INDENT).append("SupportsSignatures").append("=\"").append(supportsSignatures).append("\"").append(NL)
- .append(INDENT).append(INDENT).append("CanonicalizationMethod").append("=\"").append(C14N_METHOD).append("\"").append(GT).append(NL).append(NL)
- .append(INDENT).append(INDENT).append(LT_OPEN).append("IdentityURL").append(GT).append(identityURL).append(LT_CLOSE).append("IdentityURL").append(GT).append(NL)
- .append(INDENT).append(INDENT).append(LT_OPEN).append("ServiceURL").append(GT).append(serviceURL).append(LT_CLOSE).append("ServiceURL").append(GT).append(NL)
- .append(INDENT).append(INDENT).append(LT_OPEN).append(KEYPROVIDER_ELEMENT).append(" ").append("ClassName=\"").append(KEYPROVIDER_CLASSNAME + "\"" + GT).append(NL)
- .append(INDENT).append(INDENT).append(INDENT).append(LT_OPEN).append(AUTH_ELEMENT).append(" Key=\"KeyStoreURL\" Value=\"").append(keystoreURL).append("\"").append(GT_CLOSE).append(NL)
- .append(INDENT).append(INDENT).append(INDENT).append(LT_OPEN).append(AUTH_ELEMENT).append(" Key=\"KeyStorePass\" Value=\"").append(keystorePass).append("\"").append(GT_CLOSE).append(NL)
- .append(INDENT).append(INDENT).append(INDENT).append(LT_OPEN).append(AUTH_ELEMENT).append(" Key=\"SigningKeyAlias\" Value=\"").append(signingKeyAlias).append("\"").append(GT_CLOSE).append(NL)
- .append(INDENT).append(INDENT).append(INDENT).append(LT_OPEN).append(AUTH_ELEMENT).append(" Key=\"SigningKeyPass\" Value=\"").append(signingKeyPass).append("\"").append(GT_CLOSE).append(NL)
- .append(INDENT).append(INDENT).append(INDENT).append(LT_OPEN).append(VAL_ALIAS_ELEMENT).append(" Key=\"").append(validatingKeyAlias).append("\" Value=\"").append(validatingKeyValue).append("\"").append(GT_CLOSE).append(NL)
- .append(INDENT).append(INDENT).append(LT_CLOSE).append(KEYPROVIDER_ELEMENT).append(GT).append(NL)
- .append(INDENT).append(LT_CLOSE).append(PICKETLINKSP_ELEMENT).append(GT).append(NL)
- .append(INDENT).append(LT_OPEN).append(HANDLERS_ELEMENT).append(GT).append(NL)
- .append(INDENT).append(INDENT).append(LT_OPEN).append(HANDLER_ELEMENT).append(" class=\"").append(AUTH_HANDLER_CLASSNAME).append("\">").append(NL)
- .append(INDENT).append(INDENT).append(INDENT).append(LT_OPEN).append(OPTION_ELEMENT).append(" Key=\"NAMEID_FORMAT\" Value=\"").append(nameIDFormat).append("\"").append(GT_CLOSE).append(NL)
- .append(INDENT).append(INDENT).append(INDENT).append(LT_OPEN).append(OPTION_ELEMENT).append(" Key=\"CLOCK_SKEW_MILIS\" Value=\"").append(clockSkewMilis).append("\"").append(GT_CLOSE).append(NL)
- .append(INDENT).append(INDENT).append(INDENT).append(LT_OPEN).append(OPTION_ELEMENT).append(" Key=\"ASSERTION_SESSION_ATTRIBUTE_NAME\" Value=\"").append(assertionSessionAttributeName).append("\"").append(GT_CLOSE).append(NL)
- .append(INDENT).append(INDENT).append(LT_CLOSE).append(HANDLER_ELEMENT).append(GT).append(NL)
- .append(INDENT).append(INDENT).append(LT_OPEN).append(HANDLER_ELEMENT).append(" class=\"").append(ROLE_GEN_HANDLER_CLASSNAME).append("\"/>").append(NL)
- .append(INDENT).append(LT_CLOSE).append(HANDLERS_ELEMENT).append(GT).append(NL)
- .append(LT_CLOSE).append(PICKETLINK_ELEMENT).append(GT).append(NL);
-
- return xml.toString();
- }
-
- public static void main(String[] args) {
- PicketlinkConf conf = new PicketlinkConf();
- System.out.println(conf.toString());
- }
-
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/deploy/PicketlinkFederationProviderContributor.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/deploy/PicketlinkFederationProviderContributor.java b/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/deploy/PicketlinkFederationProviderContributor.java
deleted file mode 100644
index 4f90a41..0000000
--- a/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/deploy/PicketlinkFederationProviderContributor.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.gateway.picketlink.deploy;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.apache.hadoop.gateway.deploy.DeploymentContext;
-import org.apache.hadoop.gateway.deploy.ProviderDeploymentContributorBase;
-import org.apache.hadoop.gateway.descriptor.FilterParamDescriptor;
-import org.apache.hadoop.gateway.descriptor.ResourceDescriptor;
-import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
-import org.apache.hadoop.gateway.picketlink.PicketlinkMessages;
-import org.apache.hadoop.gateway.services.security.AliasService;
-import org.apache.hadoop.gateway.services.security.AliasServiceException;
-import org.apache.hadoop.gateway.services.security.MasterService;
-import org.apache.hadoop.gateway.topology.Provider;
-import org.apache.hadoop.gateway.topology.Service;
-import org.jboss.shrinkwrap.api.asset.StringAsset;
-import org.picketlink.identity.federation.web.filters.ServiceProviderContextInitializer;
-
-public class PicketlinkFederationProviderContributor extends
- ProviderDeploymentContributorBase {
- private static final String ROLE = "federation";
- private static final String NAME = "Picketlink";
- private static final String PICKETLINK_FILTER_CLASSNAME = "org.picketlink.identity.federation.web.filters.SPFilter";
- private static final String CAPTURE_URL_FILTER_CLASSNAME = "org.apache.hadoop.gateway.picketlink.filter.CaptureOriginalURLFilter";
- private static final String IDENTITY_ADAPTER_CLASSNAME = "org.apache.hadoop.gateway.picketlink.filter.PicketlinkIdentityAdapter";
- private static final String IDENTITY_URL_PARAM = "identity.url";
- private static final String SERVICE_URL_PARAM = "service.url";
- private static final String KEYSTORE_URL_PARAM = "keystore.url";
- private static final String SIGNINGKEY_ALIAS = "gateway-identity";
- private static final String VALIDATING_ALIAS_KEY = "validating.alias.key";
- private static final String VALIDATING_ALIAS_VALUE = "validating.alias.value";
- private static final String CLOCK_SKEW_MILIS = "clock.skew.milis";
- private static PicketlinkMessages log = MessagesFactory.get( PicketlinkMessages.class );
-
- private MasterService ms = null;
- private AliasService as = null;
-
- @Override
- public String getRole() {
- return ROLE;
- }
-
- @Override
- public String getName() {
- return NAME;
- }
-
- public void setMasterService(MasterService ms) {
- this.ms = ms;
- }
-
- public void setAliasService(AliasService as) {
- this.as = as;
- }
-
- @Override
- public void initializeContribution(DeploymentContext context) {
- super.initializeContribution(context);
- }
-
- @Override
- public void contributeProvider(DeploymentContext context, Provider provider) {
- // LJM TODO: consider creating a picketlink configuration provider to
- // handle the keystore secrets without putting them in a config file directly.
- // Once that is done then we can remove the unneeded gateway services from those
- // that are available to providers.
- context.getWebAppDescriptor().createListener().listenerClass( ServiceProviderContextInitializer.class.getName());
-
- PicketlinkConf config = new PicketlinkConf( );
- Map<String,String> params = provider.getParams();
- config.setIdentityURL(params.get(IDENTITY_URL_PARAM));
- config.setServiceURL(params.get(SERVICE_URL_PARAM));
- config.setKeystoreURL(params.get(KEYSTORE_URL_PARAM));
- if (ms != null) {
- config.setKeystorePass(new String(ms.getMasterSecret()));
- }
- config.setSigningKeyAlias(SIGNINGKEY_ALIAS);
- if (as != null) {
- char[] passphrase = null;
- try {
- passphrase = as.getGatewayIdentityPassphrase();
- config.setSigningKeyPass(new String(passphrase));
- } catch (AliasServiceException e) {
- log.unableToGetGatewayIdentityPassphrase(e);
- }
- }
- config.setValidatingAliasKey(params.get(VALIDATING_ALIAS_KEY));
- config.setValidatingAliasValue(params.get(VALIDATING_ALIAS_VALUE));
- config.setClockSkewMilis(params.get(CLOCK_SKEW_MILIS));
- String configStr = config.toString();
- if( config != null ) {
- context.getWebArchive().addAsWebInfResource( new StringAsset( configStr ), "picketlink.xml" );
- }
- }
-
- @Override
- public void contributeFilter(DeploymentContext context, Provider provider, Service service,
- ResourceDescriptor resource, List<FilterParamDescriptor> params) {
- // blindly add all the provider params as filter init params
- if (params == null) {
- params = new ArrayList<FilterParamDescriptor>();
- }
- Map<String, String> providerParams = provider.getParams();
- for(Entry<String, String> entry : providerParams.entrySet()) {
- params.add( resource.createFilterParam().name( entry.getKey().toLowerCase() ).value( entry.getValue() ) );
- }
- resource.addFilter().name( getName() ).role( getRole() ).impl( CAPTURE_URL_FILTER_CLASSNAME ).params( params );
- resource.addFilter().name( getName() ).role( getRole() ).impl( PICKETLINK_FILTER_CLASSNAME ).params( params );
- resource.addFilter().name( getName() ).role( getRole() ).impl( IDENTITY_ADAPTER_CLASSNAME ).params( params );
- }
-
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/filter/CaptureOriginalURLFilter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/filter/CaptureOriginalURLFilter.java b/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/filter/CaptureOriginalURLFilter.java
deleted file mode 100644
index 66da6c4..0000000
--- a/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/filter/CaptureOriginalURLFilter.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.gateway.picketlink.filter;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
-import org.apache.hadoop.gateway.picketlink.PicketlinkMessages;
-
-import java.io.IOException;
-
-public class CaptureOriginalURLFilter implements Filter {
- private static PicketlinkMessages log = MessagesFactory.get( PicketlinkMessages.class );
- private static final String COOKIE_PATH = "cookie.path";
- private static final String COOKIE_SECURE = "cookie.secure";
- private String cookiePath = null;
- private String cookieSecure = null;
-
- @Override
- public void init( FilterConfig filterConfig ) throws ServletException {
- cookiePath = filterConfig.getInitParameter(COOKIE_PATH);
- if (cookiePath == null) {
- cookiePath = "/gateway/idp/knoxsso/api/v1/websso";
- }
- cookieSecure = filterConfig.getInitParameter(COOKIE_SECURE);
- if (cookieSecure == null) {
- cookieSecure = "true";
- }
- }
-
- @Override
- public void doFilter( ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain ) throws IOException, ServletException {
- String original = null;
- HttpServletRequest request = (HttpServletRequest)servletRequest;
- String url = request.getParameter("originalUrl");
- if (url != null) {
- log.foundOriginalURLInRequest(url);
- original = request.getParameter("originalUrl");
- log.settingCookieForOriginalURL();
- addCookie(servletResponse, original);
- }
- filterChain.doFilter(request, servletResponse);
- }
-
- @Override
- public void destroy() {
-
- }
-
- private void addCookie(ServletResponse servletResponse, String original) {
- Cookie c = new Cookie("original-url", original);
- c.setPath(cookiePath);
- c.setHttpOnly(true);
- boolean secureOnly = true;
- if (cookieSecure != null) {
- secureOnly = ("false".equals(cookieSecure) ? false : true);
- if (!secureOnly) {
- log.secureFlagFalseForCookie();
- }
- }
- c.setSecure(secureOnly);
- c.setMaxAge(60);
- ((HttpServletResponse)servletResponse).addCookie(c);
- }
-
-}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/filter/PicketlinkIdentityAdapter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/filter/PicketlinkIdentityAdapter.java b/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/filter/PicketlinkIdentityAdapter.java
deleted file mode 100644
index 333f91d..0000000
--- a/gateway-provider-security-picketlink/src/main/java/org/apache/hadoop/gateway/picketlink/filter/PicketlinkIdentityAdapter.java
+++ /dev/null
@@ -1,102 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.hadoop.gateway.picketlink.filter;
-
-import java.io.IOException;
-import java.security.Principal;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import javax.security.auth.Subject;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.hadoop.gateway.audit.api.Action;
-import org.apache.hadoop.gateway.audit.api.ActionOutcome;
-import org.apache.hadoop.gateway.audit.api.AuditService;
-import org.apache.hadoop.gateway.audit.api.AuditServiceFactory;
-import org.apache.hadoop.gateway.audit.api.Auditor;
-import org.apache.hadoop.gateway.audit.api.ResourceType;
-import org.apache.hadoop.gateway.audit.log4j.audit.AuditConstants;
-import org.apache.hadoop.gateway.filter.AbstractGatewayFilter;
-import org.apache.hadoop.gateway.security.PrimaryPrincipal;
-
-public class PicketlinkIdentityAdapter implements Filter {
-
- private static AuditService auditService = AuditServiceFactory.getAuditService();
- private static Auditor auditor = auditService.getAuditor(
- AuditConstants.DEFAULT_AUDITOR_NAME, AuditConstants.KNOX_SERVICE_NAME,
- AuditConstants.KNOX_COMPONENT_NAME );
-
-
- @Override
- public void init( FilterConfig filterConfig ) throws ServletException {
- }
-
- public void destroy() {
- }
-
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
- throws IOException, ServletException {
-
- HttpServletRequest httpRequest = (HttpServletRequest) request;
- String username = httpRequest.getUserPrincipal().getName();
- PrimaryPrincipal pp = new PrimaryPrincipal(username);
- Subject subject = new Subject();
- subject.getPrincipals().add(pp);
-
- Principal principal = (Principal) subject.getPrincipals(PrimaryPrincipal.class);
- auditService.getContext().setUsername( principal.getName() );
- String sourceUri = (String)request.getAttribute( AbstractGatewayFilter.SOURCE_REQUEST_CONTEXT_URL_ATTRIBUTE_NAME );
- auditor.audit( Action.AUTHENTICATION , sourceUri, ResourceType.URI, ActionOutcome.SUCCESS );
-
- doAs(request, response, chain, subject);
- }
-
- private void doAs(final ServletRequest request,
- final ServletResponse response, final FilterChain chain, Subject subject)
- throws IOException, ServletException {
- try {
- Subject.doAs(
- subject,
- new PrivilegedExceptionAction<Object>() {
- public Object run() throws Exception {
- chain.doFilter(request, response);
- return null;
- }
- }
- );
- }
- catch (PrivilegedActionException e) {
- Throwable t = e.getCause();
- if (t instanceof IOException) {
- throw (IOException) t;
- }
- else if (t instanceof ServletException) {
- throw (ServletException) t;
- }
- else {
- throw new ServletException(t);
- }
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-picketlink/src/main/java/org/apache/knox/gateway/picketlink/PicketlinkMessages.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-picketlink/src/main/java/org/apache/knox/gateway/picketlink/PicketlinkMessages.java b/gateway-provider-security-picketlink/src/main/java/org/apache/knox/gateway/picketlink/PicketlinkMessages.java
new file mode 100644
index 0000000..bcb347c
--- /dev/null
+++ b/gateway-provider-security-picketlink/src/main/java/org/apache/knox/gateway/picketlink/PicketlinkMessages.java
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.knox.gateway.picketlink;
+
+import org.apache.knox.gateway.i18n.messages.Message;
+import org.apache.knox.gateway.i18n.messages.MessageLevel;
+import org.apache.knox.gateway.i18n.messages.Messages;
+import org.apache.knox.gateway.i18n.messages.StackTrace;
+
+@Messages(logger="org.apache.hadoop.gateway.picketlink")
+public interface PicketlinkMessages {
+
+ @Message( level = MessageLevel.DEBUG, text = "Found Original URL in reequest: {0}")
+ public void foundOriginalURLInRequest(String url);
+
+ @Message( level = MessageLevel.DEBUG, text = "setting cookie for original-url")
+ public void settingCookieForOriginalURL();
+
+ @Message( level = MessageLevel.DEBUG, text = "Secure Flag is set to False for cookie")
+ public void secureFlagFalseForCookie();
+
+ @Message( level = MessageLevel.ERROR, text = "Unable to get the gateway identity passphrase: {0}")
+ public void unableToGetGatewayIdentityPassphrase(@StackTrace( level = MessageLevel.DEBUG) Exception e);
+
+}