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:08 UTC
[10/64] [partial] knox git commit: KNOX-998 - Refactoring save 1
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/SSOCookieProviderTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/SSOCookieProviderTest.java b/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/SSOCookieProviderTest.java
deleted file mode 100644
index 396aec9..0000000
--- a/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/SSOCookieProviderTest.java
+++ /dev/null
@@ -1,205 +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.provider.federation;
-
-import static org.junit.Assert.fail;
-
-import java.security.NoSuchAlgorithmException;
-import java.security.Principal;
-import java.util.Properties;
-import java.util.Date;
-import java.util.Set;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.hadoop.gateway.provider.federation.jwt.filter.SSOCookieFederationFilter;
-import org.apache.hadoop.gateway.security.PrimaryPrincipal;
-import org.apache.hadoop.gateway.services.security.token.JWTokenAuthority;
-import org.easymock.EasyMock;
-import org.junit.Assert;
-import org.junit.Before;
-import org.junit.Test;
-
-import com.nimbusds.jwt.SignedJWT;
-
-public class SSOCookieProviderTest extends AbstractJWTFilterTest {
- private static final String SERVICE_URL = "https://localhost:8888/resource";
- private static final String REDIRECT_LOCATION =
- "https://localhost:8443/authserver?originalUrl=" + SERVICE_URL;
-
- @Before
- public void setup() throws Exception, NoSuchAlgorithmException {
- super.setup();
- handler = new TestSSOCookieFederationProvider();
- ((TestSSOCookieFederationProvider) handler).setTokenService(new TestJWTokenAuthority());
- }
-
- protected void setTokenOnRequest(HttpServletRequest request, SignedJWT jwt) {
- Cookie cookie = new Cookie("hadoop-jwt", jwt.serialize());
- EasyMock.expect(request.getCookies()).andReturn(new Cookie[] { cookie });
- }
-
- protected void setGarbledTokenOnRequest(HttpServletRequest request, SignedJWT jwt) {
- Cookie cookie = new Cookie("hadoop-jwt", "ljm" + jwt.serialize());
- EasyMock.expect(request.getCookies()).andReturn(new Cookie[] { cookie });
- }
-
- protected String getAudienceProperty() {
- return TestSSOCookieFederationProvider.SSO_EXPECTED_AUDIENCES;
- }
-
- @Test
- public void testCustomCookieNameJWT() throws Exception {
- try {
- Properties props = getProperties();
- props.put("sso.cookie.name", "jowt");
- handler.init(new TestFilterConfig(props));
-
- SignedJWT jwt = getJWT("alice", new Date(new Date().getTime() + 5000),
- privateKey, props);
-
- Cookie cookie = new Cookie("jowt", jwt.serialize());
- HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
- EasyMock.expect(request.getCookies()).andReturn(new Cookie[] { cookie });
- EasyMock.expect(request.getRequestURL()).andReturn(
- new StringBuffer(SERVICE_URL)).anyTimes();
- EasyMock.expect(request.getQueryString()).andReturn(null);
- HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
- EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
- SERVICE_URL);
- EasyMock.replay(request);
-
- TestFilterChain chain = new TestFilterChain();
- handler.doFilter(request, response, chain);
- Assert.assertTrue("doFilterCalled should not be false.", chain.doFilterCalled == true);
- Set<PrimaryPrincipal> principals = chain.subject.getPrincipals(PrimaryPrincipal.class);
- Assert.assertTrue("No PrimaryPrincipal returned.", principals.size() > 0);
- Assert.assertEquals("Not the expected principal", "alice", ((Principal)principals.toArray()[0]).getName());
- } catch (ServletException se) {
- fail("Should NOT have thrown a ServletException.");
- }
- }
-
- @Test
- public void testNoProviderURLJWT() throws Exception {
- try {
- Properties props = getProperties();
- props.remove("sso.authentication.provider.url");
- handler.init(new TestFilterConfig(props));
-
- fail("Servlet exception should have been thrown.");
-
- } catch (ServletException se) {
- // expected - let's ensure it mentions the missing authentication provider URL
- se.getMessage().contains("authentication provider URL is missing");
- }
- }
-
-/*
- @Test
- public void testFailedSignatureValidationJWT() throws Exception {
- try {
-
- // Create a public key that doesn't match the one needed to
- // verify the signature - in order to make it fail verification...
- KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
- kpg.initialize(2048);
-
- KeyPair kp = kpg.genKeyPair();
- RSAPublicKey publicKey = (RSAPublicKey) kp.getPublic();
-
- handler.setPublicKey(publicKey);
-
- Properties props = getProperties();
- handler.init(props);
-
- SignedJWT jwt = getJWT("bob", new Date(new Date().getTime() + 5000),
- privateKey);
-
- Cookie cookie = new Cookie("hadoop-jwt", jwt.serialize());
- HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
- Mockito.when(request.getCookies()).thenReturn(new Cookie[] { cookie });
- Mockito.when(request.getRequestURL()).thenReturn(
- new StringBuffer(SERVICE_URL)).anyTimes();
- HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
- Mockito.when(response.encodeRedirectURL(SERVICE_URL)).thenReturn(
- SERVICE_URL);
-
- AuthenticationToken token = handler.alternateAuthenticate(request,
- response);
- Mockito.verify(response).sendRedirect(REDIRECT_LOCATION);
- } catch (ServletException se) {
- fail("alternateAuthentication should NOT have thrown a ServletException");
- } catch (AuthenticationException ae) {
- fail("alternateAuthentication should NOT have thrown a AuthenticationException");
- }
- }
-*/
-
- @Test
- public void testOrigURLWithQueryString() throws Exception {
- Properties props = getProperties();
- handler.init(new TestFilterConfig(props));
-
- HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
- EasyMock.expect(request.getRequestURL()).andReturn(
- new StringBuffer(SERVICE_URL)).anyTimes();
- EasyMock.expect(request.getQueryString()).andReturn("name=value");
- EasyMock.replay(request);
-
- String loginURL = ((TestSSOCookieFederationProvider)handler).testConstructLoginURL(request);
- Assert.assertNotNull("loginURL should not be null.", loginURL);
- Assert.assertEquals("https://localhost:8443/authserver?originalUrl=" + SERVICE_URL + "?name=value", loginURL);
- }
-
- @Test
- public void testOrigURLNoQueryString() throws Exception {
- Properties props = getProperties();
- handler.init(new TestFilterConfig(props));
-
- HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
- EasyMock.expect(request.getRequestURL()).andReturn(
- new StringBuffer(SERVICE_URL)).anyTimes();
- EasyMock.expect(request.getQueryString()).andReturn(null);
- EasyMock.replay(request);
-
- String loginURL = ((TestSSOCookieFederationProvider)handler).testConstructLoginURL(request);
- Assert.assertNotNull("LoginURL should not be null.", loginURL);
- Assert.assertEquals("https://localhost:8443/authserver?originalUrl=" + SERVICE_URL, loginURL);
- }
-
-
- @Override
- protected String getVerificationPemProperty() {
- return SSOCookieFederationFilter.SSO_VERIFICATION_PEM;
- };
-
- private static class TestSSOCookieFederationProvider extends SSOCookieFederationFilter {
- public String testConstructLoginURL(HttpServletRequest req) {
- return constructLoginURL(req);
- }
-
- public void setTokenService(JWTokenAuthority ts) {
- authority = ts;
- }
- };
-
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/AbstractJWTFilterTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/AbstractJWTFilterTest.java b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/AbstractJWTFilterTest.java
new file mode 100644
index 0000000..503f323
--- /dev/null
+++ b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/AbstractJWTFilterTest.java
@@ -0,0 +1,490 @@
+/**
+ * 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.provider.federation;
+
+import static org.junit.Assert.fail;
+
+import java.io.IOException;
+import java.net.InetAddress;
+import java.security.AccessController;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.security.cert.Certificate;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.interfaces.RSAPublicKey;
+import java.text.MessageFormat;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Properties;
+import java.util.Date;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.knox.gateway.provider.federation.jwt.filter.AbstractJWTFilter;
+import org.apache.knox.gateway.provider.federation.jwt.filter.SSOCookieFederationFilter;
+import org.apache.knox.gateway.security.PrimaryPrincipal;
+import org.apache.knox.gateway.services.security.impl.X509CertificateUtil;
+import org.apache.knox.gateway.services.security.token.JWTokenAuthority;
+import org.apache.knox.gateway.services.security.token.TokenServiceException;
+import org.apache.knox.gateway.services.security.token.impl.JWT;
+import org.apache.knox.gateway.services.security.token.impl.JWTToken;
+import org.easymock.EasyMock;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.nimbusds.jose.*;
+import com.nimbusds.jwt.JWTClaimsSet;
+import com.nimbusds.jwt.SignedJWT;
+import com.nimbusds.jose.crypto.RSASSASigner;
+import com.nimbusds.jose.util.Base64URL;
+
+public abstract class AbstractJWTFilterTest {
+ private static final String SERVICE_URL = "https://localhost:8888/resource";
+ private static final String dnTemplate = "CN={0},OU=Test,O=Hadoop,L=Test,ST=Test,C=US";
+
+ protected AbstractJWTFilter handler = null;
+ protected RSAPublicKey publicKey = null;
+ protected RSAPrivateKey privateKey = null;
+ protected String pem = null;
+
+ protected abstract void setTokenOnRequest(HttpServletRequest request, SignedJWT jwt);
+ protected abstract void setGarbledTokenOnRequest(HttpServletRequest request, SignedJWT jwt);
+ protected abstract String getAudienceProperty();
+ protected abstract String getVerificationPemProperty();
+
+ private String buildDistinguishedName(String hostname) {
+ MessageFormat headerFormatter = new MessageFormat(dnTemplate);
+ String[] paramArray = new String[1];
+ paramArray[0] = hostname;
+ String dn = headerFormatter.format(paramArray);
+ return dn;
+ }
+
+ @Before
+ public void setup() throws Exception, NoSuchAlgorithmException {
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
+ kpg.initialize(2048);
+ KeyPair KPair = kpg.generateKeyPair();
+ String dn = buildDistinguishedName(InetAddress.getLocalHost().getHostName());
+ Certificate cert = X509CertificateUtil.generateCertificate(dn, KPair, 365, "SHA1withRSA");
+ byte[] data = cert.getEncoded();
+ Base64 encoder = new Base64( 76, "\n".getBytes( "ASCII" ) );
+ pem = new String(encoder.encodeToString( data ).getBytes( "ASCII" )).trim();
+
+ publicKey = (RSAPublicKey) KPair.getPublic();
+ privateKey = (RSAPrivateKey) KPair.getPrivate();
+ }
+
+ @After
+ public void teardown() throws Exception {
+ handler.destroy();
+ }
+
+ @Test
+ public void testValidJWT() throws Exception {
+ try {
+ Properties props = getProperties();
+ handler.init(new TestFilterConfig(props));
+
+ SignedJWT jwt = getJWT("alice", new Date(new Date().getTime() + 5000), privateKey, props);
+
+ HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+ setTokenOnRequest(request, jwt);
+
+ EasyMock.expect(request.getRequestURL()).andReturn(
+ new StringBuffer(SERVICE_URL)).anyTimes();
+ EasyMock.expect(request.getQueryString()).andReturn(null);
+ HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+ EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
+ SERVICE_URL);
+ EasyMock.replay(request);
+
+ TestFilterChain chain = new TestFilterChain();
+ handler.doFilter(request, response, chain);
+ Assert.assertTrue("doFilterCalled should not be false.", chain.doFilterCalled == true);
+ Set<PrimaryPrincipal> principals = chain.subject.getPrincipals(PrimaryPrincipal.class);
+ Assert.assertTrue("No PrimaryPrincipal", principals.size() > 0);
+ Assert.assertEquals("Not the expected principal", "alice", ((Principal)principals.toArray()[0]).getName());
+ } catch (ServletException se) {
+ fail("Should NOT have thrown a ServletException.");
+ }
+ }
+
+ @Test
+ public void testValidAudienceJWT() throws Exception {
+ try {
+ Properties props = getProperties();
+ props.put(getAudienceProperty(), "bar");
+ handler.init(new TestFilterConfig(props));
+
+ SignedJWT jwt = getJWT("alice", new Date(new Date().getTime() + 5000), privateKey, props);
+
+ HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+ setTokenOnRequest(request, jwt);
+
+ EasyMock.expect(request.getRequestURL()).andReturn(
+ new StringBuffer(SERVICE_URL)).anyTimes();
+ EasyMock.expect(request.getQueryString()).andReturn(null);
+ HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+ EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
+ SERVICE_URL);
+ EasyMock.replay(request);
+
+ TestFilterChain chain = new TestFilterChain();
+ handler.doFilter(request, response, chain);
+ Assert.assertTrue("doFilterCalled should not be false.", chain.doFilterCalled == true);
+ Set<PrimaryPrincipal> principals = chain.subject.getPrincipals(PrimaryPrincipal.class);
+ Assert.assertTrue("No PrimaryPrincipal", principals.size() > 0);
+ Assert.assertEquals("Not the expected principal", "alice", ((Principal)principals.toArray()[0]).getName());
+ } catch (ServletException se) {
+ fail("Should NOT have thrown a ServletException.");
+ }
+ }
+
+ @Test
+ public void testInvalidAudienceJWT() throws Exception {
+ try {
+ Properties props = getProperties();
+ props.put(getAudienceProperty(), "foo");
+ props.put("sso.authentication.provider.url", "https://localhost:8443/gateway/knoxsso/api/v1/websso");
+
+ handler.init(new TestFilterConfig(props));
+
+ SignedJWT jwt = getJWT("alice", new Date(new Date().getTime() + 5000), privateKey, props);
+
+ HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+ setTokenOnRequest(request, jwt);
+
+ EasyMock.expect(request.getRequestURL()).andReturn(
+ new StringBuffer(SERVICE_URL)).anyTimes();
+ EasyMock.expect(request.getQueryString()).andReturn(null);
+ HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+ EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
+ SERVICE_URL);
+ EasyMock.replay(request);
+
+ TestFilterChain chain = new TestFilterChain();
+ handler.doFilter(request, response, chain);
+ Assert.assertTrue("doFilterCalled should not be true.", chain.doFilterCalled == false);
+ Assert.assertTrue("No Subject should be returned.", chain.subject == null);
+ } catch (ServletException se) {
+ fail("Should NOT have thrown a ServletException.");
+ }
+ }
+
+ @Test
+ public void testValidVerificationPEM() throws Exception {
+ try {
+ Properties props = getProperties();
+
+// System.out.println("+" + pem + "+");
+
+ props.put(getAudienceProperty(), "bar");
+ props.put("sso.authentication.provider.url", "https://localhost:8443/gateway/knoxsso/api/v1/websso");
+ props.put(getVerificationPemProperty(), pem);
+ handler.init(new TestFilterConfig(props));
+
+ SignedJWT jwt = getJWT("alice", new Date(new Date().getTime() + 50000), privateKey, props);
+
+ HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+ setTokenOnRequest(request, jwt);
+
+ EasyMock.expect(request.getRequestURL()).andReturn(
+ new StringBuffer(SERVICE_URL)).anyTimes();
+ EasyMock.expect(request.getQueryString()).andReturn(null);
+ HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+ EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
+ SERVICE_URL);
+ EasyMock.replay(request);
+
+ TestFilterChain chain = new TestFilterChain();
+ handler.doFilter(request, response, chain);
+ Assert.assertTrue("doFilterCalled should not be false.", chain.doFilterCalled == true);
+ Set<PrimaryPrincipal> principals = chain.subject.getPrincipals(PrimaryPrincipal.class);
+ Assert.assertTrue("No PrimaryPrincipal", principals.size() > 0);
+ Assert.assertEquals("Not the expected principal", "alice", ((Principal)principals.toArray()[0]).getName());
+ } catch (ServletException se) {
+ fail("Should NOT have thrown a ServletException.");
+ }
+ }
+
+ @Test
+ public void testExpiredJWT() throws Exception {
+ try {
+ Properties props = getProperties();
+ handler.init(new TestFilterConfig(props));
+
+ SignedJWT jwt = getJWT("alice", new Date(new Date().getTime() - 1000), privateKey, props);
+
+ HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+ setTokenOnRequest(request, jwt);
+
+ EasyMock.expect(request.getRequestURL()).andReturn(
+ new StringBuffer(SERVICE_URL)).anyTimes();
+ EasyMock.expect(request.getQueryString()).andReturn(null);
+ HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+ EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
+ SERVICE_URL);
+ EasyMock.replay(request);
+
+ TestFilterChain chain = new TestFilterChain();
+ handler.doFilter(request, response, chain);
+ Assert.assertTrue("doFilterCalled should not be false.", chain.doFilterCalled == false);
+ Assert.assertTrue("No Subject should be returned.", chain.subject == null);
+ } catch (ServletException se) {
+ fail("Should NOT have thrown a ServletException.");
+ }
+ }
+
+ @Test
+ public void testValidJWTNoExpiration() throws Exception {
+ try {
+ Properties props = getProperties();
+ handler.init(new TestFilterConfig(props));
+
+ SignedJWT jwt = getJWT("alice", null, privateKey, props);
+
+ HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+ setTokenOnRequest(request, jwt);
+
+ EasyMock.expect(request.getRequestURL()).andReturn(
+ new StringBuffer(SERVICE_URL)).anyTimes();
+ EasyMock.expect(request.getQueryString()).andReturn(null);
+ HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+ EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
+ SERVICE_URL).anyTimes();
+ EasyMock.replay(request);
+
+ TestFilterChain chain = new TestFilterChain();
+ handler.doFilter(request, response, chain);
+ Assert.assertTrue("doFilterCalled should not be false.", chain.doFilterCalled == true);
+ Set<PrimaryPrincipal> principals = chain.subject.getPrincipals(PrimaryPrincipal.class);
+ Assert.assertTrue("No PrimaryPrincipal", principals.size() > 0);
+ Assert.assertEquals("Not the expected principal", "alice", ((Principal)principals.toArray()[0]).getName());
+ } catch (ServletException se) {
+ fail("Should NOT have thrown a ServletException.");
+ }
+ }
+
+ @Test
+ public void testUnableToParseJWT() throws Exception {
+ try {
+ Properties props = getProperties();
+ handler.init(new TestFilterConfig(props));
+
+ SignedJWT jwt = getJWT("bob",new Date(new Date().getTime() + 5000), privateKey, props);
+
+ HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+ setGarbledTokenOnRequest(request, jwt);
+
+ EasyMock.expect(request.getRequestURL()).andReturn(
+ new StringBuffer(SERVICE_URL)).anyTimes();
+ EasyMock.expect(request.getQueryString()).andReturn(null);
+ HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+ EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
+ SERVICE_URL).anyTimes();
+ EasyMock.replay(request);
+
+ TestFilterChain chain = new TestFilterChain();
+ handler.doFilter(request, response, chain);
+ Assert.assertTrue("doFilterCalled should not be false.", chain.doFilterCalled == false);
+ Assert.assertTrue("No Subject should be returned.", chain.subject == null);
+ } catch (ServletException se) {
+ fail("Should NOT have thrown a ServletException.");
+ }
+ }
+
+ protected Properties getProperties() {
+ Properties props = new Properties();
+ props.setProperty(
+ SSOCookieFederationFilter.SSO_AUTHENTICATION_PROVIDER_URL,
+ "https://localhost:8443/authserver");
+ return props;
+ }
+
+ protected SignedJWT getJWT(String sub, Date expires, RSAPrivateKey privateKey,
+ Properties props) throws Exception {
+ List<String> aud = new ArrayList<String>();
+ aud.add("bar");
+
+ JWTClaimsSet claims = new JWTClaimsSet.Builder()
+ .issuer("KNOXSSO")
+ .subject(sub)
+ .audience(aud)
+ .expirationTime(expires)
+ .claim("scope", "openid")
+ .build();
+
+ JWSHeader header = new JWSHeader.Builder(JWSAlgorithm.RS256).build();
+
+ SignedJWT signedJWT = new SignedJWT(header, claims);
+ Base64URL sigInput = Base64URL.encode(signedJWT.getSigningInput());
+ JWSSigner signer = new RSASSASigner(privateKey);
+
+ signedJWT.sign(signer);
+
+ return signedJWT;
+ }
+
+ protected static class TestFilterConfig implements FilterConfig {
+ Properties props = null;
+
+ public TestFilterConfig(Properties props) {
+ this.props = props;
+ }
+
+ @Override
+ public String getFilterName() {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.servlet.FilterConfig#getServletContext()
+ */
+ @Override
+ public ServletContext getServletContext() {
+// JWTokenAuthority authority = EasyMock.createNiceMock(JWTokenAuthority.class);
+// GatewayServices services = EasyMock.createNiceMock(GatewayServices.class);
+// EasyMock.expect(services.getService("TokenService").andReturn(authority));
+// ServletContext context = EasyMock.createNiceMock(ServletContext.class);
+// EasyMock.expect(context.getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE).andReturn(new DefaultGatewayServices()));
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see javax.servlet.FilterConfig#getInitParameter(java.lang.String)
+ */
+ @Override
+ public String getInitParameter(String name) {
+ return props.getProperty(name, null);
+ }
+
+ /* (non-Javadoc)
+ * @see javax.servlet.FilterConfig#getInitParameterNames()
+ */
+ @Override
+ public Enumeration<String> getInitParameterNames() {
+ return null;
+ }
+
+ }
+
+ protected static class TestJWTokenAuthority implements JWTokenAuthority {
+
+ /* (non-Javadoc)
+ * @see JWTokenAuthority#issueToken(javax.security.auth.Subject, java.lang.String)
+ */
+ @Override
+ public JWTToken issueToken(Subject subject, String algorithm)
+ throws TokenServiceException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see JWTokenAuthority#issueToken(java.security.Principal, java.lang.String)
+ */
+ @Override
+ public JWTToken issueToken(Principal p, String algorithm)
+ throws TokenServiceException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see JWTokenAuthority#issueToken(java.security.Principal, java.lang.String, java.lang.String)
+ */
+ @Override
+ public JWTToken issueToken(Principal p, String audience, String algorithm)
+ throws TokenServiceException {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see JWTokenAuthority#verifyToken(JWTToken)
+ */
+ @Override
+ public boolean verifyToken(JWTToken token) throws TokenServiceException {
+ return true;
+ }
+
+ /* (non-Javadoc)
+ * @see JWTokenAuthority#issueToken(java.security.Principal, java.lang.String, java.lang.String, long)
+ */
+ @Override
+ public JWTToken issueToken(Principal p, String audience, String algorithm,
+ long expires) throws TokenServiceException {
+ return null;
+ }
+
+ @Override
+ public JWTToken issueToken(Principal p, List<String> audiences, String algorithm,
+ long expires) throws TokenServiceException {
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see JWTokenAuthority#issueToken(java.security.Principal, java.lang.String, long)
+ */
+ @Override
+ public JWT issueToken(Principal p, String audience, long l)
+ throws TokenServiceException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public boolean verifyToken(JWTToken token, RSAPublicKey publicKey) throws TokenServiceException {
+ // TODO Auto-generated method stub
+ return true;
+ }
+
+ }
+
+ protected static class TestFilterChain implements FilterChain {
+ boolean doFilterCalled = false;
+ Subject subject = null;
+
+ /* (non-Javadoc)
+ * @see javax.servlet.FilterChain#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
+ */
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response)
+ throws IOException, ServletException {
+ doFilterCalled = true;
+
+ subject = Subject.getSubject( AccessController.getContext() );
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/JWTFederationFilterTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/JWTFederationFilterTest.java b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/JWTFederationFilterTest.java
new file mode 100644
index 0000000..14b704a
--- /dev/null
+++ b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/JWTFederationFilterTest.java
@@ -0,0 +1,67 @@
+/**
+ * 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.provider.federation;
+
+import java.security.NoSuchAlgorithmException;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.knox.gateway.provider.federation.jwt.filter.JWTFederationFilter;
+import org.apache.knox.gateway.services.security.token.JWTokenAuthority;
+import org.easymock.EasyMock;
+import org.junit.Before;
+
+import com.nimbusds.jwt.SignedJWT;
+
+public class JWTFederationFilterTest extends AbstractJWTFilterTest {
+
+ @Before
+ public void setup() throws Exception, NoSuchAlgorithmException {
+ super.setup();
+ handler = new TestJWTFederationFilter();
+ ((TestJWTFederationFilter) handler).setTokenService(new TestJWTokenAuthority());
+ }
+
+ protected void setTokenOnRequest(HttpServletRequest request, SignedJWT jwt) {
+ String token = "Bearer " + jwt.serialize();
+ EasyMock.expect(request.getHeader("Authorization")).andReturn(token);
+ }
+
+ protected void setGarbledTokenOnRequest(HttpServletRequest request, SignedJWT jwt) {
+ String token = "Bearer " + "ljm" + jwt.serialize();
+ EasyMock.expect(request.getHeader("Authorization")).andReturn(token);
+ }
+
+ protected String getAudienceProperty() {
+ return TestJWTFederationFilter.KNOX_TOKEN_AUDIENCES;
+ }
+
+ private static class TestJWTFederationFilter extends JWTFederationFilter {
+
+ public void setTokenService(JWTokenAuthority ts) {
+ authority = ts;
+ }
+
+ }
+
+ @Override
+ protected String getVerificationPemProperty() {
+ return TestJWTFederationFilter.TOKEN_VERIFICATION_PEM;
+ };
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/JWTTokenTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/JWTTokenTest.java b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/JWTTokenTest.java
new file mode 100644
index 0000000..1f1973e
--- /dev/null
+++ b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/JWTTokenTest.java
@@ -0,0 +1,133 @@
+/**
+ * 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.provider.federation;
+
+import java.util.ArrayList;
+import junit.framework.TestCase;
+
+import org.apache.knox.gateway.services.security.token.impl.JWTToken;
+import org.junit.Test;
+
+public class JWTTokenTest extends TestCase {
+ private static final String JWT_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpYXQiOjE0MTY5MjkxMDksImp0aSI6ImFhN2Y4ZDBhOTVjIiwic2NvcGVzIjpbInJlcG8iLCJwdWJsaWNfcmVwbyJdfQ.XCEwpBGvOLma4TCoh36FU7XhUbcskygS81HE1uHLf0E";
+ private static final String HEADER = "{\"alg\":\"RS256\", \"type\":\"JWT\"}";
+ private static final String CLAIMS = "{\"iss\": \"gateway\", \"prn\": \"john.doe@example.com\", \"aud\": \"https://login.example.com\", \"exp\": \"1363360913\"}";
+
+// public void testTokenParsing() throws Exception {
+// try {
+// JWTToken token = JWTToken.parseToken(JWT_TOKEN);
+// assertEquals(token.getHeader(), HEADER);
+// assertEquals(token.getClaims(), CLAIMS);
+//
+// assertEquals(token.getIssuer(), "gateway");
+// assertEquals(token.getPrincipal(), "john.doe@example.com");
+// assertEquals(token.getAudience(), "https://login.example.com");
+// assertEquals(token.getExpires(), "1363360913");
+// }
+// catch (ParseException pe) {
+// fail("ParseException encountered.");
+// }
+// }
+
+ @Test
+ public void testTokenCreation() throws Exception {
+ String[] claims = new String[4];
+ claims[0] = "KNOXSSO";
+ claims[1] = "john.doe@example.com";
+ claims[2] = "https://login.example.com";
+ claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
+ JWTToken token = new JWTToken("RS256", claims);
+
+ assertEquals("KNOXSSO", token.getIssuer());
+ assertEquals("john.doe@example.com", token.getSubject());
+ assertEquals("https://login.example.com", token.getAudience());
+ }
+
+ @Test
+ public void testTokenCreationWithAudienceListSingle() throws Exception {
+ String[] claims = new String[4];
+ claims[0] = "KNOXSSO";
+ claims[1] = "john.doe@example.com";
+ claims[2] = null;
+ claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
+ ArrayList<String> audiences = new ArrayList<String>();
+ audiences.add("https://login.example.com");
+
+ JWTToken token = new JWTToken("RS256", claims, audiences);
+
+ assertEquals("KNOXSSO", token.getIssuer());
+ assertEquals("john.doe@example.com", token.getSubject());
+ assertEquals("https://login.example.com", token.getAudience());
+ assertEquals(1, token.getAudienceClaims().length);
+ }
+
+ @Test
+ public void testTokenCreationWithAudienceListMultiple() throws Exception {
+ String[] claims = new String[4];
+ claims[0] = "KNOXSSO";
+ claims[1] = "john.doe@example.com";
+ claims[2] = null;
+ claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
+ ArrayList<String> audiences = new ArrayList<String>();
+ audiences.add("https://login.example.com");
+ audiences.add("KNOXSSO");
+
+ JWTToken token = new JWTToken("RS256", claims, audiences);
+
+ assertEquals("KNOXSSO", token.getIssuer());
+ assertEquals("john.doe@example.com", token.getSubject());
+ assertEquals("https://login.example.com", token.getAudience());
+ assertEquals(2, token.getAudienceClaims().length);
+ }
+
+ @Test
+ public void testTokenCreationWithAudienceListCombined() throws Exception {
+ String[] claims = new String[4];
+ claims[0] = "KNOXSSO";
+ claims[1] = "john.doe@example.com";
+ claims[2] = "LJM";
+ claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
+ ArrayList<String> audiences = new ArrayList<String>();
+ audiences.add("https://login.example.com");
+ audiences.add("KNOXSSO");
+
+ JWTToken token = new JWTToken("RS256", claims, audiences);
+
+ assertEquals("KNOXSSO", token.getIssuer());
+ assertEquals("john.doe@example.com", token.getSubject());
+ assertEquals("https://login.example.com", token.getAudience());
+ assertEquals(3, token.getAudienceClaims().length);
+ }
+
+ @Test
+ public void testTokenCreationWithNullAudienceList() throws Exception {
+ String[] claims = new String[4];
+ claims[0] = "KNOXSSO";
+ claims[1] = "john.doe@example.com";
+ claims[2] = null;
+ claims[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
+ ArrayList<String> audiences = null;
+
+ JWTToken token = new JWTToken("RS256", claims, audiences);
+
+ assertEquals("KNOXSSO", token.getIssuer());
+ assertEquals("john.doe@example.com", token.getSubject());
+ assertEquals(null, token.getAudience());
+ assertEquals(null, token.getAudienceClaims());
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/SSOCookieProviderTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/SSOCookieProviderTest.java b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/SSOCookieProviderTest.java
new file mode 100644
index 0000000..fa0e785
--- /dev/null
+++ b/gateway-provider-security-jwt/src/test/java/org/apache/knox/gateway/provider/federation/SSOCookieProviderTest.java
@@ -0,0 +1,205 @@
+/**
+ * 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.provider.federation;
+
+import static org.junit.Assert.fail;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.Principal;
+import java.util.Properties;
+import java.util.Date;
+import java.util.Set;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.Cookie;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.knox.gateway.provider.federation.jwt.filter.SSOCookieFederationFilter;
+import org.apache.knox.gateway.security.PrimaryPrincipal;
+import org.apache.knox.gateway.services.security.token.JWTokenAuthority;
+import org.easymock.EasyMock;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.nimbusds.jwt.SignedJWT;
+
+public class SSOCookieProviderTest extends AbstractJWTFilterTest {
+ private static final String SERVICE_URL = "https://localhost:8888/resource";
+ private static final String REDIRECT_LOCATION =
+ "https://localhost:8443/authserver?originalUrl=" + SERVICE_URL;
+
+ @Before
+ public void setup() throws Exception, NoSuchAlgorithmException {
+ super.setup();
+ handler = new TestSSOCookieFederationProvider();
+ ((TestSSOCookieFederationProvider) handler).setTokenService(new TestJWTokenAuthority());
+ }
+
+ protected void setTokenOnRequest(HttpServletRequest request, SignedJWT jwt) {
+ Cookie cookie = new Cookie("hadoop-jwt", jwt.serialize());
+ EasyMock.expect(request.getCookies()).andReturn(new Cookie[] { cookie });
+ }
+
+ protected void setGarbledTokenOnRequest(HttpServletRequest request, SignedJWT jwt) {
+ Cookie cookie = new Cookie("hadoop-jwt", "ljm" + jwt.serialize());
+ EasyMock.expect(request.getCookies()).andReturn(new Cookie[] { cookie });
+ }
+
+ protected String getAudienceProperty() {
+ return TestSSOCookieFederationProvider.SSO_EXPECTED_AUDIENCES;
+ }
+
+ @Test
+ public void testCustomCookieNameJWT() throws Exception {
+ try {
+ Properties props = getProperties();
+ props.put("sso.cookie.name", "jowt");
+ handler.init(new TestFilterConfig(props));
+
+ SignedJWT jwt = getJWT("alice", new Date(new Date().getTime() + 5000),
+ privateKey, props);
+
+ Cookie cookie = new Cookie("jowt", jwt.serialize());
+ HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+ EasyMock.expect(request.getCookies()).andReturn(new Cookie[] { cookie });
+ EasyMock.expect(request.getRequestURL()).andReturn(
+ new StringBuffer(SERVICE_URL)).anyTimes();
+ EasyMock.expect(request.getQueryString()).andReturn(null);
+ HttpServletResponse response = EasyMock.createNiceMock(HttpServletResponse.class);
+ EasyMock.expect(response.encodeRedirectURL(SERVICE_URL)).andReturn(
+ SERVICE_URL);
+ EasyMock.replay(request);
+
+ TestFilterChain chain = new TestFilterChain();
+ handler.doFilter(request, response, chain);
+ Assert.assertTrue("doFilterCalled should not be false.", chain.doFilterCalled == true);
+ Set<PrimaryPrincipal> principals = chain.subject.getPrincipals(PrimaryPrincipal.class);
+ Assert.assertTrue("No PrimaryPrincipal returned.", principals.size() > 0);
+ Assert.assertEquals("Not the expected principal", "alice", ((Principal)principals.toArray()[0]).getName());
+ } catch (ServletException se) {
+ fail("Should NOT have thrown a ServletException.");
+ }
+ }
+
+ @Test
+ public void testNoProviderURLJWT() throws Exception {
+ try {
+ Properties props = getProperties();
+ props.remove("sso.authentication.provider.url");
+ handler.init(new TestFilterConfig(props));
+
+ fail("Servlet exception should have been thrown.");
+
+ } catch (ServletException se) {
+ // expected - let's ensure it mentions the missing authentication provider URL
+ se.getMessage().contains("authentication provider URL is missing");
+ }
+ }
+
+/*
+ @Test
+ public void testFailedSignatureValidationJWT() throws Exception {
+ try {
+
+ // Create a public key that doesn't match the one needed to
+ // verify the signature - in order to make it fail verification...
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
+ kpg.initialize(2048);
+
+ KeyPair kp = kpg.genKeyPair();
+ RSAPublicKey publicKey = (RSAPublicKey) kp.getPublic();
+
+ handler.setPublicKey(publicKey);
+
+ Properties props = getProperties();
+ handler.init(props);
+
+ SignedJWT jwt = getJWT("bob", new Date(new Date().getTime() + 5000),
+ privateKey);
+
+ Cookie cookie = new Cookie("hadoop-jwt", jwt.serialize());
+ HttpServletRequest request = Mockito.mock(HttpServletRequest.class);
+ Mockito.when(request.getCookies()).thenReturn(new Cookie[] { cookie });
+ Mockito.when(request.getRequestURL()).thenReturn(
+ new StringBuffer(SERVICE_URL)).anyTimes();
+ HttpServletResponse response = Mockito.mock(HttpServletResponse.class);
+ Mockito.when(response.encodeRedirectURL(SERVICE_URL)).thenReturn(
+ SERVICE_URL);
+
+ AuthenticationToken token = handler.alternateAuthenticate(request,
+ response);
+ Mockito.verify(response).sendRedirect(REDIRECT_LOCATION);
+ } catch (ServletException se) {
+ fail("alternateAuthentication should NOT have thrown a ServletException");
+ } catch (AuthenticationException ae) {
+ fail("alternateAuthentication should NOT have thrown a AuthenticationException");
+ }
+ }
+*/
+
+ @Test
+ public void testOrigURLWithQueryString() throws Exception {
+ Properties props = getProperties();
+ handler.init(new TestFilterConfig(props));
+
+ HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+ EasyMock.expect(request.getRequestURL()).andReturn(
+ new StringBuffer(SERVICE_URL)).anyTimes();
+ EasyMock.expect(request.getQueryString()).andReturn("name=value");
+ EasyMock.replay(request);
+
+ String loginURL = ((TestSSOCookieFederationProvider)handler).testConstructLoginURL(request);
+ Assert.assertNotNull("loginURL should not be null.", loginURL);
+ Assert.assertEquals("https://localhost:8443/authserver?originalUrl=" + SERVICE_URL + "?name=value", loginURL);
+ }
+
+ @Test
+ public void testOrigURLNoQueryString() throws Exception {
+ Properties props = getProperties();
+ handler.init(new TestFilterConfig(props));
+
+ HttpServletRequest request = EasyMock.createNiceMock(HttpServletRequest.class);
+ EasyMock.expect(request.getRequestURL()).andReturn(
+ new StringBuffer(SERVICE_URL)).anyTimes();
+ EasyMock.expect(request.getQueryString()).andReturn(null);
+ EasyMock.replay(request);
+
+ String loginURL = ((TestSSOCookieFederationProvider)handler).testConstructLoginURL(request);
+ Assert.assertNotNull("LoginURL should not be null.", loginURL);
+ Assert.assertEquals("https://localhost:8443/authserver?originalUrl=" + SERVICE_URL, loginURL);
+ }
+
+
+ @Override
+ protected String getVerificationPemProperty() {
+ return SSOCookieFederationFilter.SSO_VERIFICATION_PEM;
+ };
+
+ private static class TestSSOCookieFederationProvider extends SSOCookieFederationFilter {
+ public String testConstructLoginURL(HttpServletRequest req) {
+ return constructLoginURL(req);
+ }
+
+ public void setTokenService(JWTokenAuthority ts) {
+ authority = ts;
+ }
+ };
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/Pac4jMessages.java
----------------------------------------------------------------------
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
deleted file mode 100644
index 931e494..0000000
--- a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/Pac4jMessages.java
+++ /dev/null
@@ -1,50 +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.i18n.messages.Message;
-import org.apache.hadoop.gateway.i18n.messages.MessageLevel;
-import org.apache.hadoop.gateway.i18n.messages.Messages;
-
-/**
- * Logging messages for the pac4j provider.
- *
- * @since 0.8.0
- */
-@Messages(logger="org.apache.hadoop.gateway.pac4j")
-public interface Pac4jMessages {
-
- @Message( level = MessageLevel.ERROR, text = "pac4j callback URL required")
- public void ssoAuthenticationProviderUrlRequired();
-
- @Message( level = MessageLevel.ERROR, text = "pac4j clientName parameter required")
- public void clientNameParameterRequired();
-
- @Message( level = MessageLevel.ERROR, text = "At least one pac4j client must be defined")
- public void atLeastOnePac4jClientMustBeDefined();
-
- @Message( level = MessageLevel.ERROR, text = "Crypto service, alias service and cluster name required")
- public void cryptoServiceAndAliasServiceAndClusterNameRequired();
-
- @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);
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/deploy/Pac4jFederationProviderContributor.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/deploy/Pac4jFederationProviderContributor.java b/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/deploy/Pac4jFederationProviderContributor.java
deleted file mode 100644
index c673ed5..0000000
--- a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/deploy/Pac4jFederationProviderContributor.java
+++ /dev/null
@@ -1,77 +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.deploy;
-
-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.topology.Provider;
-import org.apache.hadoop.gateway.topology.Service;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-
-/**
- * Descriptor of the pac4j provider. This module must be deployed for the KnoxSSO service.
- *
- * @since 0.8.0
- */
-public class Pac4jFederationProviderContributor extends ProviderDeploymentContributorBase {
-
- private static final String ROLE = "federation";
- private static final String NAME = "pac4j";
- private static final String DISPATCHER_FILTER_CLASSNAME = "org.apache.hadoop.gateway.pac4j.filter.Pac4jDispatcherFilter";
- private static final String IDENTITY_ADAPTER_CLASSNAME = "org.apache.hadoop.gateway.pac4j.filter.Pac4jIdentityAdapter";
-
- @Override
- public String getRole() {
- return ROLE;
- }
-
- @Override
- public String getName() {
- return NAME;
- }
-
- @Override
- public void initializeContribution(DeploymentContext context) {
- super.initializeContribution(context);
- }
-
- @Override
- public void contributeProvider(DeploymentContext context, Provider provider) {
- }
-
- @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() ).value( entry.getValue() ) );
- }
- resource.addFilter().name( getName() ).role( getRole() ).impl( DISPATCHER_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-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/filter/Pac4jDispatcherFilter.java
----------------------------------------------------------------------
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
deleted file mode 100644
index 574dea5..0000000
--- a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/filter/Pac4jDispatcherFilter.java
+++ /dev/null
@@ -1,215 +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.filter;
-
-import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
-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;
-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/hadoop/gateway/pac4j/filter/Pac4jIdentityAdapter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/filter/Pac4jIdentityAdapter.java b/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/filter/Pac4jIdentityAdapter.java
deleted file mode 100644
index ec5c368..0000000
--- a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/filter/Pac4jIdentityAdapter.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.pac4j.filter;
-
-import org.apache.hadoop.gateway.audit.api.*;
-import org.apache.hadoop.gateway.audit.log4j.audit.AuditConstants;
-import org.apache.hadoop.gateway.filter.AbstractGatewayFilter;
-import org.apache.hadoop.gateway.security.PrimaryPrincipal;
-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/hadoop/gateway/pac4j/session/KnoxSessionStore.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/session/KnoxSessionStore.java b/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/session/KnoxSessionStore.java
deleted file mode 100644
index 1d7c567..0000000
--- a/gateway-provider-security-pac4j/src/main/java/org/apache/hadoop/gateway/pac4j/session/KnoxSessionStore.java
+++ /dev/null
@@ -1,120 +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.session;
-
-import org.apache.commons.codec.binary.Base64;
-import org.apache.hadoop.gateway.services.security.CryptoService;
-import org.apache.hadoop.gateway.services.security.EncryptionResult;
-import org.apache.hadoop.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/java/org/apache/knox/gateway/pac4j/Pac4jMessages.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/Pac4jMessages.java b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/Pac4jMessages.java
new file mode 100644
index 0000000..32e07e6
--- /dev/null
+++ b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/Pac4jMessages.java
@@ -0,0 +1,50 @@
+/**
+ * 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.i18n.messages.Message;
+import org.apache.knox.gateway.i18n.messages.MessageLevel;
+import org.apache.knox.gateway.i18n.messages.Messages;
+
+/**
+ * Logging messages for the pac4j provider.
+ *
+ * @since 0.8.0
+ */
+@Messages(logger="org.apache.hadoop.gateway.pac4j")
+public interface Pac4jMessages {
+
+ @Message( level = MessageLevel.ERROR, text = "pac4j callback URL required")
+ public void ssoAuthenticationProviderUrlRequired();
+
+ @Message( level = MessageLevel.ERROR, text = "pac4j clientName parameter required")
+ public void clientNameParameterRequired();
+
+ @Message( level = MessageLevel.ERROR, text = "At least one pac4j client must be defined")
+ public void atLeastOnePac4jClientMustBeDefined();
+
+ @Message( level = MessageLevel.ERROR, text = "Crypto service, alias service and cluster name required")
+ public void cryptoServiceAndAliasServiceAndClusterNameRequired();
+
+ @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);
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/af9b0c3d/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/deploy/Pac4jFederationProviderContributor.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/deploy/Pac4jFederationProviderContributor.java b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/deploy/Pac4jFederationProviderContributor.java
new file mode 100644
index 0000000..f027dd3
--- /dev/null
+++ b/gateway-provider-security-pac4j/src/main/java/org/apache/knox/gateway/pac4j/deploy/Pac4jFederationProviderContributor.java
@@ -0,0 +1,78 @@
+/**
+ * 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.deploy;
+
+import org.apache.knox.gateway.deploy.DeploymentContext;
+import org.apache.knox.gateway.deploy.ProviderDeploymentContributorBase;
+import org.apache.knox.gateway.descriptor.FilterParamDescriptor;
+import org.apache.knox.gateway.descriptor.ResourceDescriptor;
+import org.apache.knox.gateway.topology.Provider;
+import org.apache.knox.gateway.topology.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * Descriptor of the pac4j provider. This module must be deployed for the KnoxSSO service.
+ *
+ * @since 0.8.0
+ */
+public class Pac4jFederationProviderContributor extends
+ ProviderDeploymentContributorBase {
+
+ private static final String ROLE = "federation";
+ private static final String NAME = "pac4j";
+ private static final String DISPATCHER_FILTER_CLASSNAME = "Pac4jDispatcherFilter";
+ private static final String IDENTITY_ADAPTER_CLASSNAME = "Pac4jIdentityAdapter";
+
+ @Override
+ public String getRole() {
+ return ROLE;
+ }
+
+ @Override
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public void initializeContribution(DeploymentContext context) {
+ super.initializeContribution(context);
+ }
+
+ @Override
+ public void contributeProvider(DeploymentContext context, Provider provider) {
+ }
+
+ @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() ).value( entry.getValue() ) );
+ }
+ resource.addFilter().name( getName() ).role( getRole() ).impl( DISPATCHER_FILTER_CLASSNAME ).params( params );
+ resource.addFilter().name( getName() ).role( getRole() ).impl( IDENTITY_ADAPTER_CLASSNAME ).params( params );
+ }
+}