knox-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From lmc...@apache.org
Subject [4/4] git commit: POC work and related changes to support a Knox SSO solution
Date Wed, 10 Jul 2013 14:25:23 GMT
POC work and related changes to support a Knox SSO solution

Project: http://git-wip-us.apache.org/repos/asf/incubator-knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-knox/commit/21e6d1da
Tree: http://git-wip-us.apache.org/repos/asf/incubator-knox/tree/21e6d1da
Diff: http://git-wip-us.apache.org/repos/asf/incubator-knox/diff/21e6d1da

Branch: refs/heads/master
Commit: 21e6d1da388df03e2fd00880ebb258c251ddadbf
Parents: e98c682
Author: Larry McCay <lmccay@hortonworks.com>
Authored: Wed Jul 10 10:23:11 2013 -0400
Committer: Larry McCay <lmccay@hortonworks.com>
Committed: Wed Jul 10 10:23:11 2013 -0400

----------------------------------------------------------------------
 gateway-provider-security-jwt/pom.xml           |    4 -
 .../provider/federation/jwt/AccessToken.java    |   87 --
 .../provider/federation/jwt/JWTAuthority.java   |   81 --
 .../provider/federation/jwt/JWTMessages.java    |   31 +
 .../federation/jwt/JWTProviderMessages.java     |   49 -
 .../provider/federation/jwt/JWTToken.java       |  135 --
 .../jwt/filter/AccessTokenFederationFilter.java |   24 +-
 .../filter/JWTAccessTokenAssertionFilter.java   |   23 +-
 .../jwt/filter/JWTAuthCodeAssertionFilter.java  |   25 +-
 .../jwt/filter/JWTFederationFilter.java         |   12 +-
 .../provider/federation/JWTTokenTest.java       |    3 +-
 gateway-release/src/assembly.xml                |    4 +-
 ...ache.hadoop.gateway.services.GatewayServices |   20 +
 .../apache/hadoop/gateway/GatewayMessages.java  |   10 +
 .../apache/hadoop/gateway/GatewayServer.java    |   30 +-
 .../gateway/deploy/DeploymentFactory.java       |   14 +-
 .../services/DefaultGatewayServices.java        |   18 +-
 .../gateway/services/HssoGatewayServices.java   |  177 +++
 .../impl/DefaultServiceRegistryService.java     |  191 +++
 .../services/registry/impl/RegEntry.java        |   52 +
 .../services/registry/impl/Registry.java        |   33 +
 .../security/impl/DefaultAliasService.java      |    4 -
 .../impl/DefaultTokenAuthorityService.java      |  116 ++
 gateway-spi/pom.xml                             |    5 +
 .../gateway/services/GatewayServices.java       |    6 +-
 .../services/registry/ServiceRegistry.java      |   30 +
 .../security/token/JWTokenAuthority.java        |   36 +
 .../token/impl/JWTProviderMessages.java         |   48 +
 .../services/security/token/impl/JWTToken.java  |  135 ++
 hsso-release/home/CHANGES                       |   15 +
 hsso-release/home/DISCLAIMER                    |   15 +
 hsso-release/home/INSTALL                       |  251 ++++
 hsso-release/home/ISSUES                        |   10 +
 hsso-release/home/LICENSE                       | 1332 ++++++++++++++++++
 hsso-release/home/NOTICE                        |  107 ++
 hsso-release/home/README                        |   87 ++
 hsso-release/home/bin/knox.sh                   |  265 ++++
 hsso-release/home/conf/README                   |    1 +
 hsso-release/home/conf/gateway-site.xml         |   39 +
 hsso-release/home/conf/log4j.properties         |   29 +
 hsso-release/home/conf/users.ldif               |   36 +
 hsso-release/home/deployments/BASIC.xml         |   56 +
 hsso-release/home/deployments/README            |    1 +
 hsso-release/home/deployments/sample.xml        |   46 +
 hsso-release/home/deployments/token.xml         |   37 +
 hsso-release/home/ext/README                    |    1 +
 hsso-release/home/lib/README                    |    1 +
 hsso-release/home/templates/topology.xml        |   62 +
 hsso-release/home/templates/users.ldif          |   36 +
 .../home/templates/workflow-configuration.xml   |   47 +
 .../home/templates/workflow-definition.xml      |   36 +
 hsso-release/pom.xml                            |  177 +++
 hsso-release/src/assembly.xml                   |   86 ++
 ...ache.hadoop.gateway.services.GatewayServices |   20 +
 pom.xml                                         |    6 +
 55 files changed, 3785 insertions(+), 417 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-provider-security-jwt/pom.xml
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/pom.xml b/gateway-provider-security-jwt/pom.xml
index 7364096..498b126 100644
--- a/gateway-provider-security-jwt/pom.xml
+++ b/gateway-provider-security-jwt/pom.xml
@@ -56,10 +56,6 @@
             <artifactId>commons-codec</artifactId>
         </dependency>
 
-        <dependency>
-            <groupId>com.jayway.jsonpath</groupId>
-            <artifactId>json-path</artifactId>
-        </dependency>
 
         <dependency>
             <groupId>junit</groupId>

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/AccessToken.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/AccessToken.java b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/AccessToken.java
deleted file mode 100644
index f765e8e..0000000
--- a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/AccessToken.java
+++ /dev/null
@@ -1,87 +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.jwt;
-
-import java.io.UnsupportedEncodingException;
-
-import org.apache.commons.codec.binary.Base64;
-import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
-import org.apache.hadoop.gateway.services.security.CryptoService;
-import org.apache.hadoop.gateway.services.security.EncryptionResult;
-
-public class AccessToken {
-  private static final String ENCRYPT_ACCESS_TOKENS = "encrypt_access_tokens";
-  private static final String GATEWAY = "__gateway";
-  private static final JWTProviderMessages LOG = MessagesFactory.get( JWTProviderMessages.class );
-  
-  private CryptoService crypto = null;
-  private String tokenStr = null;
-  private String principalName;
-  private long expires;
-  
-  public AccessToken(CryptoService crypto, String principalName, long expires) {
-    this.crypto = crypto;
-    this.principalName = principalName;
-    this.expires = expires;
-  }
-  
-  public String toString() {
-    if (tokenStr != null) {
-      return tokenStr;
-    }
-    String claims = principalName + "::" + expires;
-    EncryptionResult result;
-    try {
-      result = crypto.encryptForCluster(GATEWAY, ENCRYPT_ACCESS_TOKENS, claims.getBytes("UTF-8"));
-      tokenStr = Base64.encodeBase64URLSafeString(result.iv) + "+" + 
-          Base64.encodeBase64URLSafeString(result.salt) + "+" + 
-          Base64.encodeBase64URLSafeString(result.cipher);
-    } catch (UnsupportedEncodingException e) {
-      LOG.unsupportedEncoding( e );
-    }
-    return tokenStr;
-  }
-  
-  public static AccessToken parseToken(CryptoService crypto, String wireToken) {
-    AccessToken token = null;
-    String[] parts = wireToken.split("\\+");
-    byte[] bytes = crypto.decryptForCluster(GATEWAY, ENCRYPT_ACCESS_TOKENS, Base64.decodeBase64(parts[2]), Base64.decodeBase64(parts[0]), Base64.decodeBase64(parts[1]));
-    
-    try {
-      String claims = new String(bytes, "UTF-8");
-      String[] claimz = claims.split("\\::");
-      token = new AccessToken(crypto, claimz[0], Long.parseLong(claimz[1]));
-      token.setTokenStr(wireToken);
-    } catch (UnsupportedEncodingException e) {
-      LOG.unsupportedEncoding( e );
-    }
-    return token;
-  }
-  
-  private void setTokenStr(String wireToken) {
-    this.tokenStr = wireToken;
-  }
-
-  public String getPrincipalName() {
-    return principalName;
-  }
-  
-  public long getExpires() {
-    return expires;
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/JWTAuthority.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/JWTAuthority.java b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/JWTAuthority.java
deleted file mode 100644
index d8c86ae..0000000
--- a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/JWTAuthority.java
+++ /dev/null
@@ -1,81 +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.jwt;
-
-import java.security.Principal;
-
-import javax.security.auth.Subject;
-
-import org.apache.hadoop.gateway.services.security.AliasService;
-import org.apache.hadoop.gateway.services.security.CryptoService;
-
-public class JWTAuthority {
-  private CryptoService crypto = null;
-  
-  public JWTAuthority(CryptoService crypto) {
-    this.crypto = crypto;
-  }
-  
-  public JWTToken issueToken(Subject subject, String algorithm) {
-    Principal p = (Principal) subject.getPrincipals().toArray()[0];
-    return issueToken(p, algorithm);
-  }
-  
-  public JWTToken issueToken(Principal p, String algorithm) {
-    return issueToken(p, null, algorithm);
-  }
-  
-  public JWTToken issueToken(Principal p, String audience, String algorithm) {
-    String[] claimArray = new String[4];
-    claimArray[0] = "HSSO";
-    claimArray[1] = p.getName();
-    if (audience == null) {
-      audience = "HSSO";
-    }
-    claimArray[2] = audience;
-    // TODO: make the validity period configurable
-    claimArray[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
-
-    JWTToken token = null;
-    if ("RS256".equals(algorithm)) {
-      token = new JWTToken("RS256", claimArray);
-      signToken(token);
-    }
-    else {
-      // log inappropriate alg
-    }
-    
-    return token;
-  }
-
-  private void signToken(JWTToken token) {
-    byte[] signature = null;
-    signature = crypto.sign("SHA256withRSA","gateway-identity",token.getPayloadToSign());
-    token.setSignaturePayload(signature);
-  }
-  
-  public boolean verifyToken(JWTToken token) {
-    boolean rc = false;
-    
-    // TODO: interrogate the token for issuer claim in order to determine the public key to use for verification
-    // consider jwk for specifying the key too
-    rc = crypto.verify("SHA256withRSA", "gateway-identity", token.getPayloadToSign(), token.getSignaturePayload());
-    return rc;
-  }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/JWTMessages.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/JWTMessages.java b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/JWTMessages.java
new file mode 100644
index 0000000..1f3b302
--- /dev/null
+++ b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/JWTMessages.java
@@ -0,0 +1,31 @@
+/**
+ * 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.jwt;
+
+import org.apache.hadoop.gateway.i18n.messages.Message;
+import org.apache.hadoop.gateway.i18n.messages.MessageLevel;
+import org.apache.hadoop.gateway.i18n.messages.Messages;
+
+@Messages(logger="org.apache.hadoop.gateway.provider.federation.jwt")
+public interface JWTMessages {
+  @Message( level = MessageLevel.INFO, text = "Failed to validate the audience attribute." )
+  void failedToValidateAudience();
+
+  @Message( level = MessageLevel.INFO, text = "Failed to verify the token signature." )
+  void failedToVerifyTokenSignature();
+}

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/JWTProviderMessages.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/JWTProviderMessages.java b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/JWTProviderMessages.java
deleted file mode 100644
index 1222790..0000000
--- a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/JWTProviderMessages.java
+++ /dev/null
@@ -1,49 +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.jwt;
-
-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")
-public interface JWTProviderMessages {
-
-  @Message( level = MessageLevel.DEBUG, text = "Rendering JWT Token for the wire: {0}" )
-  void renderingJWTTokenForTheWire(String string);
-
-  @Message( level = MessageLevel.DEBUG, text = "Parsing JWT Token from the wire: {0}" )
-  void parsingToken(String wireToken);
-
-  @Message( level = MessageLevel.DEBUG, text = "header: {0}" )
-  void printTokenHeader( String header );
-
-  @Message( level = MessageLevel.DEBUG, text = "claims: {0}" )
-  void printTokenClaims( String claims );
-
-  @Message( level = MessageLevel.DEBUG, text = "payload: {0}" )
-  void printTokenPayload( byte[] payload );
-
-  @Message( level = MessageLevel.FATAL, text = "Unsupported encoding: {0}" )
-  void unsupportedEncoding( @StackTrace( level = MessageLevel.DEBUG ) Exception e );
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/JWTToken.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/JWTToken.java b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/JWTToken.java
deleted file mode 100644
index 4ecf7bd..0000000
--- a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/JWTToken.java
+++ /dev/null
@@ -1,135 +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.jwt;
-
-import java.io.UnsupportedEncodingException;
-import java.text.MessageFormat;
-
-import org.apache.commons.codec.binary.Base64;
-import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
-
-import com.jayway.jsonpath.JsonPath;
-
-public class JWTToken {
-  private static final String headerTemplate = "'{'\"alg\": \"{0}\"'}'";
-  private static final String claimTemplate = "'{'\"iss\": \"{0}\", \"prn\": \"{1}\", \"aud\": \"{2}\", \"exp\": \"{3}\"'}'";
-  public static final String PRINCIPAL = "prn";
-  public static final String ISSUER = "iss";
-  public static final String AUDIENCE = "aud";
-  public static final String EXPIRES = "exp";
-  private static JWTProviderMessages log = MessagesFactory.get( JWTProviderMessages.class );
-
-  public String header = null;
-  public String claims = null;
-  
-  byte[] payload = null;
-  
-  private JWTToken(byte[] header, byte[] claims, byte[] signature) {
-    try {
-      this.header = new String(header, "UTF-8");
-      this.claims = new String(claims, "UTF-8");
-      this.payload = signature;
-    } catch (UnsupportedEncodingException e) {
-      log.unsupportedEncoding( e );
-    }
-  }
-
-  public JWTToken(String alg, String[] claimsArray) {
-    MessageFormat headerFormatter = new MessageFormat(headerTemplate);
-    String[] algArray = new String[1];
-    algArray[0] = alg;
-    header = headerFormatter.format(algArray);
-
-    MessageFormat claimsFormatter = new MessageFormat(claimTemplate);
-    claims = claimsFormatter.format(claimsArray);
-  }
-  
-  public String getPayloadToSign() {
-    StringBuffer sb = new StringBuffer();
-    try {
-      sb.append(Base64.encodeBase64URLSafeString(header.getBytes("UTF-8")));
-      sb.append(".");
-      sb.append(Base64.encodeBase64URLSafeString(claims.getBytes("UTF-8")));
-    } catch (UnsupportedEncodingException e) {
-      log.unsupportedEncoding( e );
-    }
-    
-    return sb.toString();
-  }
-
-  public String toString() {
-    StringBuffer sb = new StringBuffer();
-    try {
-      sb.append(Base64.encodeBase64URLSafeString(header.getBytes("UTF-8")));
-      sb.append(".");
-      sb.append(Base64.encodeBase64URLSafeString(claims.getBytes("UTF-8")));
-      sb.append(".");
-      sb.append(Base64.encodeBase64URLSafeString(payload));
-    } catch (UnsupportedEncodingException e) {
-      log.unsupportedEncoding( e );
-    }
-    
-    log.renderingJWTTokenForTheWire(sb.toString());
-
-    return sb.toString();
-  }
-  
-  public void setSignaturePayload(byte[] payload) {
-    this.payload = payload;
-  }
-  
-  public byte[] getSignaturePayload() {
-    return this.payload;
-  }
-
-  public static JWTToken parseToken(String wireToken) {
-    JWTToken token = null;
-    log.parsingToken(wireToken);
-    String[] parts = wireToken.split("\\.");
-    token = new JWTToken(Base64.decodeBase64(parts[0]), Base64.decodeBase64(parts[1]), Base64.decodeBase64(parts[2]));
-//    System.out.println("header: " + token.header);
-//    System.out.println("claims: " + token.claims);
-//    System.out.println("payload: " + new String(token.payload));
-    
-    return token;
-  }
-  
-  public String getClaim(String claimName) {
-    String claim = null;
-    
-    claim = JsonPath.read(claims, "$." + claimName);
-    
-    return claim;
-  }
-
-  public String getPrincipal() {
-    return getClaim(JWTToken.PRINCIPAL);
-  }
-
-  public String getIssuer() {
-    return getClaim(JWTToken.ISSUER);
-  }
-
-  public String getAudience() {
-    return getClaim(JWTToken.AUDIENCE);
-  }
-
-  public String getExpires() {
-    return getClaim(JWTToken.EXPIRES);
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/AccessTokenFederationFilter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/AccessTokenFederationFilter.java b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/AccessTokenFederationFilter.java
index e067afc..e2856be 100644
--- a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/AccessTokenFederationFilter.java
+++ b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/AccessTokenFederationFilter.java
@@ -34,23 +34,22 @@ import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.hadoop.gateway.provider.federation.jwt.JWTAuthority;
-import org.apache.hadoop.gateway.provider.federation.jwt.JWTToken;
+import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
+import org.apache.hadoop.gateway.provider.federation.jwt.JWTMessages;
 import org.apache.hadoop.gateway.services.GatewayServices;
-import org.apache.hadoop.gateway.services.security.CryptoService;
+import org.apache.hadoop.gateway.services.security.token.JWTokenAuthority;
+import org.apache.hadoop.gateway.services.security.token.impl.JWTToken;
 
 public class AccessTokenFederationFilter implements Filter {
+  private static JWTMessages log = MessagesFactory.get( JWTMessages.class );
   private static final String BEARER = "Bearer ";
   
-  private CryptoService crypto = null;
-
-  private JWTAuthority authority;
+  private JWTokenAuthority authority;
   
   @Override
   public void init( FilterConfig filterConfig ) throws ServletException {
     GatewayServices services = (GatewayServices) filterConfig.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
-    crypto = (CryptoService) services.getService(GatewayServices.CRYPTO_SERVICE);
-    authority = new JWTAuthority(crypto);
+    authority = (JWTokenAuthority) services.getService(GatewayServices.TOKEN_SERVICE);
   }
 
   public void destroy() {
@@ -67,17 +66,19 @@ public class AccessTokenFederationFilter implements Filter {
       if (verified) {
         // TODO: validate expiration
         // TODO: confirm that audience matches intended target
-        if (token.getAudience().equals(getAudienceFromRequest(request))) {
+        if (((HttpServletRequest) request).getRequestURL().indexOf(token.getAudience().toLowerCase()) != -1) {
           // 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);
         }
         else {
+          log.failedToValidateAudience();
           ((HttpServletResponse) response).sendError(HttpServletResponse.SC_UNAUTHORIZED);
           return; //break filter chain
         }
       }
       else {
+        log.failedToVerifyTokenSignature();
         ((HttpServletResponse) response).sendError(HttpServletResponse.SC_UNAUTHORIZED);
         return; //break filter chain
       }
@@ -90,11 +91,6 @@ public class AccessTokenFederationFilter implements Filter {
     }
   }
   
-  private String getAudienceFromRequest(ServletRequest request) {
-    // TODO determine the audience value that would match the requested resource
-    return "HDFS";
-  }
-
   private void continueWithEstablishedSecurityContext(Subject subject, final HttpServletRequest request, final HttpServletResponse response, final FilterChain chain) throws IOException, ServletException {
     try {
       Subject.doAs(

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTAccessTokenAssertionFilter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTAccessTokenAssertionFilter.java b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTAccessTokenAssertionFilter.java
index db1fd2c..6b8a41e 100644
--- a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTAccessTokenAssertionFilter.java
+++ b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTAccessTokenAssertionFilter.java
@@ -18,7 +18,6 @@
 package org.apache.hadoop.gateway.provider.federation.jwt.filter;
 
 import java.io.IOException;
-import java.io.UnsupportedEncodingException;
 import java.security.AccessController;
 import java.security.Principal;
 import java.util.HashMap;
@@ -33,19 +32,21 @@ import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.hadoop.gateway.filter.security.AbstractIdentityAssertionFilter;
-import org.apache.hadoop.gateway.provider.federation.jwt.JWTAuthority;
-import org.apache.hadoop.gateway.provider.federation.jwt.JWTToken;
 import org.apache.hadoop.gateway.services.GatewayServices;
-import org.apache.hadoop.gateway.services.security.CryptoService;
+import org.apache.hadoop.gateway.services.registry.ServiceRegistry;
+import org.apache.hadoop.gateway.services.security.token.JWTokenAuthority;
+import org.apache.hadoop.gateway.services.security.token.impl.JWTToken;
 import org.apache.hadoop.gateway.util.JsonUtils;
 
 public class JWTAccessTokenAssertionFilter extends AbstractIdentityAssertionFilter {
+  private static final String SVC_URL = "svc";
   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 long validity;
-  private CryptoService crypto = null;
+  private JWTokenAuthority authority = null;
+  private ServiceRegistry sr;
 
   @Override
   public void init( FilterConfig filterConfig ) throws ServletException {
@@ -57,7 +58,8 @@ public class JWTAccessTokenAssertionFilter extends AbstractIdentityAssertionFilt
     validity = Long.parseLong(validityStr);
 
     GatewayServices services = (GatewayServices) filterConfig.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
-    crypto = (CryptoService) services.getService(GatewayServices.CRYPTO_SERVICE);
+    authority = (JWTokenAuthority) services.getService(GatewayServices.TOKEN_SERVICE);
+    sr = (ServiceRegistry) services.getService(GatewayServices.SERVICE_REGISTRY_SERVICE);
   }
   
   @Override
@@ -72,7 +74,6 @@ public class JWTAccessTokenAssertionFilter extends AbstractIdentityAssertionFilt
       JWTToken token = JWTToken.parseToken(wireToken);
       // ensure that there is a valid jwt token available and that there isn't a misconfiguration of filters
       if (token != null) {
-        JWTAuthority authority = new JWTAuthority(crypto);
         authority.verifyToken(token);
       }
       else {
@@ -91,14 +92,20 @@ public class JWTAccessTokenAssertionFilter extends AbstractIdentityAssertionFilt
       long expires = System.currentTimeMillis() + validity * 1000;
       
       String serviceName = request.getParameter("service-name");
+      String clusterName = request.getParameter("cluster-name");
       String accessToken = getAccessToken(principalName, serviceName, expires);
       
+      String serviceURL = sr.lookupServiceURL(clusterName, serviceName);
+      
       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);
       
+      // TODO: this url needs to be rewritten when in gateway deployments....
+      map.put(SVC_URL, serviceURL);
+      
       jsonResponse = JsonUtils.renderAsJsonString(map);
       
       response.getWriter().write(jsonResponse);
@@ -117,7 +124,6 @@ public class JWTAccessTokenAssertionFilter extends AbstractIdentityAssertionFilt
   private String getAccessToken(final String principalName, String serviceName, long expires) {
     String accessToken = null;
 
-    JWTAuthority authority = new JWTAuthority(crypto);
     Principal p = new Principal() {
 
       @Override
@@ -127,7 +133,6 @@ public class JWTAccessTokenAssertionFilter extends AbstractIdentityAssertionFilt
       }
     };
     JWTToken token = authority.issueToken(p, serviceName, "RS256");
-//    AccessToken token = new AccessToken(crypto, principalName, expires);
     accessToken = token.toString();
     
     return accessToken;

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTAuthCodeAssertionFilter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTAuthCodeAssertionFilter.java b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTAuthCodeAssertionFilter.java
index 072c308..ba691a5 100644
--- a/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTAuthCodeAssertionFilter.java
+++ b/gateway-provider-security-jwt/src/main/java/org/apache/hadoop/gateway/provider/federation/jwt/filter/JWTAuthCodeAssertionFilter.java
@@ -27,20 +27,20 @@ import javax.servlet.FilterConfig;
 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.hadoop.gateway.filter.security.AbstractIdentityAssertionFilter;
-import org.apache.hadoop.gateway.provider.federation.jwt.JWTAuthority;
-import org.apache.hadoop.gateway.provider.federation.jwt.JWTToken;
 import org.apache.hadoop.gateway.services.GatewayServices;
-import org.apache.hadoop.gateway.services.security.CryptoService;
+import org.apache.hadoop.gateway.services.registry.ServiceRegistry;
+import org.apache.hadoop.gateway.services.security.token.JWTokenAuthority;
+import org.apache.hadoop.gateway.services.security.token.impl.JWTToken;
 import org.apache.hadoop.gateway.util.JsonUtils;
 
 public class JWTAuthCodeAssertionFilter extends AbstractIdentityAssertionFilter {
   private static final String BEARER = "Bearer ";
   
-  private CryptoService crypto = null;
+  private JWTokenAuthority authority = null;
+
+  private ServiceRegistry sr;
 
   @Override
   public void init( FilterConfig filterConfig ) throws ServletException {
@@ -52,7 +52,8 @@ public class JWTAuthCodeAssertionFilter extends AbstractIdentityAssertionFilter
 //    validity = Long.parseLong(validityStr);
 
     GatewayServices services = (GatewayServices) filterConfig.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
-    crypto = (CryptoService) services.getService(GatewayServices.CRYPTO_SERVICE);
+    authority = (JWTokenAuthority) services.getService(GatewayServices.TOKEN_SERVICE);
+    sr = (ServiceRegistry) services.getService(GatewayServices.SERVICE_REGISTRY_SERVICE);
   }
   
   @Override
@@ -62,9 +63,14 @@ public class JWTAuthCodeAssertionFilter extends AbstractIdentityAssertionFilter
       Subject subject = Subject.getSubject(AccessController.getContext());
       String principalName = getPrincipalName(subject);
       principalName = mapper.mapPrincipal(principalName);
-      JWTAuthority authority = new JWTAuthority(crypto);
       JWTToken authCode = authority.issueToken(subject, "RS256");
       
+      // get the url for the token service
+      String url = null; 
+      if (sr != null) {
+        url = sr.lookupServiceURL("token", "TGS");
+      }
+      
       HashMap<String, Object> map = new HashMap<String, Object>();
       // TODO: populate map from JWT authorization code
       map.put("iss", authCode.getIssuer());
@@ -72,6 +78,9 @@ public class JWTAuthCodeAssertionFilter extends AbstractIdentityAssertionFilter
       map.put("aud", authCode.getAudience());
       map.put("exp", authCode.getExpires());
       map.put("code", authCode.toString());
+      if (url != null) {
+        map.put("tke", url);
+      }
       
       String jsonResponse = JsonUtils.renderAsJsonString(map);
       

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/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 29dbe5b..20b0b06 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
@@ -18,7 +18,8 @@
 package org.apache.hadoop.gateway.provider.federation.jwt.filter;
 
 import org.apache.hadoop.gateway.services.GatewayServices;
-import org.apache.hadoop.gateway.services.security.CryptoService;
+import org.apache.hadoop.gateway.services.security.token.JWTokenAuthority;
+import org.apache.hadoop.gateway.services.security.token.impl.JWTToken;
 
 import javax.security.auth.Subject;
 import javax.servlet.Filter;
@@ -30,9 +31,6 @@ import javax.servlet.ServletResponse;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.hadoop.gateway.provider.federation.jwt.JWTAuthority;
-import org.apache.hadoop.gateway.provider.federation.jwt.JWTToken;
-
 import java.io.IOException;
 import java.security.Principal;
 import java.security.PrivilegedActionException;
@@ -40,18 +38,16 @@ import java.security.PrivilegedExceptionAction;
 import java.util.HashSet;
 import java.util.Set;
 
-
 public class JWTFederationFilter implements Filter {
 
   private static final String BEARER = "Bearer ";
   
-  private JWTAuthority authority = null;
+  private JWTokenAuthority authority = null;
 
   @Override
   public void init( FilterConfig filterConfig ) throws ServletException {
     GatewayServices services = (GatewayServices) filterConfig.getServletContext().getAttribute(GatewayServices.GATEWAY_SERVICES_ATTRIBUTE);
-    CryptoService crypto = (CryptoService) services.getService(GatewayServices.CRYPTO_SERVICE);
-    authority = new JWTAuthority(crypto);
+    authority = (JWTokenAuthority) services.getService(GatewayServices.TOKEN_SERVICE);
   }
 
   public void destroy() {

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/JWTTokenTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/JWTTokenTest.java b/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/JWTTokenTest.java
index 41214e2..116e18e 100644
--- a/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/JWTTokenTest.java
+++ b/gateway-provider-security-jwt/src/test/java/org/apache/hadoop/gateway/provider/federation/JWTTokenTest.java
@@ -18,7 +18,8 @@
 package org.apache.hadoop.gateway.provider.federation;
 
 import junit.framework.TestCase;
-import org.apache.hadoop.gateway.provider.federation.jwt.JWTToken;
+
+import org.apache.hadoop.gateway.services.security.token.impl.JWTToken;
 import org.junit.Test;
 
 public class JWTTokenTest extends TestCase {

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-release/src/assembly.xml
----------------------------------------------------------------------
diff --git a/gateway-release/src/assembly.xml b/gateway-release/src/assembly.xml
index fc15c2f..24cae78 100644
--- a/gateway-release/src/assembly.xml
+++ b/gateway-release/src/assembly.xml
@@ -45,13 +45,15 @@
             <scope>runtime</scope>
             <excludes>
                 <exclude>${gateway-group}:gateway-*</exclude>
+                <exclude>${gateway-group}:hsso-*</exclude>
             </excludes>
         </dependencySet>
         <dependencySet>
-            <useProjectArtifact>false</useProjectArtifact>
             <outputDirectory>lib</outputDirectory>
             <includes>
                 <include>${gateway-group}:gateway-*</include>
+                <include>${gateway-group}:hsso-*</include>
+                <include>${gateway-group}:gateway-release-*</include>
             </includes>
             <excludes>
                 <exclude>${gateway-group}:gateway-util-launcher</exclude>

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-release/src/main/resources/META-INF/services/org.apache.hadoop.gateway.services.GatewayServices
----------------------------------------------------------------------
diff --git a/gateway-release/src/main/resources/META-INF/services/org.apache.hadoop.gateway.services.GatewayServices b/gateway-release/src/main/resources/META-INF/services/org.apache.hadoop.gateway.services.GatewayServices
new file mode 100644
index 0000000..8cf264d
--- /dev/null
+++ b/gateway-release/src/main/resources/META-INF/services/org.apache.hadoop.gateway.services.GatewayServices
@@ -0,0 +1,20 @@
+##########################################################################
+# 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.services.DefaultGatewayServices

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java
index dd2e975..90befc7 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayMessages.java
@@ -25,6 +25,7 @@ import org.apache.hadoop.gateway.i18n.messages.StackTrace;
 
 import java.io.File;
 import java.net.URI;
+import java.util.Map;
 
 /**
  *
@@ -247,4 +248,13 @@ public interface GatewayMessages {
 
   @Message( level = MessageLevel.ERROR, text = "Failed to establish connection to {0}: {1}" )
   void failedToEstablishConnectionToUrl( String url, @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+  @Message( level = MessageLevel.ERROR, text = "Failed to instantiate the internal gateway services." )
+  void failedToInstantiateGatewayServices();
+
+  @Message( level = MessageLevel.ERROR, text = "Failed to serialize map to Json string {0}: {1}" )
+  void failedToSerializeMapToJSON( Map<String, Object> map, @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+  @Message( level = MessageLevel.ERROR, text = "Failed to get map from Json string {0}: {1}" )
+  void failedToGetMapFromJsonString( String json, @StackTrace( level = MessageLevel.DEBUG ) Exception e );
 }

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayServer.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayServer.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayServer.java
index 5242e4e..85d35de 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayServer.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/GatewayServer.java
@@ -24,11 +24,13 @@ import org.apache.commons.io.IOUtils;
 import org.apache.hadoop.gateway.config.GatewayConfig;
 import org.apache.hadoop.gateway.config.impl.GatewayConfigImpl;
 import org.apache.hadoop.gateway.deploy.DeploymentFactory;
+import org.apache.hadoop.gateway.deploy.ServiceDeploymentContributor;
 import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
 import org.apache.hadoop.gateway.i18n.resources.ResourcesFactory;
 import org.apache.hadoop.gateway.services.DefaultGatewayServices;
 import org.apache.hadoop.gateway.services.GatewayServices;
 import org.apache.hadoop.gateway.services.ServiceLifecycleException;
+import org.apache.hadoop.gateway.services.registry.ServiceRegistry;
 import org.apache.hadoop.gateway.services.security.SSLService;
 import org.apache.hadoop.gateway.topology.Topology;
 import org.apache.hadoop.gateway.topology.TopologyEvent;
@@ -52,9 +54,11 @@ import java.io.OutputStream;
 import java.net.InetSocketAddress;
 import java.net.ServerSocket;
 import java.util.HashMap;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.ServiceLoader;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.regex.Pattern;
 
@@ -62,7 +66,7 @@ public class GatewayServer {
   private static GatewayResources res = ResourcesFactory.get( GatewayResources.class );
   private static GatewayMessages log = MessagesFactory.get( GatewayMessages.class );
   private static GatewayServer server;
-  private static DefaultGatewayServices services;
+  private static GatewayServices services;
   
   private static Properties buildProperties;
 
@@ -84,7 +88,10 @@ public class GatewayServer {
             buildProperties.getProperty( "build.version", "unknown" ),
             buildProperties.getProperty( "build.hash", "unknown" ) ) );
       } else {
-        services = new DefaultGatewayServices();
+        services = instantiateGatewayServices();
+        if (services == null) {
+          log.failedToInstantiateGatewayServices();
+        }
         GatewayConfig config = new GatewayConfigImpl();
         configureLogging( config );
         if (config.isHadoopKerberosSecured()) {
@@ -92,7 +99,7 @@ public class GatewayServer {
         }
         Map<String,String> options = new HashMap<String,String>();
         options.put(GatewayCommandLine.PERSIST_LONG, Boolean.toString(cmd.hasOption(GatewayCommandLine.PERSIST_LONG)));
-        services.init(config, options);
+        ((org.apache.hadoop.gateway.services.Service) services).init(config, options);
         if (!cmd.hasOption(GatewayCommandLine.NOSTART_LONG)) {
           startGateway( config, services );
         }
@@ -104,6 +111,15 @@ public class GatewayServer {
     }
   }
 
+  private static GatewayServices instantiateGatewayServices() {
+    ServiceLoader<GatewayServices> loader = ServiceLoader.load( GatewayServices.class );
+    Iterator<GatewayServices> services = loader.iterator();
+    if (services.hasNext()) {
+      return services.next();
+    }
+    return null;
+  }
+
   public static synchronized GatewayServices getGatewayServices() {
     return services;
   }
@@ -188,13 +204,13 @@ public class GatewayServer {
     input.close();
   }
 
-  public static GatewayServer startGateway( GatewayConfig config, DefaultGatewayServices srvics ) {
+  public static GatewayServer startGateway( GatewayConfig config, GatewayServices svcs ) {
     try {
       log.startingGateway();
       server = new GatewayServer( config );
       synchronized (server ) {
         if (services == null) {
-          services = srvics;
+          services = svcs;
         }
         services.start();
         DeploymentFactory.setGatewayServices(services);
@@ -338,6 +354,10 @@ public class GatewayServer {
   private synchronized void internalUndeploy( Topology topology ) {
     WebAppContext context = deployments.remove( topology.getName() );
     if( context != null ) {
+      ServiceRegistry sr = (ServiceRegistry) this.getGatewayServices().getService(GatewayServices.SERVICE_REGISTRY_SERVICE);
+      if (sr != null) {
+        sr.removeClusterServices(topology.getName());
+      }
       contexts.removeHandler( context ) ;
       try {
         context.stop();

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-server/src/main/java/org/apache/hadoop/gateway/deploy/DeploymentFactory.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/deploy/DeploymentFactory.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/deploy/DeploymentFactory.java
index 2ade641..ce2f7af 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/deploy/DeploymentFactory.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/deploy/DeploymentFactory.java
@@ -25,7 +25,8 @@ import org.apache.hadoop.gateway.descriptor.GatewayDescriptor;
 import org.apache.hadoop.gateway.descriptor.GatewayDescriptorFactory;
 import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
 import org.apache.hadoop.gateway.i18n.resources.ResourcesFactory;
-import org.apache.hadoop.gateway.services.DefaultGatewayServices;
+import org.apache.hadoop.gateway.services.GatewayServices;
+import org.apache.hadoop.gateway.services.registry.ServiceRegistry;
 import org.apache.hadoop.gateway.topology.Provider;
 import org.apache.hadoop.gateway.topology.Service;
 import org.apache.hadoop.gateway.topology.Topology;
@@ -53,7 +54,7 @@ public abstract class DeploymentFactory {
 
   private static GatewayResources res = ResourcesFactory.get( GatewayResources.class );
   private static GatewayMessages log = MessagesFactory.get( GatewayMessages.class );
-  private static DefaultGatewayServices gatewayServices = null;
+  private static GatewayServices gatewayServices = null;
 
   //private static Set<ServiceDeploymentContributor> SERVICE_CONTRIBUTORS;
   private static Map<String,Map<String,ServiceDeploymentContributor>> SERVICE_CONTRIBUTOR_MAP;
@@ -67,7 +68,7 @@ public abstract class DeploymentFactory {
     loadProviderContributors();
   }
   
-  public static void setGatewayServices(DefaultGatewayServices services) {
+  public static void setGatewayServices(GatewayServices services) {
     DeploymentFactory.gatewayServices = services;
   }
 
@@ -244,6 +245,13 @@ public abstract class DeploymentFactory {
       if( contributor != null ) {
         try {
           contributor.contributeService( context, service );
+          if (gatewayServices != null) {
+            ServiceRegistry sr = (ServiceRegistry) gatewayServices.getService(GatewayServices.SERVICE_REGISTRY_SERVICE);
+            if (sr != null) {
+              String regCode = sr.getRegistrationCode(topology.getName());
+              sr.registerService(regCode, topology.getName(), service.getRole(), service.getUrl().toExternalForm());
+            }
+          }
         } catch( Exception e ) {
           // Maybe it makes sense to throw exception
           log.failedToContributeService( service.getName(), service.getRole(), e );

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-server/src/main/java/org/apache/hadoop/gateway/services/DefaultGatewayServices.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/DefaultGatewayServices.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/DefaultGatewayServices.java
index fddf865..b17c98c 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/DefaultGatewayServices.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/DefaultGatewayServices.java
@@ -25,13 +25,13 @@ import java.util.Map;
 import org.apache.hadoop.gateway.GatewayMessages;
 import org.apache.hadoop.gateway.config.GatewayConfig;
 import org.apache.hadoop.gateway.deploy.DeploymentContext;
-import org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor;
 import org.apache.hadoop.gateway.descriptor.FilterParamDescriptor;
 import org.apache.hadoop.gateway.descriptor.ResourceDescriptor;
 import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
 import org.apache.hadoop.gateway.services.GatewayServices;
 import org.apache.hadoop.gateway.services.Service;
 import org.apache.hadoop.gateway.services.ServiceLifecycleException;
+import org.apache.hadoop.gateway.services.registry.impl.DefaultServiceRegistryService;
 import org.apache.hadoop.gateway.services.security.KeystoreServiceException;
 import org.apache.hadoop.gateway.services.security.SSLService;
 import org.apache.hadoop.gateway.services.security.impl.DefaultAliasService;
@@ -39,9 +39,11 @@ import org.apache.hadoop.gateway.services.security.impl.DefaultCryptoService;
 import org.apache.hadoop.gateway.services.security.impl.DefaultKeystoreService;
 import org.apache.hadoop.gateway.services.security.impl.DefaultMasterService;
 import org.apache.hadoop.gateway.services.security.impl.JettySSLService;
+import org.apache.hadoop.gateway.services.token.impl.DefaultTokenAuthorityService;
 import org.apache.hadoop.gateway.topology.Provider;
 
-public class DefaultGatewayServices implements Service, ProviderDeploymentContributor, GatewayServices {
+public class DefaultGatewayServices implements GatewayServices {
+
   private static GatewayMessages log = MessagesFactory.get( GatewayMessages.class );
 
   private Map<String,Service> services = new HashMap<String, Service>();
@@ -71,6 +73,12 @@ public class DefaultGatewayServices implements Service, ProviderDeploymentContri
     crypto.init(config, options);
     services.put(CRYPTO_SERVICE, crypto);
     
+    DefaultTokenAuthorityService ts = new DefaultTokenAuthorityService();
+    ts.setCryptoService(crypto);
+    ts.init(config, options);
+    // prolly should not allow the token service to be looked up?
+    services.put(TOKEN_SERVICE, ts);
+    
     JettySSLService ssl = new JettySSLService();
     ssl.setAliasService(alias);
     ssl.setKeystoreService(ks);
@@ -121,18 +129,17 @@ public class DefaultGatewayServices implements Service, ProviderDeploymentContri
 
   @Override
   public String getRole() {
-    // TODO Auto-generated method stub
     return "Services";
   }
 
   @Override
   public String getName() {
-    // TODO Auto-generated method stub
     return "GatewayServices";
   }
 
   @Override
   public void initializeContribution(DeploymentContext context) {
+    // setup credential store as appropriate
     String clusterName = context.getTopology().getName();
     try {
       if (!ks.isCredentialStoreForClusterAvailable(clusterName)) {
@@ -140,7 +147,6 @@ public class DefaultGatewayServices implements Service, ProviderDeploymentContri
         ks.createCredentialStoreForCluster(clusterName);
       }
       else {
-        // TODO: log appropriately
         log.credentialStoreForClusterFoundNotCreating(clusterName);
       }
     } catch (KeystoreServiceException e) {
@@ -156,8 +162,6 @@ public class DefaultGatewayServices implements Service, ProviderDeploymentContri
   public void contributeFilter(DeploymentContext context, Provider provider,
       org.apache.hadoop.gateway.topology.Service service,
       ResourceDescriptor resource, List<FilterParamDescriptor> params) {
-    // TODO Auto-generated method stub
-    
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-server/src/main/java/org/apache/hadoop/gateway/services/HssoGatewayServices.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/HssoGatewayServices.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/HssoGatewayServices.java
new file mode 100644
index 0000000..1711dc8
--- /dev/null
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/HssoGatewayServices.java
@@ -0,0 +1,177 @@
+/**
+ * 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.services;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.hadoop.gateway.GatewayMessages;
+import org.apache.hadoop.gateway.config.GatewayConfig;
+import org.apache.hadoop.gateway.deploy.DeploymentContext;
+import org.apache.hadoop.gateway.descriptor.FilterParamDescriptor;
+import org.apache.hadoop.gateway.descriptor.ResourceDescriptor;
+import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
+import org.apache.hadoop.gateway.services.GatewayServices;
+import org.apache.hadoop.gateway.services.Service;
+import org.apache.hadoop.gateway.services.ServiceLifecycleException;
+import org.apache.hadoop.gateway.services.registry.impl.DefaultServiceRegistryService;
+import org.apache.hadoop.gateway.services.security.KeystoreServiceException;
+import org.apache.hadoop.gateway.services.security.SSLService;
+import org.apache.hadoop.gateway.services.security.impl.DefaultAliasService;
+import org.apache.hadoop.gateway.services.security.impl.DefaultCryptoService;
+import org.apache.hadoop.gateway.services.security.impl.DefaultKeystoreService;
+import org.apache.hadoop.gateway.services.security.impl.DefaultMasterService;
+import org.apache.hadoop.gateway.services.security.impl.JettySSLService;
+import org.apache.hadoop.gateway.services.token.impl.DefaultTokenAuthorityService;
+import org.apache.hadoop.gateway.topology.Provider;
+
+public class HssoGatewayServices implements GatewayServices {
+
+  private static GatewayMessages log = MessagesFactory.get( GatewayMessages.class );
+
+  private Map<String,Service> services = new HashMap<String, Service>();
+  private DefaultMasterService ms = null;
+  private DefaultKeystoreService ks = null;
+
+  public HssoGatewayServices() {
+    super();
+  }
+
+  public void init(GatewayConfig config, Map<String,String> options) throws ServiceLifecycleException {
+    ms = new DefaultMasterService();
+    ms.init(config, options);
+
+    ks = new DefaultKeystoreService();
+    ks.setMasterService(ms);
+    ks.init(config, options);
+    
+    DefaultAliasService alias = new DefaultAliasService();
+    alias.setKeystoreService(ks);
+    alias.init(config, options);
+    services.put(ALIAS_SERVICE, alias);
+
+    DefaultCryptoService crypto = new DefaultCryptoService();
+    crypto.setKeystoreService(ks);
+    crypto.setAliasService(alias);
+    crypto.init(config, options);
+    services.put(CRYPTO_SERVICE, crypto);
+    
+    DefaultTokenAuthorityService ts = new DefaultTokenAuthorityService();
+    ts.setCryptoService(crypto);
+    ts.init(config, options);
+    // prolly should not allow the token service to be looked up?
+    services.put(TOKEN_SERVICE, ts);
+    
+    DefaultServiceRegistryService sr = new DefaultServiceRegistryService();
+    sr.setCryptoService(crypto);
+    sr.init(config, options);
+    services.put(SERVICE_REGISTRY_SERVICE, sr);
+    
+    JettySSLService ssl = new JettySSLService();
+    ssl.setAliasService(alias);
+    ssl.setKeystoreService(ks);
+    ssl.setMasterService(ms);
+    ssl.init(config, options);
+    services.put(SSL_SERVICE, ssl);
+  }
+  
+  public void start() throws ServiceLifecycleException {
+    ms.start();
+
+    ks.start();
+
+    DefaultAliasService alias = (DefaultAliasService) services.get(ALIAS_SERVICE);
+    alias.start();
+
+    SSLService ssl = (SSLService) services.get(SSL_SERVICE);
+    ssl.start();
+  }
+
+  public void stop() throws ServiceLifecycleException {
+    ms.stop();
+
+    ks.stop();
+
+    DefaultAliasService alias = (DefaultAliasService) services.get(ALIAS_SERVICE);
+    alias.stop();
+
+    SSLService ssl = (SSLService) services.get(SSL_SERVICE);
+    ssl.stop();
+  }
+  
+  /* (non-Javadoc)
+   * @see org.apache.hadoop.gateway.GatewayServices#getServiceNames()
+   */
+  @Override
+  public Collection<String> getServiceNames() {
+    return services.keySet();
+  }
+  
+  /* (non-Javadoc)
+   * @see org.apache.hadoop.gateway.GatewayServices#getService(java.lang.String)
+   */
+  @Override
+  public Service getService(String serviceName) {
+    return services.get(serviceName);
+  }
+
+  @Override
+  public String getRole() {
+    return "Services";
+  }
+
+  @Override
+  public String getName() {
+    return "GatewayServices";
+  }
+
+  @Override
+  public void initializeContribution(DeploymentContext context) {
+    // setup credential store as appropriate
+    String clusterName = context.getTopology().getName();
+    try {
+      if (!ks.isCredentialStoreForClusterAvailable(clusterName)) {
+        log.creatingCredentialStoreForCluster(clusterName);
+        ks.createCredentialStoreForCluster(clusterName);
+      }
+      else {
+        log.credentialStoreForClusterFoundNotCreating(clusterName);
+      }
+    } catch (KeystoreServiceException e) {
+      throw new RuntimeException("Credential store was found but was unable to be loaded - the provided (or persisted) master secret may not match the password for the credential store.", e);
+    }
+  }
+
+  @Override
+  public void contributeProvider(DeploymentContext context, Provider provider) {
+  }
+
+  @Override
+  public void contributeFilter(DeploymentContext context, Provider provider,
+      org.apache.hadoop.gateway.topology.Service service,
+      ResourceDescriptor resource, List<FilterParamDescriptor> params) {
+  }
+
+  @Override
+  public void finalizeContribution(DeploymentContext context) {
+    // Tell the provider the location of the descriptor.
+    context.getWebAppDescriptor().createListener().listenerClass( GatewayServicesContextListener.class.getName() );
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-server/src/main/java/org/apache/hadoop/gateway/services/registry/impl/DefaultServiceRegistryService.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/registry/impl/DefaultServiceRegistryService.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/registry/impl/DefaultServiceRegistryService.java
new file mode 100644
index 0000000..92b8621
--- /dev/null
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/registry/impl/DefaultServiceRegistryService.java
@@ -0,0 +1,191 @@
+/**
+ * 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.services.registry.impl;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Random;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.io.FileUtils;
+import org.apache.hadoop.gateway.GatewayMessages;
+import org.apache.hadoop.gateway.config.GatewayConfig;
+import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
+import org.apache.hadoop.gateway.services.Service;
+import org.apache.hadoop.gateway.services.ServiceLifecycleException;
+import org.apache.hadoop.gateway.services.registry.ServiceRegistry;
+import org.apache.hadoop.gateway.services.security.CryptoService;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonParseException;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonMappingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+
+public class DefaultServiceRegistryService implements ServiceRegistry, Service {
+  private static GatewayMessages LOG = MessagesFactory.get( GatewayMessages.class );
+  
+  protected char[] chars = { 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+  'h', 'j', 'k', 'm', 'n', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+  'x', 'y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K',
+  'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+  '2', '3', '4', '5', '6', '7', '8', '9',};
+
+  private CryptoService crypto;
+  private Registry registry = new Registry();
+
+  private String registryFileName;
+  
+  public DefaultServiceRegistryService() {
+  }
+  
+  public void setCryptoService(CryptoService crypto) {
+    this.crypto = crypto;
+  }
+  
+  public String getRegistrationCode(String clusterName) {
+    String code = generateRegCode(16);
+    byte[] signature = crypto.sign("SHA256withRSA","gateway-identity",code);
+    String encodedSig = Base64.encodeBase64URLSafeString(signature);
+    
+    return code + "::" + encodedSig;
+  }
+  
+  private String generateRegCode(int length) {
+    StringBuffer sb = new StringBuffer();
+    Random r = new Random();
+    for (int i = 0; i < length; i++) {
+      sb.append(chars[r.nextInt(chars.length)]);
+    }
+    return sb.toString();
+  }
+  
+  public void removeClusterServices(String clusterName) {
+    registry.remove(clusterName);
+  }
+
+  public boolean registerService(String regCode, String clusterName, String serviceName, String url) {
+    boolean rc = false;
+    // verify the signature of the regCode
+    if (regCode == null) {
+      throw new IllegalArgumentException("Registration Code must not be null.");
+    }
+    String[] parts = regCode.split("::");
+    
+    // part one is the code and part two is the signature
+    boolean verified = crypto.verify("SHA256withRSA", "gateway-identity", parts[0], Base64.decodeBase64(parts[1]));
+    if (verified) {
+      HashMap<String,RegEntry> clusterServices = registry.get(clusterName);
+      if (clusterServices == null) {
+        synchronized(this) {
+          clusterServices = new HashMap<String,RegEntry>();
+          registry.put(clusterName, clusterServices);
+        }
+      }
+      RegEntry regEntry = new RegEntry();
+      regEntry.setClusterName(clusterName);
+      regEntry.setServiceName(serviceName);
+      regEntry.setUrl(url);
+      clusterServices.put(serviceName , regEntry);
+      String json = renderAsJsonString(registry);
+      try {
+        FileUtils.write(new File(registryFileName), json);
+        rc = true;
+      } catch (IOException e) {
+        // log appropriately
+        e.printStackTrace();
+      }
+    }
+    
+    return rc;
+  }
+  
+  private String renderAsJsonString(HashMap<String,HashMap<String,RegEntry>> registry) {
+    String json = null;
+    ObjectMapper mapper = new ObjectMapper();
+    
+    try {
+      // write JSON to a file
+      json = mapper.writeValueAsString((Object)registry);
+    
+    } catch ( JsonProcessingException e ) {
+      e.printStackTrace();
+    }
+    return json;
+  }
+  
+  public String lookupServiceURL(String clusterName, String serviceName) {
+    RegEntry entry = null;
+    HashMap clusterServices = registry.get(clusterName);
+    if (clusterServices != null) {
+      entry = (RegEntry) clusterServices.get(serviceName);
+    }
+    return entry.url;
+  }
+  
+  private HashMap<String, HashMap<String,RegEntry>> getMapFromJsonString(String json) {
+    Registry map = null;
+    JsonFactory factory = new JsonFactory(); 
+    ObjectMapper mapper = new ObjectMapper(factory); 
+    TypeReference<Registry> typeRef 
+          = new TypeReference<Registry>() {}; 
+    try {
+      map = mapper.readValue(json, typeRef);
+    } catch (JsonParseException e) {
+      LOG.failedToGetMapFromJsonString( json, e );
+    } catch (JsonMappingException e) {
+      LOG.failedToGetMapFromJsonString( json, e );
+    } catch (IOException e) {
+      LOG.failedToGetMapFromJsonString( json, e );
+    } 
+    return map;
+  }   
+
+  @Override
+  public void init(GatewayConfig config, Map<String, String> options)
+      throws ServiceLifecycleException {
+    String securityDir = config.getGatewayHomeDir() + File.separator + "conf" + File.separator + "security";
+    String filename = "registry";
+    setupRegistryFile(securityDir, filename);
+  }
+
+  protected void setupRegistryFile(String securityDir, String filename) throws ServiceLifecycleException {
+    File registryFile = new File(securityDir, filename);
+    if (registryFile.exists()) {
+      try {
+        String json = FileUtils.readFileToString(registryFile);
+        registry = (Registry) getMapFromJsonString(json);
+      } catch (Exception e) {
+        throw new ServiceLifecycleException("Unable to load the persisted registry.", e);
+      }
+    }
+    registryFileName = registryFile.getAbsolutePath();
+  }
+
+  @Override
+  public void start() throws ServiceLifecycleException {
+  }
+
+  @Override
+  public void stop() throws ServiceLifecycleException {
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-server/src/main/java/org/apache/hadoop/gateway/services/registry/impl/RegEntry.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/registry/impl/RegEntry.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/registry/impl/RegEntry.java
new file mode 100644
index 0000000..847d72e
--- /dev/null
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/registry/impl/RegEntry.java
@@ -0,0 +1,52 @@
+/**
+ * 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.services.registry.impl;
+
+public class RegEntry {
+  public String clusterName;
+  public String serviceName;
+  public String url;
+
+  public RegEntry() {
+  }
+
+  public String getClusterName() {
+    return clusterName;
+  }
+
+  public void setClusterName(String clusterName) {
+    this.clusterName = clusterName;
+  }
+
+  public String getServiceName() {
+    return serviceName;
+  }
+
+  public void setServiceName(String serviceName) {
+    this.serviceName = serviceName;
+  }
+
+  public String getUrl() {
+    return url;
+  }
+
+  public void setUrl(String url) {
+    this.url = url;
+  }
+
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-server/src/main/java/org/apache/hadoop/gateway/services/registry/impl/Registry.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/registry/impl/Registry.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/registry/impl/Registry.java
new file mode 100644
index 0000000..a82284b
--- /dev/null
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/registry/impl/Registry.java
@@ -0,0 +1,33 @@
+/**
+ * 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.services.registry.impl;
+
+import java.util.HashMap;
+
+class Registry extends HashMap<String,HashMap<String,RegEntry>> {
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = 1L;
+  
+  public Registry() {
+    super();
+  }
+  
+}

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultAliasService.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultAliasService.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultAliasService.java
index f16c07a..5fd2883 100644
--- a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultAliasService.java
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/security/impl/DefaultAliasService.java
@@ -45,14 +45,10 @@ public class DefaultAliasService implements AliasService {
 
   @Override
   public void start() throws ServiceLifecycleException {
-    // TODO Auto-generated method stub
-
   }
 
   @Override
   public void stop() throws ServiceLifecycleException {
-    // TODO Auto-generated method stub
-
   }
   
   /* (non-Javadoc)

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-server/src/main/java/org/apache/hadoop/gateway/services/token/impl/DefaultTokenAuthorityService.java
----------------------------------------------------------------------
diff --git a/gateway-server/src/main/java/org/apache/hadoop/gateway/services/token/impl/DefaultTokenAuthorityService.java b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/token/impl/DefaultTokenAuthorityService.java
new file mode 100644
index 0000000..21cef3f
--- /dev/null
+++ b/gateway-server/src/main/java/org/apache/hadoop/gateway/services/token/impl/DefaultTokenAuthorityService.java
@@ -0,0 +1,116 @@
+/**
+ * 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.services.token.impl;
+
+import java.security.Principal;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+
+import org.apache.hadoop.gateway.config.GatewayConfig;
+import org.apache.hadoop.gateway.services.Service;
+import org.apache.hadoop.gateway.services.ServiceLifecycleException;
+import org.apache.hadoop.gateway.services.security.CryptoService;
+import org.apache.hadoop.gateway.services.security.token.JWTokenAuthority;
+import org.apache.hadoop.gateway.services.security.token.impl.JWTToken;
+
+public class DefaultTokenAuthorityService implements JWTokenAuthority, Service {
+  
+  private CryptoService crypto = null;
+
+  /* (non-Javadoc)
+   * @see org.apache.hadoop.gateway.provider.federation.jwt.JWTokenAuthority#issueToken(javax.security.auth.Subject, java.lang.String)
+   */
+  @Override
+  public JWTToken issueToken(Subject subject, String algorithm) {
+    Principal p = (Principal) subject.getPrincipals().toArray()[0];
+    return issueToken(p, algorithm);
+  }
+  
+  /* (non-Javadoc)
+   * @see org.apache.hadoop.gateway.provider.federation.jwt.JWTokenAuthority#issueToken(java.security.Principal, java.lang.String)
+   */
+  @Override
+  public JWTToken issueToken(Principal p, String algorithm) {
+    return issueToken(p, null, algorithm);
+  }
+  
+  /* (non-Javadoc)
+   * @see org.apache.hadoop.gateway.provider.federation.jwt.JWTokenAuthority#issueToken(java.security.Principal, java.lang.String, java.lang.String)
+   */
+  @Override
+  public JWTToken issueToken(Principal p, String audience, String algorithm) {
+    String[] claimArray = new String[4];
+    claimArray[0] = "HSSO";
+    claimArray[1] = p.getName();
+    if (audience == null) {
+      audience = "HSSO";
+    }
+    claimArray[2] = audience;
+    // TODO: make the validity period configurable
+    claimArray[3] = Long.toString( ( System.currentTimeMillis()/1000 ) + 300);
+
+    JWTToken token = null;
+    if ("RS256".equals(algorithm)) {
+      token = new JWTToken("RS256", claimArray);
+      signToken(token);
+    }
+    else {
+      // log inappropriate alg
+    }
+    
+    return token;
+  }
+
+  private void signToken(JWTToken token) {
+    byte[] signature = null;
+    signature = crypto.sign("SHA256withRSA","gateway-identity",token.getPayloadToSign());
+    token.setSignaturePayload(signature);
+  }
+
+  @Override
+  public boolean verifyToken(JWTToken token) {
+    boolean rc = false;
+    
+    // TODO: interrogate the token for issuer claim in order to determine the public key to use for verification
+    // consider jwk for specifying the key too
+    rc = crypto.verify("SHA256withRSA", "gateway-identity", token.getPayloadToSign(), token.getSignaturePayload());
+    return rc;
+  }
+
+  public void setCryptoService(CryptoService crypto) {
+    this.crypto = crypto;
+  }
+  
+  @Override
+  public void init(GatewayConfig config, Map<String, String> options)
+      throws ServiceLifecycleException {
+    if (crypto == null) {
+      throw new ServiceLifecycleException("Crypto service is not set");
+    }
+  }
+
+  @Override
+  public void start() throws ServiceLifecycleException {
+  }
+
+  @Override
+  public void stop() throws ServiceLifecycleException {
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-spi/pom.xml
----------------------------------------------------------------------
diff --git a/gateway-spi/pom.xml b/gateway-spi/pom.xml
index d6dadb6..1d69dbc 100644
--- a/gateway-spi/pom.xml
+++ b/gateway-spi/pom.xml
@@ -94,6 +94,11 @@
             <artifactId>httpclient</artifactId>
         </dependency>
         <dependency>
+            <groupId>com.jayway.jsonpath</groupId>
+            <artifactId>json-path</artifactId>
+        </dependency>
+        
+        <dependency>
             <groupId>junit</groupId>
             <artifactId>junit</artifactId>
             <scope>test</scope>

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/GatewayServices.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/GatewayServices.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/GatewayServices.java
index f13fe33..d97d3cb 100644
--- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/GatewayServices.java
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/GatewayServices.java
@@ -19,12 +19,16 @@ package org.apache.hadoop.gateway.services;
 
 import java.util.Collection;
 
+import org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor;
 
-public interface GatewayServices {
+
+public interface GatewayServices extends Service, ProviderDeploymentContributor {
   public static final String GATEWAY_SERVICES_ATTRIBUTE = "org.apache.hadoop.gateway.gateway.services";
   public static final String SSL_SERVICE = "SSLService";
   public static final String CRYPTO_SERVICE = "CryptoService";
   public static final String ALIAS_SERVICE = "AliasService";
+  public static final String TOKEN_SERVICE = "TokenService";
+  public static final String SERVICE_REGISTRY_SERVICE = "ServiceRegistryService";
 
   public abstract Collection<String> getServiceNames();
 

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/registry/ServiceRegistry.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/registry/ServiceRegistry.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/registry/ServiceRegistry.java
new file mode 100644
index 0000000..fc41c57
--- /dev/null
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/registry/ServiceRegistry.java
@@ -0,0 +1,30 @@
+/**
+ * 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.services.registry;
+
+public interface ServiceRegistry {
+
+  String getRegistrationCode(String clusterName);
+  
+  boolean registerService(String regCode, String ClusterName, String serviceName, String url);
+  
+  String lookupServiceURL(String ClusterName, String serviceName);
+  
+  void removeClusterServices(String clusterName);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/token/JWTokenAuthority.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/token/JWTokenAuthority.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/token/JWTokenAuthority.java
new file mode 100644
index 0000000..e603ff3
--- /dev/null
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/token/JWTokenAuthority.java
@@ -0,0 +1,36 @@
+/**
+ * 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.services.security.token;
+
+import java.security.Principal;
+
+import javax.security.auth.Subject;
+
+import org.apache.hadoop.gateway.services.security.token.impl.JWTToken;
+
+public interface JWTokenAuthority {
+
+  public abstract JWTToken issueToken(Subject subject, String algorithm);
+
+  public abstract JWTToken issueToken(Principal p, String algorithm);
+
+  public abstract JWTToken issueToken(Principal p, String audience,
+      String algorithm);
+
+  public abstract boolean verifyToken(JWTToken token);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/21e6d1da/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/token/impl/JWTProviderMessages.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/token/impl/JWTProviderMessages.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/token/impl/JWTProviderMessages.java
new file mode 100644
index 0000000..1b0b1ee
--- /dev/null
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/services/security/token/impl/JWTProviderMessages.java
@@ -0,0 +1,48 @@
+/**
+ * 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.services.security.token.impl;
+
+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")
+public interface JWTProviderMessages {
+
+  @Message( level = MessageLevel.DEBUG, text = "Rendering JWT Token for the wire: {0}" )
+  void renderingJWTTokenForTheWire(String string);
+
+  @Message( level = MessageLevel.DEBUG, text = "Parsing JWT Token from the wire: {0}" )
+  void parsingToken(String wireToken);
+
+  @Message( level = MessageLevel.DEBUG, text = "header: {0}" )
+  void printTokenHeader( String header );
+
+  @Message( level = MessageLevel.DEBUG, text = "claims: {0}" )
+  void printTokenClaims( String claims );
+
+  @Message( level = MessageLevel.DEBUG, text = "payload: {0}" )
+  void printTokenPayload( byte[] payload );
+
+  @Message( level = MessageLevel.FATAL, text = "Unsupported encoding: {0}" )
+  void unsupportedEncoding( @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+}


Mime
View raw message