inputParams) throws ClientProtocolException {
+ String newUri = uri.toString() + "/v3/auth/tokens/";
+ Header[] header = new Header[1];
+ header[0] = new BasicHeader(AUTH_SUBJECT_TOKEN, token);
+ String serviceIds = null;
+ String endpointIds = null;
+ if (inputParams.containsKey(SERVICE_IDS_PARAM))
+ serviceIds = inputParams.get(SERVICE_IDS_PARAM);
+ if (inputParams.containsKey(ENDPOINT_IDS_PARAM))
+ endpointIds = inputParams.get(ENDPOINT_IDS_PARAM);
+ return verifyUUIDToken(token, newUri, header, serviceIds, endpointIds);
+ }
+
+ private Object verifyUUIDToken(String token, String newUri,
+ Header[] header, String serviceIds, String endpointIds)
+ throws ClientProtocolException {
+ HttpResponse response = sendGet(newUri, header, serviceIds, endpointIds);
+
+ HttpEntity entity = response.getEntity();
+ int code = response.getStatusLine().getStatusCode();
+
+ InputStream instream = null;
+ try {
+ if (code == 404) {
+ instream = entity.getContent();
+ instream.close();
+ throw new AuthException("Authorization failed for token: " + token);
+ }
+
+ if (code != 200) {
+ adminToken = null;
+ instream = entity.getContent();
+ instream.close();
+ String reasonPhrase = response.getStatusLine().getReasonPhrase();
+
+ throw new AuthException("Failed to validate via HTTP " + code
+ + " " + reasonPhrase);
+ }
+ } catch(IOException e) {
+ throw new ClientProtocolException(
+ "IO Exception: problem closing stream ", e);
+ }
+
+
+ return parseResponse(response);
+ }
+
+ private HttpResponse sendPost(String uri, StringEntity body)
+ throws ClientProtocolException {
+ HttpResponse response = null;
+ HttpPost post = new HttpPost(uri);
+ post.setHeader("Accept", "application/json");
+ post.setHeader("Content-Type", "application/json");
+ try {
+ post.setEntity(body);
+ response = client.execute(post);
+ int code = response.getStatusLine().getStatusCode();
+ if (!(code == 201 || code == 200 || code == 203)) {
+ adminToken = null;
+ throw new AuthException(
+ "Failed to authenticate admin credentials " + code
+ + response.getStatusLine().getReasonPhrase());
+ }
+ } catch (IOException e) {
+ post.abort();
+ throw new ClientProtocolException(
+ "IO Exception during POST request ", e);
+ }
+ return response;
+ }
+
+ private HttpResponse sendGet(String newUri, Header[] headers,
+ String serviceIds, String endpointIds)
+ throws ClientProtocolException {
+ HttpResponse response = null;
+ HttpGet get = null;
+ boolean hasServiceIds = false;
+ if (serviceIds != null && !serviceIds.isEmpty()) {
+ newUri += "?HP-IDM-serviceId=" + serviceIds;
+ hasServiceIds = true;
+ }
+ if (endpointIds != null && !endpointIds.isEmpty()) {
+ newUri += hasServiceIds ? "&HP-IDM-endpointTemplateId="
+ + endpointIds : "?HP-IDM-endpointTemplateId=" + endpointIds;
+ }
+
+ get = new HttpGet(newUri);
+ get.setHeader("Accept", "application/json");
+ get.setHeader("Content-Type", "application/json");
+ if (headers != null) {
+ for (Header header : headers) {
+ get.setHeader(header);
+ }
+ }
+
+ if(!appConfig.getAdminToken().isEmpty()) {
+ get.setHeader(new BasicHeader(TOKEN, appConfig.getAdminToken()));
+ }
+ else if (!appConfig.getAdminAuthMethod().isEmpty()) {
+ get.setHeader(new BasicHeader(TOKEN, getAdminToken()));
+ }
+
+ try {
+ response = client.execute(get);
+
+ }catch(ConnectException c) {
+ get.abort();
+ throw new UnavailableException(c.getMessage());
+ }
+ catch (IOException e) {
+ get.abort();
+
+ throw new ClientProtocolException(
+ "IO Exception during GET request ", e);
+ }
+ return response;
+ }
+
+ private String parseResponse(HttpResponse response) {
+ StringBuffer json = new StringBuffer();
+ HttpEntity entity = response.getEntity();
+ if (entity != null) {
+ InputStream instream;
+ try {
+ instream = entity.getContent();
+
+ BufferedReader reader = new BufferedReader(
+ new InputStreamReader(instream));
+ String line = reader.readLine();
+ while (line != null) {
+ json.append(line);
+ line = reader.readLine();
+ }
+ instream.close();
+ reader.close();
+ } catch (Exception e) {
+ throw new AuthException("Failed to parse Http Response ", e);
+ }
+ }
+
+ return json.toString();
+ }
+
+ private String getAdminToken() throws ClientProtocolException {
+ HttpResponse response;
+ String json;
+ JsonParser jp = new JsonParser();
+
+ if (adminTokenExpiry != null) {
+ if (isExpired(adminTokenExpiry)) {
+ adminToken = null;
+ }
+ }
+ if (adminToken == null) {
+ if (appConfig.getAuthVersion().equalsIgnoreCase("v2.0")) {
+ StringEntity params = getUnscopedV2AdminTokenRequest();
+ String authUri = uri + "/v2.0/tokens";
+ response = sendPost(authUri, params);
+ json = parseResponse(response);
+ JsonObject access = jp.parse(json).getAsJsonObject()
+ .get("access").getAsJsonObject();
+ JsonObject token = access.get("token").getAsJsonObject();
+ adminToken = token.get("id").getAsString();
+ adminTokenExpiry = token.get("expires").getAsString();
+ } else {
+ StringEntity params = getUnscopedV3AdminTokenRequest();
+ String authUri = uri + "/v3/auth/tokens";
+ response = sendPost(authUri, params);
+ adminToken = response.getFirstHeader(AUTH_SUBJECT_TOKEN)
+ .getValue();
+ json = parseResponse(response);
+ JsonObject token = jp.parse(json).getAsJsonObject()
+ .get("token").getAsJsonObject();
+ adminTokenExpiry = token.get("expires_at").getAsString();
+
+ }
+ }
+ return adminToken;
+ }
+
+ private StringEntity getUnscopedV2AdminTokenRequest() {
+ StringBuffer bfr = new StringBuffer();
+ if (appConfig.getAdminAuthMethod().equalsIgnoreCase(PASSWORD)) {
+ bfr.append("{\"auth\": {\"passwordCredentials\": {\"username\": \"");
+ bfr.append(appConfig.getAdminUser());
+ bfr.append("\",\"password\": \"");
+ bfr.append(appConfig.getAdminPassword());
+ if (appConfig.getAdminProject() != null && !appConfig.getAdminProject().isEmpty()) {
+ bfr.append("\"}, \"tenantId\": \"");
+ bfr.append(appConfig.getAdminProject());
+ bfr.append("\"}}");
+ } else {
+ bfr.append("\"}}}");
+ }
+ try {
+ return new StringEntity(bfr.toString());
+ } catch (UnsupportedEncodingException e) {
+ throw new AuthException("Invalid V2 authentication request "
+ + e);
+ }
+ } else {
+ String msg = String.format("Admin auth method %s not supported",appConfig.getAdminAuthMethod());
+ throw new AuthException(msg);
+ }
+ }
+
+ private StringEntity getUnscopedV3AdminTokenRequest() {
+ StringBuffer bfr = new StringBuffer();
+ if (appConfig.getAdminAuthMethod().equalsIgnoreCase(PASSWORD)) {
+ bfr.append("{\"auth\": {\"identity\": {\"methods\": [\"password\"],\"password\": {\"user\": {\"name\": \"");
+ bfr.append(appConfig.getAdminUser());
+ bfr.append("\",\"password\": \"");
+ bfr.append(appConfig.getAdminPassword());
+ bfr.append("\",\"domain\": {\"id\": \"default\"");
+ bfr.append("}}}}}}");
+ } else {
+ String msg = String.format("Admin auth method %s not supported",appConfig.getAdminAuthMethod());
+ throw new AuthException(msg);
+ }
+ try {
+ return new StringEntity(bfr.toString());
+ } catch (UnsupportedEncodingException e) {
+ throw new AuthException("Invalid V3 authentication request " + e);
+ }
+ }
+
+ private boolean isExpired(String expires) {
+ Date tokenExpiryDate = null;
+ try {
+ tokenExpiryDate = expiryFormat.parse(expires);
+ } catch (ParseException e) {
+ return true;
+ }
+ Date current = new Date();
+ return tokenExpiryDate.getTime() < (current.getTime() + DELTA_TIME_IN_SEC * 1000);
+ }
+
+ public void reset() { }
+
+}
diff --git a/java/mon-middleware/src/main/java/com/hpcloud/middleware/HttpClientFactory.java b/java/mon-middleware/src/main/java/com/hpcloud/middleware/HttpClientFactory.java
new file mode 100644
index 00000000..79318302
--- /dev/null
+++ b/java/mon-middleware/src/main/java/com/hpcloud/middleware/HttpClientFactory.java
@@ -0,0 +1,29 @@
+package com.hpcloud.middleware;
+
+import org.apache.commons.pool.impl.GenericObjectPool;
+
+/**
+ * An HTTP factory.
+ *
+ * @author liemmn
+ */
+public class HttpClientFactory extends AuthClientFactory {
+ private HttpClientPoolFactory clientPool;
+
+ HttpClientFactory(String host, int port, int timeout, boolean clientAuth,
+ String keyStore, String keyPass, String trustStore,
+ String trustPass, String adminToken, int maxActive,
+ long timeBetweenEvictionRunsMillis, long minEvictableIdleTimeMillis) {
+ clientPool = new HttpClientPoolFactory(host, port, timeout, clientAuth,
+ keyStore, keyPass, trustStore, trustPass, adminToken,
+ maxActive, timeBetweenEvictionRunsMillis,
+ minEvictableIdleTimeMillis);
+ pool = new GenericObjectPool(clientPool);
+ }
+
+ @Override
+ public void shutdown() {
+ clientPool.shutDown();
+ super.shutdown();
+ }
+}
diff --git a/java/mon-middleware/src/main/java/com/hpcloud/middleware/HttpClientPoolFactory.java b/java/mon-middleware/src/main/java/com/hpcloud/middleware/HttpClientPoolFactory.java
new file mode 100644
index 00000000..18609a17
--- /dev/null
+++ b/java/mon-middleware/src/main/java/com/hpcloud/middleware/HttpClientPoolFactory.java
@@ -0,0 +1,130 @@
+package com.hpcloud.middleware;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.net.URI;
+import java.security.KeyStore;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.pool.BasePoolableObjectFactory;
+import org.apache.http.client.HttpClient;
+import org.apache.http.conn.scheme.PlainSocketFactory;
+import org.apache.http.conn.scheme.Scheme;
+import org.apache.http.conn.scheme.SchemeRegistry;
+import org.apache.http.conn.ssl.SSLSocketFactory;
+import org.apache.http.impl.client.DefaultHttpClient;
+import org.apache.http.impl.conn.PoolingClientConnectionManager;
+import org.apache.http.params.BasicHttpParams;
+import org.apache.http.params.CoreConnectionPNames;
+import org.apache.http.params.HttpParams;
+
+/**
+ * A Http request pool factory. Based on Apache Commons Pool. Singleton.
+ * Note that the Apache HttpClient maintains its own connection pool and
+ * does not participate in Apache Commons pool' lifecycle other than creating
+ * HTTPRequests.
+ *
+ * @author liemmn
+ */
+public class HttpClientPoolFactory extends BasePoolableObjectFactory {
+ private URI uri;
+ private PoolingClientConnectionManager connMgr;
+ private HttpPoolCleaner cleaner;
+ private HttpClient client;
+
+ HttpClientPoolFactory(String host, int port, int timeout,
+ boolean clientAuth, String keyStore, String keyPass,
+ String trustStore, String trustPass, String adminToken,
+ int maxActive, long timeBetweenEvictionRunsMillis,
+ long minEvictableIdleTimeMillis) {
+ // Setup auth URL
+ String protocol = (port == 35357) ? "https://" : "http://";
+ String urlStr = protocol + host + ":" + port;
+ uri = URI.create(urlStr);
+
+ // Setup connection pool
+ SchemeRegistry schemeRegistry = new SchemeRegistry();
+ if (protocol.startsWith("https")) {
+ SSLSocketFactory sslf = sslFactory(keyStore, keyPass, trustStore,
+ trustPass, clientAuth);
+ schemeRegistry.register(new Scheme("https", port, sslf));
+ } else {
+ schemeRegistry.register(new Scheme("http", port, PlainSocketFactory
+ .getSocketFactory()));
+ }
+ connMgr = new PoolingClientConnectionManager(schemeRegistry,
+ minEvictableIdleTimeMillis, TimeUnit.MILLISECONDS);
+
+ connMgr.setMaxTotal(maxActive);
+ connMgr.setDefaultMaxPerRoute(maxActive);
+
+ // Http connection timeout
+ HttpParams params = new BasicHttpParams();
+ params.setParameter(CoreConnectionPNames.SO_TIMEOUT, timeout);
+ params.setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, timeout);
+
+ // Create a single client
+ client = new DefaultHttpClient(connMgr, params);
+
+ // Create and start the connection pool cleaner
+ cleaner = new HttpPoolCleaner(connMgr, timeBetweenEvictionRunsMillis,
+ minEvictableIdleTimeMillis);
+ new Thread(cleaner).start();
+
+ }
+
+ @Override
+ public Object makeObject() throws Exception {
+ return new HttpAuthClient(client, uri);
+ }
+
+ @Override
+ public void passivateObject(Object obj) throws Exception {
+ ((HttpAuthClient) obj).reset();
+ }
+
+ @Override
+ public void destroyObject(Object obj) throws Exception {
+ ((HttpAuthClient) obj).reset();
+ obj = null;
+ }
+
+ public void shutDown() {
+ // Shutdown all connections
+ connMgr.shutdown();
+ // Shutdown connection pool cleaner
+ cleaner.shutdown();
+ }
+
+ // get a socket factory
+ private static SSLSocketFactory sslFactory(String keyStore, String keyPass,
+ String trustStore, String trustPass, boolean clientAuth) {
+ try {
+ // keystore
+ KeyStore ks = null;
+ if (clientAuth) {
+ ks = KeyStore.getInstance("jks");
+ FileInputStream is1 = new FileInputStream(new File(keyStore));
+ try {
+ ks.load(is1, keyPass.toCharArray());
+ } finally {
+ is1.close();
+ }
+ }
+ // truststore
+ KeyStore ts = KeyStore.getInstance("jks");
+ FileInputStream is2 = new FileInputStream(
+ new File(trustStore));
+ try {
+ ts.load(is2, trustPass.toCharArray());
+ } finally {
+ is2.close();
+ }
+ SSLSocketFactory sslf = new SSLSocketFactory(ks, keyPass, ts);
+ return sslf;
+ } catch (Exception e) {
+ throw new AuthConnectionException(
+ "Failed to create SSLSocketFactory", e);
+ }
+ }
+}
diff --git a/java/mon-middleware/src/main/java/com/hpcloud/middleware/HttpPoolCleaner.java b/java/mon-middleware/src/main/java/com/hpcloud/middleware/HttpPoolCleaner.java
new file mode 100644
index 00000000..1d01bb57
--- /dev/null
+++ b/java/mon-middleware/src/main/java/com/hpcloud/middleware/HttpPoolCleaner.java
@@ -0,0 +1,56 @@
+package com.hpcloud.middleware;
+
+import java.util.concurrent.TimeUnit;
+
+import org.apache.http.conn.ClientConnectionManager;
+
+/**
+ * A runner to clean the connection pool! There should only be one!
+ *
+ * @author liemmn
+ *
+ */
+public class HttpPoolCleaner implements Runnable {
+ private final ClientConnectionManager connMgr;
+ private long timeBetweenEvictionRunsMillis, minEvictableIdleTimeMillis;
+ private volatile boolean shutdown;
+
+ public HttpPoolCleaner(ClientConnectionManager connMgr,
+ long timeBetweenEvictionRunsMillis, long minEvictableIdleTimeMillis) {
+ this.connMgr = connMgr;
+ this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
+ this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
+ }
+
+ /**
+ * Start the cleaner.
+ */
+ @Override
+ public void run() {
+ try {
+ while (!shutdown) {
+ synchronized (this) {
+ wait(timeBetweenEvictionRunsMillis);
+ // Close expired connections
+ connMgr.closeExpiredConnections();
+ // Close connections that have been idle longer than x sec
+ connMgr.closeIdleConnections(minEvictableIdleTimeMillis,
+ TimeUnit.MILLISECONDS);
+ }
+ }
+ } catch (InterruptedException ex) {
+ // terminate
+ }
+ }
+
+ /**
+ * Shutdown the cleaner.
+ */
+ public void shutdown() {
+ shutdown = true;
+ synchronized (this) {
+ notifyAll();
+ }
+ }
+
+}
diff --git a/java/mon-middleware/src/main/java/com/hpcloud/middleware/SignatureBuilderException.java b/java/mon-middleware/src/main/java/com/hpcloud/middleware/SignatureBuilderException.java
new file mode 100644
index 00000000..b8c3b731
--- /dev/null
+++ b/java/mon-middleware/src/main/java/com/hpcloud/middleware/SignatureBuilderException.java
@@ -0,0 +1,15 @@
+package com.hpcloud.middleware;
+
+public class SignatureBuilderException extends RuntimeException {
+
+ private static final long serialVersionUID = -2643382825421961020L;
+
+ public SignatureBuilderException(String msg) {
+ super(msg);
+ }
+ public SignatureBuilderException(String msg, Exception e) {
+ super(msg, e);
+ }
+
+
+}
diff --git a/java/mon-middleware/src/main/java/com/hpcloud/middleware/SignatureExceptionHandler.java b/java/mon-middleware/src/main/java/com/hpcloud/middleware/SignatureExceptionHandler.java
new file mode 100644
index 00000000..db5dc0d3
--- /dev/null
+++ b/java/mon-middleware/src/main/java/com/hpcloud/middleware/SignatureExceptionHandler.java
@@ -0,0 +1,79 @@
+package com.hpcloud.middleware;
+
+import java.io.IOException;
+
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public enum SignatureExceptionHandler {
+
+ AuthConnectionException {
+ @Override
+ public void onException(Exception e, ServletResponse resp) {
+ AuthConnectionException ae = (AuthConnectionException) e;
+ logger.error(ae.getMessage() + " " + ae);
+ try {
+ ((HttpServletResponse) resp).sendError(
+ HttpServletResponse.SC_UNAUTHORIZED,
+ ExceptionHandlerUtil.getStatusText(HttpServletResponse.SC_UNAUTHORIZED));
+ } catch (IOException ie) {
+ logger.debug("Error in writing the HTTP response "
+ + ie.getMessage() + " " + ie);
+ }
+ }
+ },
+ TException {
+ @Override
+ public void onException(Exception e, ServletResponse resp) {
+ // TException t = (TException) e;
+ //logger.error("Thrift Exception " + t.getMessage() + " " + t);
+ try {
+ ((HttpServletResponse) resp).sendError(
+ HttpServletResponse.SC_UNAUTHORIZED,
+ ExceptionHandlerUtil.getStatusText(HttpServletResponse.SC_UNAUTHORIZED));
+ } catch (IOException ie) {
+ logger.debug("Error in writing the HTTP response "
+ + ie.getMessage() + " " + ie);
+ }
+ }
+ },
+ SignatureBuilderException {
+ @Override
+ public void onException(Exception e, ServletResponse resp) {
+ SignatureBuilderException sbe = (SignatureBuilderException) e;
+ logger.error(sbe.getMessage() + " " + sbe);
+ try {
+ ((HttpServletResponse) resp).sendError(
+ HttpServletResponse.SC_UNAUTHORIZED,
+ ExceptionHandlerUtil.getStatusText(HttpServletResponse.SC_UNAUTHORIZED));
+ } catch (IOException ie) {
+ logger.debug("Error in writing the HTTP response "
+ + ie.getMessage() + " " + ie);
+ }
+ }
+ },
+ AuthException {
+ @Override
+ public void onException(Exception e, ServletResponse resp) {
+ AuthException ae = (AuthException) e;
+ logger.error(ae.getMessage() + " " + ae);
+ try {
+ ((HttpServletResponse) resp).sendError(
+ HttpServletResponse.SC_UNAUTHORIZED,
+ ExceptionHandlerUtil.getStatusText(HttpServletResponse.SC_UNAUTHORIZED));
+ } catch (IOException ie) {
+ logger.debug("Error in writing the HTTP response "
+ + ie.getMessage() + " " + ie);
+ }
+ }
+ };
+
+ final Logger logger = LoggerFactory.getLogger(SignatureExceptionHandler.class);
+
+ abstract void onException(Exception e, ServletResponse resp);
+
+}
diff --git a/java/mon-middleware/src/main/java/com/hpcloud/middleware/TokenAuth.java b/java/mon-middleware/src/main/java/com/hpcloud/middleware/TokenAuth.java
new file mode 100644
index 00000000..7dce0a62
--- /dev/null
+++ b/java/mon-middleware/src/main/java/com/hpcloud/middleware/TokenAuth.java
@@ -0,0 +1,144 @@
+package com.hpcloud.middleware;
+
+import java.io.IOException;
+import org.apache.http.client.ClientProtocolException;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A token-based authentication filter. This filter uses Thrift protocol to
+ * communicate with the CS server. The token to validate is set via the header
+ * {@link #TOKEN}.
+ *
+ * A token is required to validate. However, if no token is presented, the
+ * filter will set the {@link #AUTH_IDENTITY_STATUS} request parameter to
+ * Invalid and let any other filter downstream to decide what to
+ * do. For instance, if a downstream filter knows how to deal with signature
+ * rather than tokens, then it will go ahead and validate with signatures.
+ *
+ * Upon successful validation, all the Auth request parameters will be
+ * populated, including information such as tenant, user and user roles, and
+ * passed down to the next filter downstream.
+ *
+ * Upon unsuccessful validation, this filter will terminate the request by
+ * returning a 401 (unauthorized).
+ *
+ * @author liemmn
+ *
+ */
+public class TokenAuth implements Filter, AuthConstants {
+
+ private static final String TOKEN_NOTFOUND = "Bad Request: Token not found in the request";
+ private static final String SERVICE_IDS_PARAM = "serviceIds";
+ private static final String ENDPOINT_IDS_PARAM = "endpointIds";
+ private static final String SERVICE_CATALOG_PARAM = "includeCatalog";
+ private static final String API_VERSION_PARAM = "apiVersion";
+
+ private final Config appConfig = Config.getInstance();
+
+ private FilterConfig filterConfig;
+
+ // Thee faithful logger
+ private static final Logger logger = LoggerFactory
+ .getLogger(TokenAuth.class);
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ this.filterConfig = filterConfig;
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ public void destroy() {
+ FilterUtils.destroyFilter();
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ public void doFilter(ServletRequest req, ServletResponse resp,
+ FilterChain chain) throws IOException, ServletException {
+ Object auth = null;
+ int numberOfTries = 0;
+ if (!appConfig.isInitialized()) {
+ appConfig.initialize(filterConfig,req,getInputParams());
+ }
+ int retries = appConfig.getRetries();
+ long pauseTime = appConfig.getPauseTime();
+ AuthClientFactory factory = appConfig.getFactory();
+
+ // Extract credential
+ String token = ((HttpServletRequest) req).getHeader(TOKEN);
+
+ if (token == null) {
+ if (!appConfig.isDelayAuthDecision()) {
+ logger.error(HttpServletResponse.SC_UNAUTHORIZED
+ + " No token found.");
+ ((HttpServletResponse) resp).sendError(
+ HttpServletResponse.SC_UNAUTHORIZED, TOKEN_NOTFOUND);
+ return;
+ } else {
+ logger.info("No token found...Skipping");
+ }
+ } else {
+ do {
+ try {
+ auth = FilterUtils.getCachedToken(token);
+ }catch(UnavailableException e) {
+ TokenExceptionHandler handler = TokenExceptionHandler
+ .valueOf("UnavailableException");
+ handler.onException(e,resp,token);
+ }
+ catch(ClientProtocolException e) {
+ if (numberOfTries < retries) {
+ FilterUtils.pause(pauseTime);
+ logger.debug("Retrying connection after "
+ + pauseTime + " seconds.");
+ numberOfTries++;
+ continue;
+ } else {
+ logger.debug("Exhausted retries..");
+ TokenExceptionHandler handler = TokenExceptionHandler
+ .valueOf("ClientProtocolException");
+ handler.onException(e, resp, token);
+ }
+ return;
+ }
+
+ }while(auth==null && numberOfTries<=retries);
+ }
+ req = FilterUtils.wrapRequest(req, auth);
+ logger.debug("TokenAuth: Forwarding down stream to next filter/servlet");
+ // Forward downstream...
+ chain.doFilter(req, resp);
+ }
+
+ private Map getInputParams() {
+ Map inputParams = new HashMap();
+ if (appConfig.getServiceIds() != null) {
+ inputParams.put(SERVICE_IDS_PARAM, appConfig.getServiceIds());
+ }
+ if (appConfig.getEndpointIds() != null) {
+ inputParams.put(ENDPOINT_IDS_PARAM, appConfig.getEndpointIds());
+ }
+ inputParams.put(SERVICE_CATALOG_PARAM, String.valueOf(appConfig.isIncludeCatalog()));
+ inputParams.put(API_VERSION_PARAM, appConfig.getAuthVersion());
+ return inputParams;
+ }
+
+
+}
diff --git a/java/mon-middleware/src/main/java/com/hpcloud/middleware/TokenCache.java b/java/mon-middleware/src/main/java/com/hpcloud/middleware/TokenCache.java
new file mode 100644
index 00000000..473518ae
--- /dev/null
+++ b/java/mon-middleware/src/main/java/com/hpcloud/middleware/TokenCache.java
@@ -0,0 +1,66 @@
+package com.hpcloud.middleware;
+
+import com.google.common.cache.*;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.thrift.TException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+
+
+public class TokenCache {
+
+ private final LoadingCache cache;
+ private final Config appConfig = Config.getInstance();
+ private AuthClientFactory factory;
+ private AuthClient client;
+ private static final Logger logger = LoggerFactory
+ .getLogger(TokenCache.class);
+
+
+ public TokenCache(final long maxSize, final long timeToExpire, final Map map) {
+ factory = appConfig.getFactory();
+
+ cache = CacheBuilder.newBuilder().maximumSize(maxSize)
+ .expireAfterWrite(timeToExpire, TimeUnit.SECONDS)
+ .build(new CacheLoader() {
+ public V load(K key) throws TException, ClientProtocolException {
+
+ V value = null;
+ AuthClient client = null;
+
+ try {
+ client = factory.getClient();
+ if (appConfig.getAuthVersion().equals("v2.0")) {
+ value = (V) client.validateTokenForServiceEndpointV2((String) key, appConfig.getServiceIds(),
+ appConfig.getEndpointIds(), appConfig.isIncludeCatalog());
+ } else {
+ value = (V) client.validateTokenForServiceEndpointV3((String) key, map);
+ }
+ } finally {
+ if (client != null)
+ factory.recycle(client);
+ }
+ return value;
+ }
+ });
+ }
+
+ public V getToken(K key) throws ClientProtocolException {
+ V value = null;
+ try {
+ value = cache.get(key);
+ } catch (ExecutionException e) {
+ logger.debug("had problem caching token");
+ }
+ return value;
+ }
+
+ public void put(K key, V value) {
+ cache.put(key, value);
+ }
+
+}
diff --git a/java/mon-middleware/src/main/java/com/hpcloud/middleware/TokenExceptionHandler.java b/java/mon-middleware/src/main/java/com/hpcloud/middleware/TokenExceptionHandler.java
new file mode 100644
index 00000000..9ffac02e
--- /dev/null
+++ b/java/mon-middleware/src/main/java/com/hpcloud/middleware/TokenExceptionHandler.java
@@ -0,0 +1,106 @@
+package com.hpcloud.middleware;
+
+import java.io.IOException;
+
+import org.apache.http.client.ClientProtocolException;
+
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.thrift.TException;
+
+public enum TokenExceptionHandler {
+
+ AuthConnectionException {
+ @Override
+ public void onException(Exception e, ServletResponse resp, String token) {
+ AuthConnectionException ae = (AuthConnectionException) e;
+ logger.error(ae.getMessage() + " " + ae);
+ try {
+ ((HttpServletResponse) resp).sendError(
+ HttpServletResponse.SC_UNAUTHORIZED,
+ ExceptionHandlerUtil.getStatusText(HttpServletResponse.SC_UNAUTHORIZED)
+ + " " + token);
+ } catch (IOException ie) {
+ logger.debug("Error in writing the HTTP response "
+ + ie.getMessage() + " " + ie);
+ }
+ }
+ },
+ TException {
+ @Override
+ public void onException(Exception e, ServletResponse resp, String token) {
+ TException t = (TException) e;
+ logger.error("Thrift Exception " + t.getMessage() + " " + t);
+ try {
+ ((HttpServletResponse) resp).sendError(
+ HttpServletResponse.SC_UNAUTHORIZED,
+ ExceptionHandlerUtil.getStatusText(HttpServletResponse.SC_UNAUTHORIZED)
+ + " " + token);
+ } catch (IOException ie) {
+ logger.debug("Error in writing the HTTP response "
+ + ie.getMessage() + " " + ie);
+ }
+ }
+ },
+ ClientProtocolException {
+ @Override
+ public void onException(Exception e, ServletResponse resp, String token) {
+ ClientProtocolException t = (ClientProtocolException) e;
+ logger.error("Http Client Exception " + t.getMessage() + " " + t);
+ try {
+ ((HttpServletResponse) resp).sendError(
+ HttpServletResponse.SC_UNAUTHORIZED,
+ ExceptionHandlerUtil.getStatusText(HttpServletResponse.SC_UNAUTHORIZED)
+ + " " + token);
+ } catch (IOException ie) {
+ logger.debug("Error in writing the HTTP response "
+ + ie.getMessage() + " " + ie);
+ }
+ }
+ },
+ AuthException {
+ @Override
+ public void onException(Exception e, ServletResponse resp, String token) {
+ AuthException ae = (AuthException) e;
+ logger.error(ae.getMessage() + " " + ae);
+ String statusText = ae.getMessage();
+ if (statusText == null || statusText.isEmpty()) {
+ statusText = ExceptionHandlerUtil.getStatusText(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+ try {
+ ((HttpServletResponse) resp).sendError(
+ HttpServletResponse.SC_UNAUTHORIZED,
+ statusText + " " + token);
+ } catch (IOException ie) {
+ logger.debug("Error in writing the HTTP response "
+ + ie.getMessage() + " " + ie);
+ }
+ }
+ }, ServiceUnavailableException {
+ @Override
+ public void onException(Exception e, ServletResponse resp, String token) {
+ AuthException ae = (AuthException) e;
+ logger.error(ae.getMessage() + " " + ae);
+ String statusText = ae.getMessage();
+ if (statusText == null || statusText.isEmpty()) {
+ statusText = ExceptionHandlerUtil.getStatusText(HttpServletResponse.SC_UNAUTHORIZED);
+ }
+ try {
+ ((HttpServletResponse) resp).sendError(
+ HttpServletResponse.SC_UNAUTHORIZED,
+ statusText + " " + token);
+ } catch (IOException ie) {
+ logger.debug("Error in writing the HTTP response "
+ + ie.getMessage() + " " + ie);
+ }
+ }
+ };
+
+ final Logger logger = LoggerFactory.getLogger(TokenExceptionHandler.class);
+
+ abstract void onException(Exception e, ServletResponse resp, String token);
+}
diff --git a/java/mon-middleware/src/main/java/com/hpcloud/middleware/UnavailableException.java b/java/mon-middleware/src/main/java/com/hpcloud/middleware/UnavailableException.java
new file mode 100644
index 00000000..c07cacac
--- /dev/null
+++ b/java/mon-middleware/src/main/java/com/hpcloud/middleware/UnavailableException.java
@@ -0,0 +1,17 @@
+package com.hpcloud.middleware;
+
+/**
+ * Created by johnderr on 6/25/14.
+ */
+public class UnavailableException extends RuntimeException {
+
+ private static final long serialVersionUID = -2353922744077869466L;
+
+ public UnavailableException(String msg) {
+ super(msg);
+ }
+
+ public UnavailableException(String msg, Exception e) {
+ super(msg, e);
+ }
+}