You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by lm...@apache.org on 2017/01/26 22:35:07 UTC
knox git commit: POC commit to feature branch
Repository: knox
Updated Branches:
refs/heads/knoxinit [created] d6fda9c8d
POC commit to feature branch
Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/d6fda9c8
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/d6fda9c8
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/d6fda9c8
Branch: refs/heads/knoxinit
Commit: d6fda9c8d6b8d51f931dd715a4792c000820051f
Parents: ebc2ac8
Author: Larry McCay <lm...@hortonworks.com>
Authored: Thu Jan 26 17:34:09 2017 -0500
Committer: Larry McCay <lm...@hortonworks.com>
Committed: Thu Jan 26 17:34:09 2017 -0500
----------------------------------------------------------------------
.../jwt/filter/JWTFederationFilter.java | 29 ++--
gateway-release/pom.xml | 4 +
gateway-service-knoxtoken/pom.xml | 67 +++++++++
.../service/knoxtoken/TokenResource.java | 149 +++++++++++++++++++
.../service/knoxtoken/TokenServiceMessages.java | 66 ++++++++
.../TokenServiceDeploymentContributor.java | 55 +++++++
....gateway.deploy.ServiceDeploymentContributor | 19 +++
.../service/knoxsso/WebSSOResourceTest.java | 71 +++++++++
.../hadoop/gateway/shell/AbstractRequest.java | 22 +++
.../org/apache/hadoop/gateway/shell/Hadoop.java | 86 +++++++++++
.../shell/KnoxTokenCredentialCollector.java | 75 ++++++++++
.../hadoop/gateway/shell/knox/token/Get.java | 57 +++++++
.../hadoop/gateway/shell/knox/token/Token.java | 29 ++++
...che.hadoop.gateway.shell.CredentialCollector | 3 +-
pom.xml | 6 +
15 files changed, 722 insertions(+), 16 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/knox/blob/d6fda9c8/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTFederationFilter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTFederationFilter.java b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTFederationFilter.java
index 48bc51d..9a95421 100644
--- a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTFederationFilter.java
+++ b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTFederationFilter.java
@@ -20,6 +20,7 @@ package org.apache.hadoop.gateway.provider.federation.jwt.filter;
import org.apache.commons.logging.Log;
import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
import org.apache.hadoop.gateway.provider.federation.jwt.JWTMessages;
+import org.apache.hadoop.gateway.security.PrimaryPrincipal;
import org.apache.hadoop.gateway.services.GatewayServices;
import org.apache.hadoop.gateway.services.security.token.JWTokenAuthority;
import org.apache.hadoop.gateway.services.security.token.TokenServiceException;
@@ -65,11 +66,12 @@ public class JWTFederationFilter implements Filter {
// what follows the bearer designator should be the JWT token being used to request or as an access token
String wireToken = header.substring(BEARER.length());
JWTToken token;
- try {
- token = JWTToken.parseToken(wireToken);
- } catch (ParseException e) {
- throw new ServletException("ParseException encountered while processing the JWT token: ", e);
- }
+// try {
+ token = new JWTToken(wireToken);
+// token = JWTToken.parseToken(wireToken);
+// } catch (ParseException e) {
+// throw new ServletException("ParseException encountered while processing the JWT token: ", e);
+// }
boolean verified = false;
try {
verified = authority.verifyToken(token);
@@ -78,8 +80,8 @@ public class JWTFederationFilter implements Filter {
}
if (verified) {
// TODO: validate expiration
- // confirm that audience matches intended target - which for this filter must be HSSO
- if (token.getAudience().equals("HSSO")) {
+ // confirm that audience matches intended target - which for this filter must be KNOXSSO
+ if (token.getIssuer().equals("KNOXSSO")) {
// TODO: verify that the user requesting access to the service/resource is authorized for it - need scopes?
Subject subject = createSubjectFromToken(token);
continueWithEstablishedSecurityContext(subject, (HttpServletRequest)request, (HttpServletResponse)response, chain);
@@ -130,26 +132,23 @@ public class JWTFederationFilter implements Filter {
}
private Subject createSubjectFromToken(JWTToken token) {
- final String principal = token.getPrincipal();
+ final String principal = token.getSubject();
+ @SuppressWarnings("rawtypes")
HashSet emptySet = new HashSet();
Set<Principal> principals = new HashSet<Principal>();
- Principal p = new Principal() {
- @Override
- public String getName() {
- return principal;
- }
- };
+ Principal p = new PrimaryPrincipal(principal);
principals.add(p);
// The newly constructed Sets check whether this Subject has been set read-only
// before permitting subsequent modifications. The newly created Sets also prevent
// illegal modifications by ensuring that callers have sufficient permissions.
- //
+//
// To modify the Principals Set, the caller must have AuthPermission("modifyPrincipals").
// To modify the public credential Set, the caller must have AuthPermission("modifyPublicCredentials").
// To modify the private credential Set, the caller must have AuthPermission("modifyPrivateCredentials").
javax.security.auth.Subject subject = new javax.security.auth.Subject(true, principals, emptySet, emptySet);
return subject;
}
+
}
http://git-wip-us.apache.org/repos/asf/knox/blob/d6fda9c8/gateway-release/pom.xml
----------------------------------------------------------------------
diff --git a/gateway-release/pom.xml b/gateway-release/pom.xml
index 5b3e7c1..09c38fd 100644
--- a/gateway-release/pom.xml
+++ b/gateway-release/pom.xml
@@ -196,6 +196,10 @@
</dependency>
<dependency>
<groupId>${gateway-group}</groupId>
+ <artifactId>gateway-service-knoxtoken</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${gateway-group}</groupId>
<artifactId>gateway-provider-rewrite</artifactId>
</dependency>
<dependency>
http://git-wip-us.apache.org/repos/asf/knox/blob/d6fda9c8/gateway-service-knoxtoken/pom.xml
----------------------------------------------------------------------
diff --git a/gateway-service-knoxtoken/pom.xml b/gateway-service-knoxtoken/pom.xml
new file mode 100644
index 0000000..7c1d805
--- /dev/null
+++ b/gateway-service-knoxtoken/pom.xml
@@ -0,0 +1,67 @@
+<?xml version="1.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.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.knox</groupId>
+ <artifactId>gateway</artifactId>
+ <version>0.12.0-SNAPSHOT</version>
+ </parent>
+ <groupId>org.apache.knox</groupId>
+ <artifactId>gateway-service-knoxtoken</artifactId>
+ <version>0.12.0-SNAPSHOT</version>
+ <name>gateway-service-knoxtoken</name>
+ <url>http://maven.apache.org</url>
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+ <dependencies>
+ <dependency>
+ <groupId>${gateway-group}</groupId>
+ <artifactId>gateway-util-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${gateway-group}</groupId>
+ <artifactId>gateway-spi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${gateway-group}</groupId>
+ <artifactId>gateway-provider-rewrite</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${gateway-group}</groupId>
+ <artifactId>gateway-provider-jersey</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.knox</groupId>
+ <artifactId>gateway-test-utils</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency> </dependencies>
+</project>
http://git-wip-us.apache.org/repos/asf/knox/blob/d6fda9c8/gateway-service-knoxtoken/src/main/java/org/apache/hadoop/gateway/service/knoxtoken/TokenResource.java
----------------------------------------------------------------------
diff --git a/gateway-service-knoxtoken/src/main/java/org/apache/hadoop/gateway/service/knoxtoken/TokenResource.java b/gateway-service-knoxtoken/src/main/java/org/apache/hadoop/gateway/service/knoxtoken/TokenResource.java
new file mode 100644
index 0000000..0d7688a
--- /dev/null
+++ b/gateway-service-knoxtoken/src/main/java/org/apache/hadoop/gateway/service/knoxtoken/TokenResource.java
@@ -0,0 +1,149 @@
+/**
+ * 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.service.knoxtoken;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import javax.annotation.PostConstruct;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.Response;
+import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
+import org.apache.hadoop.gateway.services.GatewayServices;
+import org.apache.hadoop.gateway.services.security.token.JWTokenAuthority;
+import org.apache.hadoop.gateway.services.security.token.TokenServiceException;
+import org.apache.hadoop.gateway.services.security.token.impl.JWT;
+import org.apache.hadoop.gateway.util.JsonUtils;
+import static javax.ws.rs.core.MediaType.APPLICATION_JSON;
+import static javax.ws.rs.core.MediaType.APPLICATION_XML;
+
+@Path( TokenResource.RESOURCE_PATH )
+public class TokenResource {
+ private static final String EXPIRES_IN = "expires_in";
+ private static final String TOKEN_TYPE = "token_type";
+ private static final String ACCESS_TOKEN = "access_token";
+ private static final String BEARER = "Bearer ";
+ private static final String TOKEN_TTL_PARAM = "knox.token.ttl";
+ private static final String TOKEN_AUDIENCES_PARAM = "knox.token.audiences";
+ static final String RESOURCE_PATH = "knoxtoken/api/v1/token";
+ private static TokenServiceMessages log = MessagesFactory.get( TokenServiceMessages.class );
+ private long tokenTTL = 30000l;
+ private String[] targetAudiences = null;
+
+ @Context
+ private HttpServletRequest request;
+
+ @Context
+ private HttpServletResponse response;
+
+ @Context
+ ServletContext context;
+
+ @PostConstruct
+ public void init() {
+
+ String audiences = context.getInitParameter(TOKEN_AUDIENCES_PARAM);
+ if (audiences != null) {
+ targetAudiences = audiences.split(",");
+ }
+
+ String ttl = context.getInitParameter(TOKEN_TTL_PARAM);
+ if (ttl != null) {
+ try {
+ tokenTTL = Long.parseLong(ttl);
+ }
+ catch (NumberFormatException nfe) {
+ log.invalidTokenTTLEncountered(ttl);
+ }
+ }
+ }
+
+ @GET
+ @Produces({APPLICATION_JSON, APPLICATION_XML})
+ public Response doGet() {
+ return getAuthenticationToken();
+ }
+
+ @POST
+ @Produces({APPLICATION_JSON, APPLICATION_XML})
+ public Response doPost() {
+ return getAuthenticationToken();
+ }
+
+ private Response getAuthenticationToken() {
+ GatewayServices services = (GatewayServices) request.getServletContext()
+ .getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
+
+ JWTokenAuthority ts = services.getService(GatewayServices.TOKEN_SERVICE);
+ Principal p = ((HttpServletRequest)request).getUserPrincipal();
+ long expires = getExpiry();
+
+ try {
+ JWT token = null;
+ if (targetAudiences == null || targetAudiences.length == 0) {
+ token = ts.issueToken(p, "RS256", getExpiry());
+ } else {
+ ArrayList<String> aud = new ArrayList<String>();
+ for (int i = 0; i < targetAudiences.length; i++) {
+ aud.add(targetAudiences[i]);
+ }
+ token = ts.issueToken(p, aud, "RS256", expires);
+ }
+
+ String accessToken = token.toString();
+
+ HashMap<String, Object> map = new HashMap<String, Object>();
+ // TODO: populate map from JWT authorization code
+ map.put(ACCESS_TOKEN, accessToken);
+ map.put(TOKEN_TYPE, BEARER);
+ map.put(EXPIRES_IN, expires);
+
+ String jsonResponse = JsonUtils.renderAsJsonString(map);
+
+ response.getWriter().write(jsonResponse);
+ //KNOX-685: response.getWriter().flush();
+// return response; // break filter chain
+ return Response.ok().build();
+
+ }
+ catch (TokenServiceException | IOException e) {
+ log.unableToIssueToken(e);
+ }
+
+ return Response.ok().entity("{ \"Unable to acquire token.\" }").build();
+ }
+
+ private long getExpiry() {
+ long expiry = 0l;
+ if (tokenTTL == -1) {
+ expiry = -1;
+ }
+ else {
+ expiry = System.currentTimeMillis() + tokenTTL;
+ }
+ return expiry;
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/d6fda9c8/gateway-service-knoxtoken/src/main/java/org/apache/hadoop/gateway/service/knoxtoken/TokenServiceMessages.java
----------------------------------------------------------------------
diff --git a/gateway-service-knoxtoken/src/main/java/org/apache/hadoop/gateway/service/knoxtoken/TokenServiceMessages.java b/gateway-service-knoxtoken/src/main/java/org/apache/hadoop/gateway/service/knoxtoken/TokenServiceMessages.java
new file mode 100644
index 0000000..b590614
--- /dev/null
+++ b/gateway-service-knoxtoken/src/main/java/org/apache/hadoop/gateway/service/knoxtoken/TokenServiceMessages.java
@@ -0,0 +1,66 @@
+/**
+ * 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.service.knoxtoken;
+
+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.service.knoxsso")
+public interface TokenServiceMessages {
+ @Message( level = MessageLevel.INFO, text = "About to redirect to original URL: {0}")
+ void aboutToRedirectToOriginal(String original);
+
+ @Message( level = MessageLevel.DEBUG, text = "Adding the following JWT token as a cookie: {0}")
+ void addingJWTCookie(String token);
+
+ @Message( level = MessageLevel.INFO, text = "Unable to find cookie with name: {0}")
+ void cookieNotFound(String name);
+
+ @Message( level = MessageLevel.ERROR, text = "Unable to properly send needed HTTP status code: {0}, {1}")
+ void unableToCloseOutputStream(String message, String string);
+
+ @Message( level = MessageLevel.ERROR, text = "Unable to add cookie to response. {0}: {1}")
+ void unableAddCookieToResponse(String message, String stackTrace);
+
+ @Message( level = MessageLevel.ERROR, text = "Original URL not found in request.")
+ void originalURLNotFound();
+
+ @Message( level = MessageLevel.INFO, text = "JWT cookie successfully added.")
+ void addedJWTCookie();
+
+ @Message( level = MessageLevel.ERROR, text = "Unable to issue token.")
+ void unableToIssueToken(@StackTrace( level = MessageLevel.DEBUG) Exception e);
+
+ @Message( level = MessageLevel.WARN, text = "The SSO cookie SecureOnly flag is set to FALSE and is therefore insecure.")
+ void cookieSecureOnly(boolean secureOnly);
+
+ @Message( level = MessageLevel.WARN, text = "The SSO cookie max age configuration is invalid: {0} - using default.")
+ void invalidMaxAgeEncountered(String age);
+
+ @Message( level = MessageLevel.WARN, text = "The SSO token time to live - ttl is invalid: {0} - using default.")
+ void invalidTokenTTLEncountered(String ttl);
+
+ @Message( level = MessageLevel.INFO, text = "The cookie max age is being set to: {0}.")
+ void setMaxAge(String age);
+
+ @Message( level = MessageLevel.ERROR, text = "The original URL: {0} for redirecting back after authentication is " +
+ "not valid according to the configured whitelist: {1}. See documentation for KnoxSSO Whitelisting.")
+ void whiteListMatchFail(String original, String whitelist);
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/d6fda9c8/gateway-service-knoxtoken/src/main/java/org/apache/hadoop/gateway/service/knoxtoken/deploy/TokenServiceDeploymentContributor.java
----------------------------------------------------------------------
diff --git a/gateway-service-knoxtoken/src/main/java/org/apache/hadoop/gateway/service/knoxtoken/deploy/TokenServiceDeploymentContributor.java b/gateway-service-knoxtoken/src/main/java/org/apache/hadoop/gateway/service/knoxtoken/deploy/TokenServiceDeploymentContributor.java
new file mode 100644
index 0000000..cc92732
--- /dev/null
+++ b/gateway-service-knoxtoken/src/main/java/org/apache/hadoop/gateway/service/knoxtoken/deploy/TokenServiceDeploymentContributor.java
@@ -0,0 +1,55 @@
+/**
+ * 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.service.knoxtoken.deploy;
+
+import org.apache.hadoop.gateway.jersey.JerseyServiceDeploymentContributorBase;
+
+public class TokenServiceDeploymentContributor extends JerseyServiceDeploymentContributorBase {
+
+ /* (non-Javadoc)
+ * @see org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor#getRole()
+ */
+ @Override
+ public String getRole() {
+ return "KNOXTOKEN";
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor#getName()
+ */
+ @Override
+ public String getName() {
+ return "KnoxTokenService";
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.hadoop.gateway.jersey.JerseyServiceDeploymentContributorBase#getPackages()
+ */
+ @Override
+ protected String[] getPackages() {
+ return new String[]{ "org.apache.hadoop.gateway.service.knoxtoken" };
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.hadoop.gateway.jersey.JerseyServiceDeploymentContributorBase#getPatterns()
+ */
+ @Override
+ protected String[] getPatterns() {
+ return new String[]{ "knoxtoken/api/**?**" };
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/d6fda9c8/gateway-service-knoxtoken/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor
----------------------------------------------------------------------
diff --git a/gateway-service-knoxtoken/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor b/gateway-service-knoxtoken/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor
new file mode 100644
index 0000000..d250459
--- /dev/null
+++ b/gateway-service-knoxtoken/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor
@@ -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.hadoop.gateway.service.knoxtoken.deploy.TokenServiceDeploymentContributor
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/d6fda9c8/gateway-service-knoxtoken/src/test/java/org/apache/hadoop/gateway/service/knoxsso/WebSSOResourceTest.java
----------------------------------------------------------------------
diff --git a/gateway-service-knoxtoken/src/test/java/org/apache/hadoop/gateway/service/knoxsso/WebSSOResourceTest.java b/gateway-service-knoxtoken/src/test/java/org/apache/hadoop/gateway/service/knoxsso/WebSSOResourceTest.java
new file mode 100644
index 0000000..73910dd
--- /dev/null
+++ b/gateway-service-knoxtoken/src/test/java/org/apache/hadoop/gateway/service/knoxsso/WebSSOResourceTest.java
@@ -0,0 +1,71 @@
+/**
+ * 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.service.knoxsso;
+
+import org.apache.hadoop.gateway.util.RegExUtils;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class WebSSOResourceTest {
+
+ @Test
+ public void testWhitelistMatching() throws Exception {
+ String whitelist = "^https?://.*example.com:8080/.*$;" +
+ "^https?://.*example.com/.*$;" +
+ "^https?://.*example2.com:\\d{0,9}/.*$;" +
+ "^https://.*example3.com:\\d{0,9}/.*$;" +
+ "^https?://localhost:\\d{0,9}/.*$;^/.*$";
+
+ // match on explicit hostname/domain and port
+ Assert.assertTrue("Failed to match whitelist", RegExUtils.checkWhitelist(whitelist,
+ "http://host.example.com:8080/"));
+ // match on non-required port
+ Assert.assertTrue("Failed to match whitelist", RegExUtils.checkWhitelist(whitelist,
+ "http://host.example.com/"));
+ // match on required but any port
+ Assert.assertTrue("Failed to match whitelist", RegExUtils.checkWhitelist(whitelist,
+ "http://host.example2.com:1234/"));
+ // fail on missing port
+ Assert.assertFalse("Matched whitelist inappropriately", RegExUtils.checkWhitelist(whitelist,
+ "http://host.example2.com/"));
+ // fail on invalid port
+ Assert.assertFalse("Matched whitelist inappropriately", RegExUtils.checkWhitelist(whitelist,
+ "http://host.example.com:8081/"));
+ // fail on alphanumeric port
+ Assert.assertFalse("Matched whitelist inappropriately", RegExUtils.checkWhitelist(whitelist,
+ "http://host.example.com:A080/"));
+ // fail on invalid hostname/domain
+ Assert.assertFalse("Matched whitelist inappropriately", RegExUtils.checkWhitelist(whitelist,
+ "http://host.example.net:8080/"));
+ // fail on required port
+ Assert.assertFalse("Matched whitelist inappropriately", RegExUtils.checkWhitelist(whitelist,
+ "http://host.example2.com/"));
+ // fail on required https
+ Assert.assertFalse("Matched whitelist inappropriately", RegExUtils.checkWhitelist(whitelist,
+ "http://host.example3.com/"));
+ // match on localhost and port
+ Assert.assertTrue("Failed to match whitelist", RegExUtils.checkWhitelist(whitelist,
+ "http://localhost:8080/"));
+ // match on local/relative path
+ Assert.assertTrue("Failed to match whitelist", RegExUtils.checkWhitelist(whitelist,
+ "/local/resource/"));
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/d6fda9c8/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/AbstractRequest.java
----------------------------------------------------------------------
diff --git a/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/AbstractRequest.java b/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/AbstractRequest.java
index 67ee7ad..4c5dfb3 100644
--- a/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/AbstractRequest.java
+++ b/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/AbstractRequest.java
@@ -28,6 +28,7 @@ import org.apache.http.message.BasicNameValuePair;
import java.io.IOException;
import java.net.URISyntaxException;
import java.util.List;
+import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;
@@ -44,9 +45,30 @@ public abstract class AbstractRequest<T> {
}
protected CloseableHttpResponse execute(HttpRequest request ) throws IOException {
+ addHeaders(request, session.getHeaders());
return session.executeNow( request );
}
+ /**
+ * @param request
+ * @param headers
+ */
+ private void removeHeaders(HttpRequest request, Map<String, String> headers) {
+ for(String header : headers.keySet()) {
+ request.removeHeaders(header);
+ }
+ }
+
+ /**
+ * @param request
+ * @param headers
+ */
+ private void addHeaders(HttpRequest request, Map<String, String> headers) {
+ for(String header : headers.keySet()) {
+ request.setHeader(header, headers.get(header));
+ }
+ }
+
protected URIBuilder uri( String... parts ) throws URISyntaxException {
return new URIBuilder( session.base() + StringUtils.join( parts ) );
}
http://git-wip-us.apache.org/repos/asf/knox/blob/d6fda9c8/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/Hadoop.java
----------------------------------------------------------------------
diff --git a/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/Hadoop.java b/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/Hadoop.java
index 1fe28b1..b2e186f 100644
--- a/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/Hadoop.java
+++ b/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/Hadoop.java
@@ -59,6 +59,8 @@ import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
+import java.util.HashMap;
+import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
@@ -80,6 +82,15 @@ public class Hadoop implements Closeable {
CloseableHttpClient client;
BasicHttpContext context;
ExecutorService executor;
+ Map<String, String> headers = new HashMap<String, String>();
+
+ public Map<String, String> getHeaders() {
+ return headers;
+ }
+
+ public void setHeaders(Map<String, String> headers) {
+ this.headers = headers;
+ }
public static Hadoop login( String url, String username, String password ) throws URISyntaxException {
return new Hadoop(ClientContext.with(username, password, url));
@@ -90,11 +101,29 @@ public class Hadoop implements Closeable {
.connection().secure(false).end());
}
+<<<<<<< Updated upstream
public Hadoop( ClientContext clientContext) throws HadoopException, URISyntaxException {
+=======
+ public static Hadoop login(String url, Map<String, String> headers) throws URISyntaxException {
+ return new Hadoop( url, headers, true );
+ }
+
+ private Hadoop( String url, Map<String, String> headers ) throws HadoopException, URISyntaxException {
+ this(url, null, null, false);
+ this.headers = headers;
+ }
+
+ private Hadoop( String url, String username, String password ) throws HadoopException, URISyntaxException {
+ this(url, username, password, false);
+ }
+
+ private Hadoop( String url, String username, String password, boolean secure ) throws HadoopException, URISyntaxException {
+>>>>>>> Stashed changes
this.executor = Executors.newCachedThreadPool();
this.base = clientContext.url();
try {
+<<<<<<< Updated upstream
client = createClient(clientContext);
} catch (GeneralSecurityException e) {
throw new HadoopException("Failed to create HTTP client.", e);
@@ -118,6 +147,63 @@ public class Hadoop implements Closeable {
+ "*******************************************");
}
+=======
+ if (!secure) {
+ client = createInsecureClient();
+ }
+ else {
+ client = createClient();
+ }
+ if (username != null && password != null) {
+ client.getCredentialsProvider().setCredentials(
+ new AuthScope( host.getHostName(), host.getPort() ),
+ new UsernamePasswordCredentials( username, password ) );
+ AuthCache authCache = new BasicAuthCache();
+ BasicScheme authScheme = new BasicScheme();
+ authCache.put( host, authScheme );
+ context = new BasicHttpContext();
+ context.setAttribute( ClientContext.AUTH_CACHE, authCache );
+ }
+ } catch( GeneralSecurityException e ) {
+ throw new HadoopException( "Failed to create HTTP client.", e );
+ }
+ }
+
+ private Hadoop(String url, Map<String,String> headers, boolean secure)
+ throws HadoopException, URISyntaxException {
+ this.executor = Executors.newCachedThreadPool();
+ this.base = url;
+ this.headers = headers;
+
+ URI uri = new URI( url );
+ host = new HttpHost( uri.getHost(), uri.getPort(), uri.getScheme() );
+
+ try {
+ if (!secure) {
+ client = createInsecureClient();
+ }
+ else {
+ client = createClient();
+ }
+ if (username != null && password != null) {
+ client.getCredentialsProvider().setCredentials(
+ new AuthScope( host.getHostName(), host.getPort() ),
+ new UsernamePasswordCredentials( username, password ) );
+ AuthCache authCache = new BasicAuthCache();
+ BasicScheme authScheme = new BasicScheme();
+ authCache.put( host, authScheme );
+ context = new BasicHttpContext();
+ context.setAttribute( ClientContext.AUTH_CACHE, authCache );
+ }
+ } catch( GeneralSecurityException e ) {
+ throw new HadoopException( "Failed to create HTTP client.", e );
+ }
+ }
+
+
+ private static DefaultHttpClient createClient() throws GeneralSecurityException {
+ SchemeRegistry registry = new SchemeRegistry();
+>>>>>>> Stashed changes
KeyStore trustStore = getTrustStore();
SSLContext sslContext = SSLContexts.custom().loadTrustMaterial(trustStore, trustStrategy).build();
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
http://git-wip-us.apache.org/repos/asf/knox/blob/d6fda9c8/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/KnoxTokenCredentialCollector.java
----------------------------------------------------------------------
diff --git a/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/KnoxTokenCredentialCollector.java b/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/KnoxTokenCredentialCollector.java
new file mode 100644
index 0000000..9972da2
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/KnoxTokenCredentialCollector.java
@@ -0,0 +1,75 @@
+/**
+ * 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.shell;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.hadoop.gateway.util.JsonUtils;
+
+public class KnoxTokenCredentialCollector extends AbstractCredentialCollector {
+ /**
+ *
+ */
+ private static final String KNOXTOKENCACHE = ".knoxtokencache";
+ public static final String COLLECTOR_TYPE = "KnoxToken";
+ /* (non-Javadoc)
+ * @see org.apache.hadoop.gateway.shell.CredentialCollector#collect()
+ */
+ @Override
+ public void collect() throws CredentialCollectionException {
+ String userDir = System.getProperty("user.home");
+ File knoxtoken = new File(userDir, KNOXTOKENCACHE);
+ if (knoxtoken.exists()) {
+ Path path = Paths.get(knoxtoken.toURI());
+ List<String> lines;
+ try {
+ lines = Files.readAllLines(path, StandardCharsets.UTF_8);
+ Map<String, String> attrs = JsonUtils.getMapFromJsonString(lines.get(0));
+ value = attrs.get("access_token");
+ Date expires = new Date(Long.parseLong(attrs.get("expires_in")));
+ if (expires.before(new Date())) {
+ System.out.println("Cached knox token has expired. Please relogin through knoxinit.");
+ System.exit(1);
+ }
+ } catch (IOException e) {
+ System.out.println("Cached knox token cannot be read. Please login through knoxinit.");
+ System.exit(1);
+ e.printStackTrace();
+ }
+ } else {
+ System.out.println("Cached knox token cannot be found. Please login through knoxinit.");
+ System.exit(1);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.hadoop.gateway.shell.CredentialCollector#name()
+ */
+ @Override
+ public String type() {
+ return COLLECTOR_TYPE;
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/d6fda9c8/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/knox/token/Get.java
----------------------------------------------------------------------
diff --git a/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/knox/token/Get.java b/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/knox/token/Get.java
new file mode 100644
index 0000000..f946db5
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/knox/token/Get.java
@@ -0,0 +1,57 @@
+/**
+ * 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.shell.knox.token;
+
+import java.io.IOException;
+import java.util.concurrent.Callable;
+
+import org.apache.hadoop.gateway.shell.AbstractRequest;
+import org.apache.hadoop.gateway.shell.BasicResponse;
+import org.apache.hadoop.gateway.shell.Hadoop;
+import org.apache.http.HttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.utils.URIBuilder;
+
+/**
+ * Acquire a Knox access token for token based authentication
+ * to access REST APIs
+ */
+public class Get {
+ public static class Request extends AbstractRequest<Response> {
+ Request(Hadoop session) {
+ super(session);
+ }
+
+ protected Callable<Response> callable() {
+ return new Callable<Response>() {
+ @Override
+ public Response call() throws Exception {
+ URIBuilder uri = uri(Token.SERVICE_PATH);
+ HttpGet request = new HttpGet(uri.build());
+ return new Response(execute(request));
+ }
+ };
+ }
+ }
+
+ public static class Response extends BasicResponse {
+ Response(HttpResponse response) throws IOException {
+ super(response);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/d6fda9c8/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/knox/token/Token.java
----------------------------------------------------------------------
diff --git a/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/knox/token/Token.java b/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/knox/token/Token.java
new file mode 100644
index 0000000..b7f5115
--- /dev/null
+++ b/gateway-shell/src/main/java/org/apache/hadoop/gateway/shell/knox/token/Token.java
@@ -0,0 +1,29 @@
+/**
+ * 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.shell.knox.token;
+
+import org.apache.hadoop.gateway.shell.Hadoop;
+
+public class Token {
+
+ static String SERVICE_PATH = "/knoxtoken/api/v1/token";
+
+ public static Get.Request get( Hadoop session ) {
+ return new Get.Request( session );
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/d6fda9c8/gateway-shell/src/main/resources/META-INF/services/org.apache.hadoop.gateway.shell.CredentialCollector
----------------------------------------------------------------------
diff --git a/gateway-shell/src/main/resources/META-INF/services/org.apache.hadoop.gateway.shell.CredentialCollector b/gateway-shell/src/main/resources/META-INF/services/org.apache.hadoop.gateway.shell.CredentialCollector
index eb6d5b8..e4f8462 100644
--- a/gateway-shell/src/main/resources/META-INF/services/org.apache.hadoop.gateway.shell.CredentialCollector
+++ b/gateway-shell/src/main/resources/META-INF/services/org.apache.hadoop.gateway.shell.CredentialCollector
@@ -17,4 +17,5 @@
##########################################################################
org.apache.hadoop.gateway.shell.ClearInputCredentialCollector
-org.apache.hadoop.gateway.shell.HiddenInputCredentialCollector
\ No newline at end of file
+org.apache.hadoop.gateway.shell.HiddenInputCredentialCollector
+org.apache.hadoop.gateway.shell.KnoxTokenCredentialCollector
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/d6fda9c8/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 43ad583..c317165 100644
--- a/pom.xml
+++ b/pom.xml
@@ -76,6 +76,7 @@
<module>gateway-service-hive</module>
<module>gateway-service-knoxsso</module>
<module>gateway-service-knoxssout</module>
+ <module>gateway-service-knoxtoken</module>
<module>gateway-service-webhdfs</module>
<module>gateway-service-tgs</module>
<module>gateway-service-storm</module>
@@ -582,6 +583,11 @@
</dependency>
<dependency>
<groupId>${gateway-group}</groupId>
+ <artifactId>gateway-service-knoxtoken</artifactId>
+ <version>${gateway-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${gateway-group}</groupId>
<artifactId>gateway-service-admin</artifactId>
<version>${gateway-version}</version>
</dependency>