not authenticating
This commit is contained in:
parent
648bb38cd8
commit
a83e51c9fa
34
pom.xml
34
pom.xml
|
@ -119,11 +119,43 @@
|
|||
<artifactId>jsr305</artifactId>
|
||||
<version>2.0.0</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<!-- <dependency>
|
||||
<groupId>com.hp.csbu.cc</groupId>
|
||||
<artifactId>CsMiddleware</artifactId>
|
||||
<version>3.34.0</version>
|
||||
</dependency> -->
|
||||
<!-- removing CSMiddleware -->
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
<version>4.3.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<version>2.2.4</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-pool</groupId>
|
||||
<artifactId>commons-pool</artifactId>
|
||||
<version>1.6</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.thrift</groupId>
|
||||
<artifactId>libthrift</artifactId>
|
||||
<version>0.9.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-collections4</artifactId>
|
||||
<version>4.0</version>
|
||||
</dependency>
|
||||
|
||||
<!-- removing CSMiddleware -->
|
||||
<dependency>
|
||||
<groupId>org.apache.curator</groupId>
|
||||
<artifactId>curator-recipes</artifactId>
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.thrift.TException;
|
||||
/*import org.apache.thrift.TException;
|
||||
|
||||
import com.hp.csbu.cc.security.cs.thrift.service.AuthResponse;
|
||||
import com.hp.csbu.cc.security.cs.thrift.service.ResourceException;
|
||||
import com.hp.csbu.cc.security.cs.thrift.service.SigAuthRequest; */
|
||||
|
||||
|
||||
/**
|
||||
* A client that can communicate to an authentication server for authentication.
|
||||
*
|
||||
* @author liemmn
|
||||
*
|
||||
*/
|
||||
public interface AuthClient {
|
||||
public Object validateTokenForServiceEndpointV2(String token,
|
||||
String serviceIds, String endpointIds, boolean includeCatalog)
|
||||
throws TException, ClientProtocolException; //ResourceException
|
||||
public Object validateTokenForServiceEndpointV3(String token,
|
||||
Map<String, String> inputParams) throws TException, ClientProtocolException; //ResourceException
|
||||
|
||||
//public AuthResponse validateSignature(SigAuthRequest request) throws ResourceException, TException;
|
||||
|
||||
}
|
|
@ -0,0 +1,145 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
import org.apache.commons.pool.impl.GenericObjectPool;
|
||||
|
||||
//import com.hp.csbu.cc.security.cs.thrift.service.CsThriftService.Client;
|
||||
|
||||
/**
|
||||
* A factory for building {@link AuthClient}s.
|
||||
*
|
||||
* @author liemmn
|
||||
*
|
||||
*/
|
||||
public abstract class AuthClientFactory {
|
||||
private static AuthClientFactory instance = null;
|
||||
protected static GenericObjectPool pool;
|
||||
|
||||
/**
|
||||
* Build a AuthClientFactory. Singleton.
|
||||
*
|
||||
* @param host
|
||||
* Auth host
|
||||
* @param port
|
||||
* Auth port
|
||||
* @param timeout
|
||||
* Auth connection timeout
|
||||
* @param clientAuth
|
||||
* 2-way SSL (if false, 1-way SSL is used)
|
||||
* @param keyStore
|
||||
* Keystore
|
||||
* @param keyPass
|
||||
* Keystore password
|
||||
* @param trustStore
|
||||
* Truststore
|
||||
* @param trustPass
|
||||
* Truststore password
|
||||
* @param maxActive
|
||||
* Maximum number of objects that can be allocated by the pool
|
||||
* (checked out to clients, or idle awaiting checkout) at a given
|
||||
* time. When non-positive, there is no limit to the number of
|
||||
* objects that can be managed by the pool at one time. When
|
||||
* maxActive is reached, the pool is said to be exhausted. The
|
||||
* default setting for this parameter is 8.
|
||||
* @param maxIdle
|
||||
* Maximum number of objects that can sit idle in the pool at any
|
||||
* time. When negative, there is no limit to the number of
|
||||
* objects that may be idle at one time. The default setting for
|
||||
* this parameter is 8.
|
||||
* @param timeBetweenEvictionRunsMillis
|
||||
* How long the eviction thread should sleep before "runs" of
|
||||
* examining idle objects. When non-positive, no eviction thread
|
||||
* will be launched. The default setting for this parameter is -1
|
||||
* (i.e., idle object eviction is disabled by default).
|
||||
* @param minEvictableIdleTimeMillis
|
||||
* Minimum amount of time that an object may sit idle in the pool
|
||||
* before it is eligible for eviction due to idle time. When
|
||||
* non-positive, no object will be dropped from the pool due to
|
||||
* idle time alone. This setting has no effect unless
|
||||
* timeBetweenEvictionRunsMillis > 0. The default setting for
|
||||
* this parameter is 30 minutes.
|
||||
* @param adminToken
|
||||
* Admin token for use with vanilla Keystone.
|
||||
*
|
||||
* @return AuthClientFactory singleton.
|
||||
* @throws Exception
|
||||
*/
|
||||
public static synchronized AuthClientFactory build(String host, int port,
|
||||
int timeout, boolean clientAuth, String keyStore, String keyPass,
|
||||
String trustStore, String trustPass, int maxActive, int maxIdle,
|
||||
long timeBetweenEvictionRunsMillis,
|
||||
long minEvictableIdleTimeMillis, String adminToken)
|
||||
throws Exception {
|
||||
if (instance == null) {
|
||||
/*if (port == 9543) {
|
||||
instance = new ThriftClientFactory(host, port, timeout,
|
||||
clientAuth, keyStore, keyPass, trustStore, trustPass);
|
||||
} else {*/
|
||||
instance = new HttpClientFactory(host, port, timeout,
|
||||
clientAuth, keyStore, keyPass, trustStore, trustPass,
|
||||
adminToken, maxActive, timeBetweenEvictionRunsMillis,
|
||||
minEvictableIdleTimeMillis);
|
||||
// }
|
||||
// Pool tweaking
|
||||
pool.setMaxActive(maxActive);
|
||||
pool.setMaxIdle(maxIdle);
|
||||
pool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
|
||||
pool.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a client. Don't forget to {@link #recycleClient(Client)} after you
|
||||
* are done using it, successfully or not.
|
||||
*
|
||||
* @return Client
|
||||
* @throws Exception
|
||||
*/
|
||||
public AuthClient getClient() {
|
||||
try {
|
||||
return (AuthClient) pool.borrowObject();
|
||||
} catch (Exception e) {
|
||||
throw new AuthConnectionException("Failed to get a client "+ e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recycle the client for next usage.
|
||||
*
|
||||
* @param client
|
||||
* Client to recycle
|
||||
* @throws Exception
|
||||
*/
|
||||
public void recycle(AuthClient client) {
|
||||
try {
|
||||
pool.returnObject(client);
|
||||
} catch (Exception e) {
|
||||
throw new AuthConnectionException("Failed to recycle client", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this if the client is unusable (i.e., exception).
|
||||
*
|
||||
* @param client
|
||||
* Client to discard.
|
||||
*/
|
||||
public void discard(AuthClient client) {
|
||||
try {
|
||||
pool.invalidateObject(client);
|
||||
} catch (Exception e) {
|
||||
throw new AuthConnectionException("Failed to destroy client", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shut down this factory.
|
||||
*/
|
||||
public void shutdown() {
|
||||
try {
|
||||
pool.close();
|
||||
} catch (Exception e) {
|
||||
throw new AuthConnectionException("Failed to close client pool", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
/**
|
||||
* An exception to indicate any connection issue.
|
||||
*
|
||||
* @author liemmn
|
||||
*
|
||||
*/
|
||||
public class AuthConnectionException extends RuntimeException {
|
||||
private static final long serialVersionUID = 4318025130590973448L;
|
||||
|
||||
public AuthConnectionException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
public AuthConnectionException(String msg, Exception e) {
|
||||
super(msg, e);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,183 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
public interface AuthConstants {
|
||||
/** 'Confirmed' or 'Invalid' */
|
||||
public static enum IdentityStatus {
|
||||
Confirmed, Invalid
|
||||
}
|
||||
|
||||
// =============================== TOKEN ===================================
|
||||
/** Credential (token) header */
|
||||
public static final String TOKEN = "X-AUTH-TOKEN";
|
||||
/** Auth status parameter */
|
||||
public static final String AUTH_IDENTITY_STATUS = "X-IDENTITY-STATUS";
|
||||
/** Auth user Id parameter */
|
||||
public static final String AUTH_USER_ID = "X-USER-ID";
|
||||
/** Auth user name parameter */
|
||||
public static final String AUTH_USER_NAME = "X-USER-NAME";
|
||||
|
||||
/** Auth user roles parameter, comma-separated roles */
|
||||
public static final String AUTH_ROLES = "X-ROLES";
|
||||
/** json encoded keystone service catalog */
|
||||
public static final String AUTH_SERVICE_CATALOG = "X-SERVICE-CATALOG";
|
||||
/** Service Ids initialization parameter */
|
||||
public static final String SERVICE_IDS = "ServiceIds";
|
||||
/** Endpoint Ids initialization parameter */
|
||||
public static final String ENDPOINT_IDS = "EndpointIds";
|
||||
/** Keystone admin token for use in vanilla Keystone */
|
||||
public static final String ADMIN_TOKEN = "AdminToken";
|
||||
|
||||
// ============================ CONNECTION =================================
|
||||
/** Auth server initialization parameter */
|
||||
public static final String SERVER_VIP = "ServerVIP";
|
||||
/** Auth server port: 9543 for Thrift, 35357 for HTTP. */
|
||||
public static final String SERVER_PORT = "ServerPort";
|
||||
/** connection timeout initialization parameter */
|
||||
public static final String CONN_TIMEOUT = "ConnTimeout";
|
||||
/** 2-way SSL initialization parameter: True or False */
|
||||
public static final String CONN_SSL_CLIENT_AUTH = "ConnSSLClientAuth";
|
||||
/** SSL keystore initialization parameter */
|
||||
public static final String KEYSTORE = "Keystore";
|
||||
/** SSL keystore password initialization parameter */
|
||||
public static final String KEYSTORE_PASS = "KeystorePass";
|
||||
/** SSL truststore initialization parameter */
|
||||
public static final String TRUSTSTORE = "Truststore";
|
||||
/** SSL truststore password initialization parameter */
|
||||
public static final String TRUSTSTORE_PASS = "TruststorePass";
|
||||
|
||||
// ============================== POOLING ==================================
|
||||
/**
|
||||
* Maximum number of objects that can be allocated by the pool (checked out
|
||||
* to clients, or idle awaiting checkout) at a given time. When
|
||||
* non-positive, there is no limit to the number of objects that can be
|
||||
* managed by the pool at one time. When maxActive is reached, the pool is
|
||||
* said to be exhausted. The default setting for this parameter is 8.
|
||||
*/
|
||||
public static final String CONN_POOL_MAX_ACTIVE = "ConnPoolMaxActive";
|
||||
/**
|
||||
* Maximum number of objects that can sit idle in the pool at any time. When
|
||||
* negative, there is no limit to the number of objects that may be idle at
|
||||
* one time. The default setting for this parameter is 8.
|
||||
*/
|
||||
public static final String CONN_POOL_MAX_IDLE = "ConnPoolMaxIdle";
|
||||
/**
|
||||
* How long the eviction thread should sleep before "runs" of examining idle
|
||||
* objects. When non-positive, no eviction thread will be launched. The
|
||||
* default setting for this parameter is -1 (i.e., idle object eviction is
|
||||
* disabled by default).
|
||||
*/
|
||||
public static final String CONN_POOL_EVICT_PERIOD = "ConnPoolEvictPeriod";
|
||||
/**
|
||||
* Minimum amount of time that an object may sit idle in the pool before it
|
||||
* is eligible for eviction due to idle time. When non-positive, no object
|
||||
* will be dropped from the pool due to idle time alone. This setting has no
|
||||
* effect unless ConnPoolEvictPeriod > 0. The default setting for this
|
||||
* parameter is 30 minutes.
|
||||
*/
|
||||
public static final String CONN_POOL_MIN_IDLE_TIME = "ConnPoolMinIdleTime";
|
||||
|
||||
// ============================== CACHING ==================================
|
||||
/** Memcache hosts */
|
||||
public static final String MEMCACHE_HOSTS = "MemcacheHosts";
|
||||
/** Memcache connection timeout */
|
||||
public static final String MEMCACHE_TIMEOUT = "MemcacheTimeout";
|
||||
/** Memcache encryption */
|
||||
public static final String MEMCACHE_ENCRYPT = "MemcacheEncrypt";
|
||||
|
||||
/** Number of connection timeout retries **/
|
||||
public static final String CONN_TIMEOUT_RETRIES = "ConnRetryTimes";
|
||||
/** Number of connection timeout retries **/
|
||||
public static final String PAUSE_BETWEEN_RETRIES = "ConnRetryInterval";
|
||||
/** Authentication decision is forwarded to next filter **/
|
||||
public static final String DELAY_AUTH_DECISION = "DelayAuthDecision";
|
||||
|
||||
public static final String SIGNATURE_METHOD = "HmacSHA1";
|
||||
|
||||
/** Version of CS to authenticate the credentials **/
|
||||
public static final String AUTH_VERSION = "AuthVersion";
|
||||
|
||||
/** Include Service Catalog as part of Authentication Response **/
|
||||
public static final String INCLUDE_SERVICE_CATALOG = "IncludeServiceCatalog";
|
||||
|
||||
/**
|
||||
* Identity service managed unique identifier, string. Only present if this
|
||||
* is a project-scoped v3 token, or a tenant-scoped v2 token.
|
||||
**/
|
||||
public static final String AUTH_PROJECT_ID = "X-PROJECT-ID";
|
||||
|
||||
/**
|
||||
* Project name, unique within owning domain, string. Only present if this
|
||||
* is a project-scoped v3 token, or a tenant-scoped v2 token.
|
||||
**/
|
||||
public static final String AUTH_PROJECT_NAME = "X-PROJECT-NAME";
|
||||
|
||||
/**
|
||||
* Identity service managed unique identifier of owning domain of project,
|
||||
* string. Only present if this is a project-scoped v3 token. If this
|
||||
* variable is set, this indicates that the PROJECT_NAME can only be assumed
|
||||
* to be unique within this domain.
|
||||
**/
|
||||
public static final String AUTH_PROJECT_DOMAIN_ID = "X-PROJECT-DOMAIN-ID";
|
||||
|
||||
/**
|
||||
* Name of owning domain of project, string. Only present if this is a
|
||||
* project-scoped v3 token. If this variable is set, this indicates that the
|
||||
* PROJECT_NAME can only be assumed to be unique within this domain.
|
||||
**/
|
||||
public static final String AUTH_PROJECT_DOMAIN_NAME = "X-PROJECT-DOMAIN-NAME";
|
||||
|
||||
/**
|
||||
* Identity service managed unique identifier of owning domain of user,
|
||||
* string. If this variable is set, this indicates that the USER_NAME can
|
||||
* only be assumed to be unique within this domain.
|
||||
**/
|
||||
public static final String AUTH_USER_DOMAIN_ID = "X-USER-DOMAIN-ID";
|
||||
|
||||
/**
|
||||
* Name of owning domain of user, string. If this variable is set, this
|
||||
* indicates that the USER_NAME can only be assumed to be unique within this
|
||||
* domain.
|
||||
**/
|
||||
public static final String AUTH_USER_DOMAIN_NAME = "X-USER-DOMAIN-NAME";
|
||||
|
||||
/**
|
||||
* Identity service managed unique identifier, string. Only present if this
|
||||
* is a domain-scoped v3 token.
|
||||
**/
|
||||
public static final String AUTH_DOMAIN_ID = "X-DOMAIN-ID";
|
||||
|
||||
/**
|
||||
* Unique domain name, string. Only present if this is a domain-scoped v3
|
||||
* token.
|
||||
**/
|
||||
public static final String AUTH_DOMAIN_NAME = "X-DOMAIN-NAME";
|
||||
|
||||
public static final String AUTH_HP_IDM_ROLES = "X-HP-IDM-Non-Tenant-Roles";
|
||||
|
||||
public static final String REMOTE_HOST = "RemoteHost";
|
||||
public static final String REMOTE_ADDR = "RemoteAddress";
|
||||
|
||||
// Depracated Headers.
|
||||
/** Auth user roles parameter, comma-separated roles */
|
||||
public static final String AUTH_ROLE = "X-ROLE";
|
||||
/** Auth tenant Id parameter */
|
||||
public static final String AUTH_TENANT_ID = "X-TENANT-ID";
|
||||
/** Auth tenant name parameter */
|
||||
public static final String AUTH_TENANT_NAME = "X-TENANT-NAME";
|
||||
/** Auth tenant name parameter */
|
||||
public static final String AUTH_TENANT = "X-TENANT";
|
||||
/**
|
||||
* *Deprecated* in favor of HTTP_X_USER_ID and HTTP_X_USER_NAME User name,
|
||||
* unique within owning domain, string
|
||||
**/
|
||||
public static final String AUTH_USER = "X-USER";
|
||||
|
||||
public static final String AUTH_SUBJECT_TOKEN = "X-Subject-Token";
|
||||
public static final String ADMIN_USER = "AdminUser";
|
||||
public static final String ADMIN_PASSWORD = "AdminPassword";
|
||||
public static final String ADMIN_AUTH_METHOD = "AdminAuthMethod";
|
||||
public static final String ADMIN_ACCESS_KEY = "AdminAccessKey";
|
||||
public static final String ADMIN_SECRET_KEY = "AdminSecretKey";
|
||||
public static final String ADMIN_PROJECT_ID = "AdminProjectId";
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
/**
|
||||
* An exception to indicate any authentication error.
|
||||
*
|
||||
* @author liemmn
|
||||
*
|
||||
*/
|
||||
public class AuthException extends RuntimeException {
|
||||
private static final long serialVersionUID = 2287073516214658461L;
|
||||
|
||||
public AuthException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public AuthException(String msg, Exception e) {
|
||||
super(msg, e);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class CatalogV3 {
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
public List getEndPoints() {
|
||||
return endPoints;
|
||||
}
|
||||
public void setEndPoints(List endPoints) {
|
||||
this.endPoints = endPoints;
|
||||
}
|
||||
String id;
|
||||
String type;
|
||||
List endPoints;
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,294 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class Config implements AuthConstants {
|
||||
|
||||
// Thee faithful logger
|
||||
private static final Logger logger = LoggerFactory
|
||||
.getLogger(Config.class);
|
||||
|
||||
private static final Config instance = new Config();
|
||||
|
||||
private static final String PASSWORD = "password";
|
||||
private static final String ACCESS_KEY = "accesskey";
|
||||
|
||||
// Application wide init param -- ServletContext
|
||||
private ServletContext context = null;
|
||||
|
||||
// Memcache client--There shall only be one
|
||||
///private MemcacheCrypt client = null;
|
||||
|
||||
private TokenCache<String, String> client = null;
|
||||
|
||||
// Auth client factory
|
||||
private AuthClientFactory factory = null;
|
||||
|
||||
// The service IDs that this filter serves
|
||||
private String serviceIds;
|
||||
|
||||
// The optional endpoint IDs that this filter serves
|
||||
private String endpointIds;
|
||||
|
||||
// Memcache timeout value
|
||||
private long memCacheTimeOut;
|
||||
|
||||
// flag to set if auth decision can be delegated to next filter
|
||||
private boolean delayAuthDecision;
|
||||
|
||||
// retries and pauseTime configuration for retry logic
|
||||
private int retries;
|
||||
private int pauseTime;
|
||||
|
||||
// configuration to authenticate against CS api
|
||||
private String authVersion;
|
||||
|
||||
// flag to include catalog in the response
|
||||
private boolean includeCatalog;
|
||||
|
||||
// configuration for admin authentication method to be used for 2-way SSL
|
||||
private String adminAuthMethod;
|
||||
|
||||
// configuration for admin default project
|
||||
private String adminProjectId;
|
||||
|
||||
// flag to indicate if the filter is already intialized with required parameters
|
||||
private volatile boolean initialized = false;
|
||||
|
||||
//context is not getting properly filed so will use FilterConfig
|
||||
private FilterConfig filterConfig;
|
||||
private Config() {
|
||||
}
|
||||
|
||||
public static Config getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public synchronized void initialize(FilterConfig config) throws ServletException {
|
||||
this.context = config.getServletContext();
|
||||
this.filterConfig = config;
|
||||
|
||||
try {
|
||||
// Initialize serviceIds...
|
||||
//serviceIds = context.getInitParameter(SERVICE_IDS);
|
||||
serviceIds = filterConfig.getInitParameter(SERVICE_IDS);
|
||||
// Initialize endpointIds...
|
||||
//endpointIds = context.getInitParameter(ENDPOINT_IDS);
|
||||
endpointIds = filterConfig.getInitParameter(ENDPOINT_IDS);
|
||||
|
||||
String somthing = context
|
||||
.getInitParameter(SERVER_PORT);
|
||||
// Initialize auth server connection parameters...
|
||||
//String host = context.getInitParameter(SERVER_VIP);
|
||||
String host = filterConfig.getInitParameter(SERVER_VIP);
|
||||
|
||||
//int port = Integer.parseInt(context
|
||||
// .getInitParameter(SERVER_PORT));
|
||||
|
||||
int port = Integer.parseInt(filterConfig.getInitParameter(SERVER_PORT));
|
||||
|
||||
// HP Keystone Server only supports authentication against
|
||||
// V3.0 api
|
||||
authVersion = getValue(AUTH_VERSION, "v3.0");
|
||||
|
||||
if ((serviceIds == null || serviceIds.isEmpty())
|
||||
&& (endpointIds == null || endpointIds.isEmpty())
|
||||
&& authVersion.equalsIgnoreCase("v2.0")) {
|
||||
throw new Throwable("Need to specify " + SERVICE_IDS);
|
||||
}
|
||||
|
||||
// Initialize memcache...
|
||||
String cacheHosts = context.getInitParameter(MEMCACHE_HOSTS);
|
||||
boolean isEncrypted = Boolean.valueOf(context
|
||||
.getInitParameter(MEMCACHE_ENCRYPT));
|
||||
memCacheTimeOut = getValue(MEMCACHE_TIMEOUT, 2000L);
|
||||
/* if (cacheHosts != null && !cacheHosts.isEmpty()) {
|
||||
this.client = new MemcacheCrypt(cacheHosts, isEncrypted);
|
||||
}*/
|
||||
|
||||
this.client = new TokenCache<>(getValue(MEMCACHE_TIMEOUT,2000L));
|
||||
// Initialize Certificates
|
||||
/*String keyStore = context.getInitParameter(KEYSTORE);
|
||||
String keyPass = context.getInitParameter(KEYSTORE_PASS);
|
||||
String trustStore = context.getInitParameter(TRUSTSTORE);
|
||||
String trustPass = context.getInitParameter(TRUSTSTORE_PASS);*/
|
||||
|
||||
String keyStore = filterConfig.getInitParameter(KEYSTORE);
|
||||
String keyPass = filterConfig.getInitParameter(KEYSTORE_PASS);
|
||||
String trustStore = filterConfig.getInitParameter(TRUSTSTORE);
|
||||
String trustPass = filterConfig.getInitParameter(TRUSTSTORE_PASS);
|
||||
|
||||
String adminToken = getValue(ADMIN_TOKEN, "");
|
||||
int timeout = getValue(CONN_TIMEOUT, 0);
|
||||
boolean clientAuth = getValue(CONN_SSL_CLIENT_AUTH, true);
|
||||
int maxActive = getValue(CONN_POOL_MAX_ACTIVE, 3);
|
||||
int maxIdle = getValue(CONN_POOL_MAX_IDLE, 3);
|
||||
long evictPeriod = getValue(CONN_POOL_EVICT_PERIOD, 60000L);
|
||||
long minIdleTime = getValue(CONN_POOL_MIN_IDLE_TIME, 90000L);
|
||||
retries = getValue(CONN_TIMEOUT_RETRIES, 3);
|
||||
pauseTime = getValue(PAUSE_BETWEEN_RETRIES, 100);
|
||||
delayAuthDecision = getValue(DELAY_AUTH_DECISION, false);
|
||||
includeCatalog = getValue(INCLUDE_SERVICE_CATALOG, true);
|
||||
adminAuthMethod = getValue(ADMIN_AUTH_METHOD, "");
|
||||
adminProjectId = getValue(ADMIN_PROJECT_ID, "");
|
||||
this.factory = AuthClientFactory.build(host, port, timeout,
|
||||
clientAuth, keyStore, keyPass, trustStore, trustPass,
|
||||
maxActive, maxIdle, evictPeriod, minIdleTime, adminToken);
|
||||
verifyRequiredParamsForAuthMethod();
|
||||
logger.info("Auth host (2-way SSL: " + clientAuth + "): " + host);
|
||||
logger.info("Read Servlet Initialization Parameters ");
|
||||
initialized = true;
|
||||
} catch (Throwable t) {
|
||||
logger.error("Failed to read Servlet Initialization Parameters ",
|
||||
t.getMessage());
|
||||
throw new ServletException(
|
||||
"Failed to read Servlet Initialization Parameters :: "
|
||||
+ t.getMessage(), t);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
return initialized;
|
||||
}
|
||||
|
||||
protected String getAdminProject() {
|
||||
return adminProjectId;
|
||||
}
|
||||
|
||||
protected String getAdminAccessKey() {
|
||||
if (context.getAttribute(ADMIN_ACCESS_KEY) != null) {
|
||||
return (String) context.getAttribute(ADMIN_ACCESS_KEY);
|
||||
} else {
|
||||
return getValue(ADMIN_ACCESS_KEY, "");
|
||||
}
|
||||
}
|
||||
|
||||
protected String getAdminSecretKey() {
|
||||
if (context.getAttribute(ADMIN_SECRET_KEY) != null) {
|
||||
return (String) context.getAttribute(ADMIN_SECRET_KEY);
|
||||
} else {
|
||||
return getValue(ADMIN_SECRET_KEY, "");
|
||||
}
|
||||
}
|
||||
|
||||
protected String getAdminAuthMethod() {
|
||||
return adminAuthMethod;
|
||||
}
|
||||
|
||||
protected String getAdminUser() {
|
||||
if (context.getAttribute(ADMIN_USER) != null) {
|
||||
return (String) context.getAttribute(ADMIN_USER);
|
||||
} else {
|
||||
return getValue(ADMIN_USER, "");
|
||||
}
|
||||
}
|
||||
|
||||
protected String getAdminPassword() {
|
||||
if (context.getAttribute(ADMIN_PASSWORD) != null) {
|
||||
return (String) context.getAttribute(ADMIN_PASSWORD);
|
||||
} else {
|
||||
return getValue(ADMIN_PASSWORD, "");
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean isIncludeCatalog() {
|
||||
return includeCatalog;
|
||||
}
|
||||
|
||||
protected long getMemCacheTimeOut() {
|
||||
return memCacheTimeOut;
|
||||
}
|
||||
|
||||
protected String getAuthVersion() {
|
||||
return authVersion;
|
||||
}
|
||||
|
||||
protected void setMemCacheTimeOut(long memCacheTimeOut) {
|
||||
this.memCacheTimeOut = memCacheTimeOut;
|
||||
}
|
||||
|
||||
// Is caching enabled?
|
||||
protected boolean isCaching() {
|
||||
//return this.client != null;
|
||||
return false;
|
||||
}
|
||||
|
||||
protected ServletContext getConfig() {
|
||||
return context;
|
||||
}
|
||||
|
||||
/*protected MemcacheCrypt getClient() {
|
||||
return client;
|
||||
}*/
|
||||
protected TokenCache getClient() {
|
||||
return client;
|
||||
}
|
||||
|
||||
protected AuthClientFactory getFactory() {
|
||||
return factory;
|
||||
}
|
||||
|
||||
protected String getServiceIds() {
|
||||
return serviceIds;
|
||||
}
|
||||
|
||||
protected String getEndpointIds() {
|
||||
return endpointIds;
|
||||
}
|
||||
|
||||
protected boolean isDelayAuthDecision() {
|
||||
return delayAuthDecision;
|
||||
}
|
||||
|
||||
protected int getRetries() {
|
||||
return retries;
|
||||
}
|
||||
|
||||
protected int getPauseTime() {
|
||||
return pauseTime;
|
||||
}
|
||||
|
||||
private <T> T getValue(String paramName, T defaultValue) {
|
||||
Class type = defaultValue.getClass();
|
||||
//String initparamValue = context.getInitParameter(paramName);
|
||||
String initparamValue = filterConfig.getInitParameter(paramName);
|
||||
if (initparamValue != null && !initparamValue.isEmpty()) {
|
||||
if (type.equals(Integer.class)) {
|
||||
int paramValue = Integer.parseInt(initparamValue);
|
||||
return (T) type.cast(paramValue);
|
||||
} else if (type.equals(Long.class)) {
|
||||
long paramValue = Long.parseLong(initparamValue);
|
||||
return (T) type.cast(paramValue);
|
||||
} else if (type.equals(Boolean.class)) {
|
||||
boolean paramValue = Boolean.parseBoolean(initparamValue);
|
||||
return (T) type.cast(paramValue);
|
||||
} else if (type.equals(String.class)) {
|
||||
return (T) type.cast(initparamValue);
|
||||
}
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private void verifyRequiredParamsForAuthMethod() {
|
||||
if (adminAuthMethod.equalsIgnoreCase(PASSWORD)) {
|
||||
if (getAdminUser().isEmpty() || getAdminPassword().isEmpty()) {
|
||||
String msg = String
|
||||
.format("admin user and password must be specified if admin auth method is %s",
|
||||
adminAuthMethod);
|
||||
throw new AuthException(msg);
|
||||
}
|
||||
} else if (adminAuthMethod.equalsIgnoreCase(ACCESS_KEY)) {
|
||||
if (getAdminAccessKey().isEmpty() || getAdminSecretKey().isEmpty()) {
|
||||
String msg = String
|
||||
.format("admin access and secret key must be specified if admin auth method is %s",
|
||||
adminAuthMethod);
|
||||
throw new AuthException(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
/**
|
||||
* An exception caused for memcache decryption issues.
|
||||
*
|
||||
* @author liemmn
|
||||
*
|
||||
*/
|
||||
public class DecryptionException extends RuntimeException {
|
||||
private static final long serialVersionUID = 5463487714560524511L;
|
||||
|
||||
public DecryptionException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public DecryptionException(String msg, Exception e) {
|
||||
super(msg, e);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
/**
|
||||
* Memcache encryption exception.
|
||||
*
|
||||
* @author liemmn
|
||||
*
|
||||
*/
|
||||
public class EncryptionException extends RuntimeException {
|
||||
private static final long serialVersionUID = 8249423387842730866L;
|
||||
|
||||
public EncryptionException(String msg) {
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public EncryptionException(String msg, Exception e) {
|
||||
super(msg, e);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
public class ExceptionHandlerUtil {
|
||||
|
||||
public final static String SERVICE_UNAVAILABLE = "Service Unavailable";
|
||||
public final static String UNAUTHORIZED_TOKEN = "Unauthorized Token";
|
||||
public final static String INTERNAL_SERVER_ERROR = "Internal Server Error";
|
||||
|
||||
private ExceptionHandlerUtil() {
|
||||
}
|
||||
|
||||
public static String getStatusText(int errorCode) {
|
||||
if (errorCode == 401) {
|
||||
return UNAUTHORIZED_TOKEN;
|
||||
}
|
||||
if (errorCode == 503) {
|
||||
return SERVICE_UNAVAILABLE;
|
||||
}
|
||||
if (errorCode == 500) {
|
||||
return INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
return "Unknown Error";
|
||||
|
||||
}
|
||||
|
||||
public static TokenExceptionHandler lookUpTokenException(Exception ex) {
|
||||
try {
|
||||
return TokenExceptionHandler.valueOf(ex.getClass().getSimpleName());
|
||||
} catch (IllegalArgumentException iae) {
|
||||
return TokenExceptionHandler.valueOf("ResourceException");
|
||||
}
|
||||
}
|
||||
|
||||
/*public static SignatureExceptionHandler lookUpSignatureException(Exception ex) {
|
||||
try {
|
||||
return SignatureExceptionHandler.valueOf(ex.getClass().getSimpleName());
|
||||
} catch (IllegalArgumentException iae) {
|
||||
return SignatureExceptionHandler.valueOf("ResourceException");
|
||||
}
|
||||
} */
|
||||
|
||||
}
|
|
@ -0,0 +1,471 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_DOMAIN_ID;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_DOMAIN_NAME;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_HP_IDM_ROLES;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_IDENTITY_STATUS;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_PROJECT_DOMAIN_ID;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_PROJECT_DOMAIN_NAME;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_PROJECT_ID;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_PROJECT_NAME;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_ROLE;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_ROLES;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_SERVICE_CATALOG;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_TENANT;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_TENANT_NAME;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_USER;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_USER_DOMAIN_ID;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_USER_DOMAIN_NAME;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_USER_ID;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_TENANT_ID;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_USER_NAME;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.IdentityStatus;
|
||||
|
||||
/*import com.hp.csbu.cc.security.cs.thrift.service.AuthResponseV2;
|
||||
import com.hp.csbu.cc.security.cs.thrift.service.AuthResponseV3;
|
||||
import com.hp.csbu.cc.security.cs.thrift.service.EndpointV3;
|
||||
import com.hp.csbu.cc.security.cs.thrift.service.Role;
|
||||
import com.hp.csbu.cc.security.cs.thrift.service.ServiceForCatalogV3;
|
||||
import com.hp.csbu.cc.security.cs.thrift.service.V3Role;
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
//import net.rubyeye.xmemcached.exception.MemcachedException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonNull;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
|
||||
public class FilterUtils {
|
||||
|
||||
private FilterUtils() {
|
||||
}
|
||||
|
||||
private static final Config appConfig = Config.getInstance();
|
||||
|
||||
private static final Gson gson = new GsonBuilder()
|
||||
.excludeFieldsWithModifiers(Modifier.PRIVATE, Modifier.FINAL)
|
||||
.create();
|
||||
|
||||
// Thee faithful logger
|
||||
private static final Logger logger = LoggerFactory
|
||||
.getLogger(FilterUtils.class);
|
||||
|
||||
public static void destroyFilter() {
|
||||
/*MemcacheCrypt client = appConfig.getClient();
|
||||
// Shutdown memcache
|
||||
if (client != null) {
|
||||
try {
|
||||
client.shutdown();
|
||||
} catch (IOException e) {
|
||||
logger.warn("Failed to shutdown memcache", e);
|
||||
}
|
||||
} */
|
||||
|
||||
AuthClientFactory factory = appConfig.getFactory();
|
||||
// Shutdown factory
|
||||
if (factory != null) {
|
||||
factory.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
public static ServletRequest wrapRequestFromHttpResponse(
|
||||
ServletRequest req, String data) {
|
||||
if (appConfig.getAuthVersion().equalsIgnoreCase("v2.0")) {
|
||||
wrapRequestFromHttpV2Response(req, data);
|
||||
|
||||
} else {
|
||||
wrapRequestFromHttpV3Response(req, data);
|
||||
}
|
||||
return req;
|
||||
}
|
||||
|
||||
private static void wrapRequestFromHttpV3Response(ServletRequest req,
|
||||
String data) {
|
||||
StringBuilder tenants = new StringBuilder();
|
||||
StringBuilder nonTenants = new StringBuilder();
|
||||
JsonParser jp = new JsonParser();
|
||||
JsonObject token = jp.parse(data).getAsJsonObject().get("token")
|
||||
.getAsJsonObject();
|
||||
// Domain Scoped Token
|
||||
if (token.get("domain") != null) {
|
||||
JsonObject domain = token.get("domain").getAsJsonObject();
|
||||
req.setAttribute(AUTH_DOMAIN_ID, domain.get("id").getAsString());
|
||||
if (domain.get("name") != null) {
|
||||
req.setAttribute(AUTH_DOMAIN_NAME, domain.get("name")
|
||||
.getAsString());
|
||||
}
|
||||
}
|
||||
// Project Scoped Token
|
||||
if (token.get("project") != null) {
|
||||
JsonObject project = token.get("project").getAsJsonObject();
|
||||
req.setAttribute(AUTH_PROJECT_ID, project.get("id").getAsString());
|
||||
req.setAttribute(AUTH_PROJECT_NAME, project.get("name")
|
||||
.getAsString());
|
||||
|
||||
JsonObject projectDomain = project.get("domain").getAsJsonObject();
|
||||
// special case where the value of id is null and the
|
||||
// projectDomain.get("id") != null
|
||||
if (!projectDomain.get("id").equals(new JsonNull())) {
|
||||
req.setAttribute(AUTH_PROJECT_DOMAIN_ID, projectDomain
|
||||
.get("id").getAsString());
|
||||
}
|
||||
if (projectDomain.get("name") != null) {
|
||||
req.setAttribute(AUTH_PROJECT_DOMAIN_NAME,
|
||||
projectDomain.get("name"));
|
||||
}
|
||||
}
|
||||
// User info
|
||||
if (token.get("user") != null) {
|
||||
JsonObject user = token.get("user").getAsJsonObject();
|
||||
req.setAttribute(AUTH_USER_ID, user.get("id").getAsString());
|
||||
req.setAttribute(AUTH_USER_NAME, user.get("name").getAsString());
|
||||
|
||||
JsonObject userDomain = user.get("domain").getAsJsonObject();
|
||||
if (userDomain.get("id") != null) {
|
||||
req.setAttribute(AUTH_USER_DOMAIN_ID, userDomain.get("id")
|
||||
.getAsString());
|
||||
}
|
||||
if (userDomain.get("name") != null) {
|
||||
req.setAttribute(AUTH_USER_DOMAIN_NAME, userDomain.get("name")
|
||||
.getAsString());
|
||||
}
|
||||
|
||||
}
|
||||
// Roles
|
||||
JsonArray roles = token.getAsJsonArray("roles");
|
||||
if (roles != null) {
|
||||
Iterator<JsonElement> it = roles.iterator();
|
||||
while (it.hasNext()) {
|
||||
JsonObject role = it.next().getAsJsonObject();
|
||||
if (role.get("HP-IDM") != null) {
|
||||
JsonObject hpIdm = role.get("HP-IDM").getAsJsonObject();
|
||||
if (hpIdm.get("projectId") != null) {
|
||||
tenants.append(",");
|
||||
tenants.append(role.get("name").getAsString());
|
||||
} else {
|
||||
nonTenants.append(",");
|
||||
nonTenants.append(role.get("name").getAsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
String tenantRoles = (tenants.length() > 0) ? tenants.substring(1)
|
||||
: tenants.toString();
|
||||
String nonTenantRoles = (nonTenants.length() > 0) ? nonTenants
|
||||
.substring(1) : nonTenants.toString();
|
||||
if (!tenantRoles.equals("")) {
|
||||
req.setAttribute(AUTH_ROLES, tenantRoles);
|
||||
}
|
||||
if (!nonTenantRoles.equals("")) {
|
||||
req.setAttribute(AUTH_HP_IDM_ROLES, nonTenantRoles);
|
||||
}
|
||||
// Catalog
|
||||
if (token.get("catalog") != null && appConfig.isIncludeCatalog()) {
|
||||
JsonArray catalog = token.get("catalog").getAsJsonArray();
|
||||
req.setAttribute(AUTH_SERVICE_CATALOG, catalog.toString());
|
||||
}
|
||||
}
|
||||
|
||||
private static void wrapRequestFromHttpV2Response(ServletRequest req,
|
||||
String data) {
|
||||
StringBuilder tenants = new StringBuilder();
|
||||
StringBuilder nonTenants = new StringBuilder();
|
||||
JsonParser jp = new JsonParser();
|
||||
JsonObject access = jp.parse(data).getAsJsonObject().get("access")
|
||||
.getAsJsonObject();
|
||||
JsonObject token = access.get("token").getAsJsonObject();
|
||||
|
||||
// Tenant info
|
||||
if (token.get("tenant") != null) {
|
||||
JsonObject tenant = token.get("tenant").getAsJsonObject();
|
||||
|
||||
String id = tenant.get("id").getAsString();
|
||||
String name = tenant.get("name").getAsString();
|
||||
if (id != null)
|
||||
req.setAttribute(AUTH_TENANT_ID, id);
|
||||
if (name != null)
|
||||
req.setAttribute(AUTH_TENANT_NAME, name);
|
||||
}
|
||||
// User info
|
||||
if (access.get("user") != null) {
|
||||
JsonObject user = access.get("user").getAsJsonObject();
|
||||
|
||||
String userId = user.get("id").getAsString();
|
||||
String username = user.get("name").getAsString();
|
||||
if (userId != null)
|
||||
req.setAttribute(AUTH_USER_ID, userId);
|
||||
if (username != null)
|
||||
req.setAttribute(AUTH_USER_NAME, username);
|
||||
// Roles
|
||||
JsonArray roles = user.getAsJsonArray("roles");
|
||||
if (roles != null) {
|
||||
Iterator<JsonElement> it = roles.iterator();
|
||||
while (it.hasNext()) {
|
||||
JsonObject role = it.next().getAsJsonObject();
|
||||
if (role.get("tenantId") != null) {
|
||||
tenants.append(",");
|
||||
tenants.append(role.get("name").getAsString());
|
||||
} else {
|
||||
nonTenants.append(",");
|
||||
nonTenants.append(role.get("name").getAsString());
|
||||
}
|
||||
}
|
||||
}
|
||||
String tenantRoles = (tenants.length() > 0) ? tenants.substring(1)
|
||||
: tenants.toString();
|
||||
if (!tenantRoles.equals("")) {
|
||||
req.setAttribute(AUTH_ROLES, tenantRoles);
|
||||
}
|
||||
String nonTenantRoles = (nonTenants.length() > 0) ? nonTenants
|
||||
.substring(1) : nonTenants.toString();
|
||||
if (!nonTenantRoles.equals("")) {
|
||||
req.setAttribute(AUTH_HP_IDM_ROLES, nonTenantRoles);
|
||||
}
|
||||
}
|
||||
// Service catalog
|
||||
if (access.get("serviceCatalog") != null
|
||||
&& appConfig.isIncludeCatalog()) {
|
||||
JsonArray serviceCatalog = access.get("serviceCatalog")
|
||||
.getAsJsonArray();
|
||||
req.setAttribute(AUTH_SERVICE_CATALOG, serviceCatalog.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public static ServletRequest wrapRequest(ServletRequest req, Object data) {
|
||||
if (data == null) {
|
||||
req.setAttribute(AUTH_IDENTITY_STATUS,
|
||||
IdentityStatus.Invalid.toString());
|
||||
logger.debug("Failed Authentication. Setting identity status header to Invalid");
|
||||
}
|
||||
req.setAttribute(AUTH_IDENTITY_STATUS,
|
||||
IdentityStatus.Confirmed.toString());
|
||||
//if (data instanceof String) {
|
||||
wrapRequestFromHttpResponse(req, ((String) data));
|
||||
//} else {
|
||||
// wrapRequestFromThriftResponse(req, data);
|
||||
//}
|
||||
return req;
|
||||
}
|
||||
|
||||
/*private static void wrapRequestFromThriftResponse(ServletRequest req,
|
||||
Object data) {
|
||||
StringBuilder tenants = new StringBuilder();
|
||||
StringBuilder nonTenants = new StringBuilder();
|
||||
if (data instanceof AuthResponseV2) {
|
||||
AuthResponseV2 auth = (AuthResponseV2) data;
|
||||
req.setAttribute(AUTH_TENANT_ID, auth.userInfo.tenantId);
|
||||
req.setAttribute(AUTH_TENANT_NAME, auth.userInfo.tenantName);
|
||||
req.setAttribute(AUTH_USER_ID, auth.userInfo.userId);
|
||||
req.setAttribute(AUTH_USER_NAME, auth.userInfo.username);
|
||||
getRoles(auth.userInfo.roles, tenants, nonTenants);
|
||||
String tenantRoles = (tenants.length() > 0) ? tenants.substring(1)
|
||||
: tenants.toString();
|
||||
if (!tenantRoles.equals("")) {
|
||||
req.setAttribute(AUTH_ROLES, tenantRoles);
|
||||
}
|
||||
String nonTenantRoles = (nonTenants.length() > 0) ? nonTenants
|
||||
.substring(1) : nonTenants.toString();
|
||||
if (!nonTenantRoles.equals("")) {
|
||||
req.setAttribute(AUTH_HP_IDM_ROLES, nonTenantRoles);
|
||||
}
|
||||
if (auth.getServiceCatalog() != null) {
|
||||
req.setAttribute(AUTH_SERVICE_CATALOG,
|
||||
gson.toJson(auth.getServiceCatalog()));
|
||||
}
|
||||
|
||||
} else if (data instanceof AuthResponseV3) {
|
||||
AuthResponseV3 auth = (AuthResponseV3) data;
|
||||
if (auth.getToken().getDomain() != null) {
|
||||
req.setAttribute(AUTH_DOMAIN_ID, auth.getToken().getDomain()
|
||||
.getId());
|
||||
if (auth.getToken().getDomain().getName() != null) {
|
||||
req.setAttribute(AUTH_DOMAIN_NAME, auth.getToken()
|
||||
.getDomain().getName());
|
||||
}
|
||||
} else if (auth.getToken().getProject() != null) {
|
||||
req.setAttribute(AUTH_PROJECT_ID, auth.getToken().getProject()
|
||||
.getId());
|
||||
req.setAttribute(AUTH_PROJECT_NAME, auth.getToken()
|
||||
.getProject().getName());
|
||||
req.setAttribute(AUTH_PROJECT_DOMAIN_ID, auth.getToken()
|
||||
.getProject().getDomain().getId());
|
||||
if (auth.getToken().getProject().getDomain().getName() != null) {
|
||||
req.setAttribute(AUTH_PROJECT_DOMAIN_NAME, auth.getToken()
|
||||
.getProject().getDomain().getName());
|
||||
}
|
||||
}
|
||||
req.setAttribute(AUTH_USER_ID, auth.getToken().getUser()
|
||||
.getUserId());
|
||||
req.setAttribute(AUTH_USER_NAME, auth.getToken().getUser()
|
||||
.getUsername());
|
||||
req.setAttribute(AUTH_USER_DOMAIN_ID, auth.getToken().getUser()
|
||||
.getDomain().getId());
|
||||
if (auth.getToken().getUser().getDomain().getName() != null) {
|
||||
req.setAttribute(AUTH_USER_DOMAIN_NAME, auth.getToken()
|
||||
.getUser().getDomain().getName());
|
||||
}
|
||||
getRoles(auth.getToken().getRoles(), tenants, nonTenants);
|
||||
String tenantRoles = (tenants.length() > 0) ? tenants.substring(1)
|
||||
: tenants.toString();
|
||||
String nonTenantRoles = (nonTenants.length() > 0) ? nonTenants
|
||||
.substring(1) : nonTenants.toString();
|
||||
if (!tenantRoles.equals("")) {
|
||||
req.setAttribute(AUTH_ROLES, tenantRoles);
|
||||
}
|
||||
if (!nonTenantRoles.equals("")) {
|
||||
req.setAttribute(AUTH_HP_IDM_ROLES, nonTenantRoles);
|
||||
}
|
||||
if (auth.getToken().getCatalog() != null) {
|
||||
req.setAttribute(AUTH_SERVICE_CATALOG, gson
|
||||
.toJson(buildServiceCatalogV3(auth.getToken()
|
||||
.getCatalog())));
|
||||
}
|
||||
|
||||
setDeprecatedHeaders(req, auth, tenantRoles);
|
||||
}
|
||||
} */
|
||||
|
||||
/*private static List<CatalogV3> buildServiceCatalogV3(
|
||||
List<ServiceForCatalogV3> catalogs) {
|
||||
List<CatalogV3> v3Catalogs = new ArrayList<CatalogV3>();
|
||||
for (ServiceForCatalogV3 catalog : catalogs) {
|
||||
CatalogV3 catalogv3 = new CatalogV3();
|
||||
catalogv3.setId(catalog.getId());
|
||||
catalogv3.setType(catalog.getType());
|
||||
List<EndpointV3> endPoints = catalog.getEndpoints();
|
||||
List<Properties> endPointsv3 = new ArrayList<Properties>();
|
||||
for (EndpointV3 endPoint : endPoints) {
|
||||
Properties endPointv3 = new Properties();
|
||||
if (endPoint.getInterfaceName() != null) {
|
||||
endPointv3.put("interface", endPoint.getInterfaceName());
|
||||
}
|
||||
if (endPoint.getEndpointId() != null) {
|
||||
endPointv3.put("id", endPoint.getEndpointId());
|
||||
}
|
||||
if (endPoint.getServiceId() != null) {
|
||||
endPointv3.put("service_id", endPoint.getServiceId());
|
||||
}
|
||||
if (endPoint.getRegion() != null) {
|
||||
endPointv3.put("region", endPoint.getRegion());
|
||||
}
|
||||
if (endPoint.getUrl() != null) {
|
||||
endPointv3.put("url", endPoint.getUrl());
|
||||
}
|
||||
endPointsv3.add(endPointv3);
|
||||
}
|
||||
catalogv3.setEndPoints(endPointsv3);
|
||||
v3Catalogs.add(catalogv3);
|
||||
}
|
||||
return v3Catalogs;
|
||||
} */
|
||||
|
||||
// Method will be removed after keystone removes the deprecated headers.
|
||||
/*private static void setDeprecatedHeaders(ServletRequest req,
|
||||
AuthResponseV3 auth, String tenantRoles) {
|
||||
// Deprecated
|
||||
req.setAttribute(AUTH_USER, auth.getToken().getUser().getUsername());
|
||||
if (auth.getToken().getProject() != null) {
|
||||
req.setAttribute(AUTH_TENANT_ID, auth.getToken().getProject()
|
||||
.getId());
|
||||
req.setAttribute(AUTH_TENANT_NAME, auth.getToken().getProject()
|
||||
.getName());
|
||||
req.setAttribute(AUTH_TENANT, auth.getToken().getProject()
|
||||
.getName());
|
||||
}
|
||||
if (!tenantRoles.equals("")) {
|
||||
req.setAttribute(AUTH_ROLE, tenantRoles);
|
||||
}
|
||||
} */
|
||||
|
||||
// Insert token into cache
|
||||
public static void cacheToken(String token, Object auth) {
|
||||
if (isCaching()) {
|
||||
appConfig.getClient().put(token, auth);
|
||||
/*try {
|
||||
appConfig.getClient().putToken(token, auth);
|
||||
} catch (TimeoutException e) {
|
||||
logger.error("Error timeout setting memcache: " + token);
|
||||
} catch (InterruptedException e) {
|
||||
logger.error("Error memcache interrupted");
|
||||
} catch (MemcachedException e) {
|
||||
logger.error("Error memcache", e);
|
||||
} */
|
||||
}
|
||||
}
|
||||
|
||||
// Get token from cache
|
||||
public static Object getCachedToken(String token) {
|
||||
if (isCaching()) {
|
||||
long timeout = appConfig.getMemCacheTimeOut();
|
||||
|
||||
/*try {
|
||||
return appConfig.getClient().getToken(token, timeout);
|
||||
} catch (TimeoutException e) {
|
||||
logger.error("Error timeout getting from memcache: " + token);
|
||||
} catch (InterruptedException e) {
|
||||
logger.error("Error memcache interrupted");
|
||||
} catch (MemcachedException e) {
|
||||
logger.error("Error memcache", e);
|
||||
} */
|
||||
}
|
||||
return appConfig.getClient().getToken(token);
|
||||
}
|
||||
|
||||
public static void pause(long pauseTime) {
|
||||
try {
|
||||
Thread.currentThread().sleep(pauseTime);
|
||||
} catch (InterruptedException e) {
|
||||
logger.debug("Thread is interrupted while sleeping before "
|
||||
+ pauseTime + " seconds. ");
|
||||
}
|
||||
}
|
||||
|
||||
// Is caching enabled?
|
||||
private static boolean isCaching() {
|
||||
return appConfig.getClient() != null;
|
||||
}
|
||||
|
||||
/* private static void getRoles(Object obj, StringBuilder tenants,
|
||||
StringBuilder nonTenants) {
|
||||
if (appConfig.getAuthVersion().equalsIgnoreCase("v2.0")) {
|
||||
List<Role> roles = (List<Role>) obj;
|
||||
for (Role role : roles) {
|
||||
if (role.getTenantId() != null) {
|
||||
tenants.append(",");
|
||||
tenants.append(role.getName());
|
||||
} else {
|
||||
nonTenants.append(",");
|
||||
nonTenants.append(role.getName());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
List<V3Role> roles = (List<V3Role>) obj;
|
||||
for (V3Role role : roles) {
|
||||
if (role.getProjectId() != null) {
|
||||
tenants.append(",");
|
||||
tenants.append(role.getName());
|
||||
} else {
|
||||
nonTenants.append(",");
|
||||
nonTenants.append(role.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
} */
|
||||
}
|
|
@ -0,0 +1,236 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
import java.text.Format;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.TreeMap;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import com.hp.csbu.cc.security.cs.thrift.service.SigAuthRequest;
|
||||
import com.hp.csbu.cc.security.cs.thrift.service.SignatureCredentials;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.SIGNATURE_METHOD;
|
||||
|
||||
public class HPS3Signer implements Signer {
|
||||
|
||||
private final Set<String> subResources = new HashSet<String>() {
|
||||
{
|
||||
add("acl");
|
||||
add("logging");
|
||||
add("torrent");
|
||||
add("location");
|
||||
add("requestPayment");
|
||||
}
|
||||
};
|
||||
|
||||
public SigAuthRequest sign(ServletRequest req, String serviceIds,
|
||||
String endPointIds) {
|
||||
String accessKeyId = null;
|
||||
String signature = null;
|
||||
String dataToSign = null;
|
||||
if (req.getParameter("AWSAccessKeyId") != null) {
|
||||
if (hasRequestExpired(req)) {
|
||||
throw new SignatureBuilderException(
|
||||
"Either signature is expired or expiration field is missing");
|
||||
}
|
||||
req.setAttribute("Date", req.getParameter("Expires"));
|
||||
accessKeyId = req.getParameter("AWSAccessKeyId");
|
||||
signature = req.getParameter("Signature");
|
||||
} else {
|
||||
Date d = null;
|
||||
if (((HttpServletRequest) req).getHeader("X-Amz-Date") != null) {
|
||||
d = parseDate(((HttpServletRequest) req)
|
||||
.getHeader("X-Amz-Date"));
|
||||
} else if (((HttpServletRequest) req).getHeader("Date") != null) {
|
||||
d = parseDate(((HttpServletRequest) req).getHeader("Date"));
|
||||
} else {
|
||||
throw new SignatureBuilderException(
|
||||
"Either date is missing or an invalid date is provided");
|
||||
}
|
||||
if (hasClockSkew(d)) {
|
||||
throw new SignatureBuilderException(
|
||||
"Date is invalid. Date is skewed by more than 15 mins");
|
||||
}
|
||||
String authorizationStr = ((HttpServletRequest) req)
|
||||
.getHeader("Authorization");
|
||||
authorizationStr = authorizationStr.substring(
|
||||
authorizationStr.indexOf(" ")).trim();
|
||||
int colonDelimeter = authorizationStr.lastIndexOf(":");
|
||||
accessKeyId = authorizationStr.substring(0, colonDelimeter);
|
||||
signature = authorizationStr.substring(colonDelimeter + 1);
|
||||
}
|
||||
dataToSign = getCanonicalString(req);
|
||||
return getSignedRequest(dataToSign, accessKeyId, signature,
|
||||
SIGNATURE_METHOD, serviceIds, endPointIds);
|
||||
}
|
||||
|
||||
protected boolean hasClockSkew(Date d) {
|
||||
if (d == null) {
|
||||
// Invalid date
|
||||
return true;
|
||||
}
|
||||
Date currentDate = new Date();
|
||||
long currentTime = currentDate.getTime();
|
||||
long epochTime = getUnixEpochTime();
|
||||
long requestTime = d.getTime();
|
||||
long delta = TimeUnit.MILLISECONDS.convert(15L, TimeUnit.MINUTES);
|
||||
|
||||
if (requestTime < epochTime) {
|
||||
// Invalid date
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Math.abs(requestTime - currentTime) > delta) {
|
||||
// Invalid date
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected String getCanonicalString(ServletRequest req) {
|
||||
HttpServletRequest request = ((HttpServletRequest) req);
|
||||
StringBuffer canonicalStr = new StringBuffer();
|
||||
Map<String, String> amzHeaders = new TreeMap<String, String>();
|
||||
String contentMd5 = (request.getHeader("Content-MD5") == null) ? ""
|
||||
: request.getHeader("Content-MD5");
|
||||
String contentType = (request.getHeader("Content-Type") == null) ? ""
|
||||
: request.getHeader("Content-Type");
|
||||
String method = request.getMethod();
|
||||
canonicalStr.append(method).append("\n").append(contentMd5)
|
||||
.append("\n").append(contentType).append("\n");
|
||||
|
||||
Enumeration<String> headers = request.getHeaderNames();
|
||||
while (headers.hasMoreElements()) {
|
||||
String headerName = ((String) headers.nextElement()).toLowerCase();
|
||||
if (headerName.startsWith("x-amz-")) {
|
||||
Enumeration multiHeaderValues = request.getHeaders(headerName);
|
||||
StringBuffer headerValues = new StringBuffer();
|
||||
headerValues.append((String) multiHeaderValues.nextElement());
|
||||
while (multiHeaderValues.hasMoreElements()) {
|
||||
headerValues.append(",").append(
|
||||
multiHeaderValues.nextElement());
|
||||
}
|
||||
amzHeaders.put(headerName, headerValues.toString());
|
||||
}
|
||||
}
|
||||
if (amzHeaders.containsKey("X-Amz-Date")) {
|
||||
canonicalStr.append("\n");
|
||||
} else {
|
||||
String date = (request.getHeader("Date") != null) ? (String) request
|
||||
.getHeader("Date") : (String) request.getAttribute("Date");
|
||||
canonicalStr.append(date).append("\n");
|
||||
}
|
||||
|
||||
for (String key : amzHeaders.keySet()) {
|
||||
canonicalStr.append(key).append(":").append(amzHeaders.get(key))
|
||||
.append("\n");
|
||||
}
|
||||
String resource = getCanonicalResource(request);
|
||||
canonicalStr.append(resource);
|
||||
return canonicalStr.toString();
|
||||
}
|
||||
|
||||
protected String getCanonicalResource(HttpServletRequest request) {
|
||||
StringBuffer canonicalResource = new StringBuffer();
|
||||
canonicalResource.append(request.getRequestURI());
|
||||
String queryString = request.getQueryString();
|
||||
if (queryString != null) {
|
||||
canonicalResource.append(getCanonicalSubResource(queryString));
|
||||
}
|
||||
return canonicalResource.toString();
|
||||
}
|
||||
|
||||
protected String getCanonicalSubResource(String queryString) {
|
||||
String[] queryParams;
|
||||
if (queryString.contains("&")) {
|
||||
queryParams = queryString.split("&");
|
||||
} else {
|
||||
queryParams = new String[1];
|
||||
queryParams[0] = queryString;
|
||||
}
|
||||
for (String param : queryParams) {
|
||||
String paramName = param;
|
||||
if (paramName.contains("=")) {
|
||||
paramName = paramName.substring(0, paramName.indexOf("="));
|
||||
}
|
||||
if (subResources.contains(paramName)) {
|
||||
return "?" + paramName;
|
||||
}
|
||||
}
|
||||
return "";
|
||||
|
||||
}
|
||||
|
||||
protected long getUnixEpochTime() {
|
||||
Format formatter = new SimpleDateFormat("dd MMM yyyy HH:mm:ss z");
|
||||
Date date;
|
||||
try {
|
||||
date = (Date) formatter.parseObject("01 Jan 1970 00:00:00 UTC");
|
||||
} catch (ParseException e) {
|
||||
return 0;
|
||||
}
|
||||
return date.getTime();
|
||||
}
|
||||
|
||||
protected boolean hasRequestExpired(ServletRequest req) {
|
||||
if (req.getParameter("Expires") == null) {
|
||||
return true;
|
||||
}
|
||||
long expirationTime = new Long(req.getParameter("Expires"));
|
||||
return expirationTime < (System.currentTimeMillis()/1000);
|
||||
}
|
||||
|
||||
protected Date parseDate(String data) {
|
||||
/* Currently date is parsed in RFC 822 format */
|
||||
SimpleDateFormat df = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z");
|
||||
df.setTimeZone(new SimpleTimeZone(0, "UTC"));
|
||||
try {
|
||||
return df.parse(data);
|
||||
} catch (ParseException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
protected SigAuthRequest getSignedRequest(String dataToSign,
|
||||
String accessKeyId, String signature, String signatureMethod,
|
||||
String serviceIds, String endPointIds) {
|
||||
try {
|
||||
SignatureCredentials credentials = null;
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
String tenantId = null;
|
||||
String keyId = accessKeyId;
|
||||
|
||||
if (accessKeyId.contains(":")) {
|
||||
String[] strArr = accessKeyId.split(":");
|
||||
tenantId = strArr[0];
|
||||
keyId = strArr[1];
|
||||
}
|
||||
credentials = new SignatureCredentials(keyId, "accesskey",
|
||||
signatureMethod, dataToSign, signature);
|
||||
//If tenantId is null, you get an unscoped token.
|
||||
if (tenantId != null) {
|
||||
params.put("tenantId", tenantId);
|
||||
}
|
||||
if (serviceIds != null) {
|
||||
params.put("serviceIds", serviceIds);
|
||||
}
|
||||
if (endPointIds != null) {
|
||||
params.put("endPointTemplateIds", endPointIds);
|
||||
}
|
||||
return new SigAuthRequest(credentials, params);
|
||||
} catch (Exception e) {
|
||||
throw new SignatureBuilderException(
|
||||
"Exception building signature with given credentials");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,296 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.AUTH_SUBJECT_TOKEN;
|
||||
import static com.hp.csbu.cc.middleware.AuthConstants.TOKEN;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URI;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.client.methods.HttpPost;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
//import com.hp.csbu.cc.security.cs.thrift.service.AuthResponse;
|
||||
//import com.hp.csbu.cc.security.cs.thrift.service.SigAuthRequest;
|
||||
|
||||
public class HttpAuthClient implements AuthClient {
|
||||
private static final String ACCESSKEY = "accesskey";
|
||||
private static final String PASSWORD = "password";
|
||||
private static final String SERVICE_IDS_PARAM = "serviceIds";
|
||||
private static final String ENDPOINT_IDS_PARAM = "endpointIds";
|
||||
private static final int DELTA_TIME_IN_SEC = 30;
|
||||
private static SimpleDateFormat expiryFormat;
|
||||
static {
|
||||
expiryFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mmmmmm'Z'");
|
||||
expiryFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
}
|
||||
private final Config appConfig = Config.getInstance();
|
||||
|
||||
private HttpClient client;
|
||||
private String adminToken;
|
||||
private String adminTokenExpiry;
|
||||
private URI uri;
|
||||
|
||||
public HttpAuthClient(HttpClient client, URI uri) {
|
||||
this.client = client;
|
||||
this.uri = uri;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object validateTokenForServiceEndpointV2(String token,
|
||||
String serviceIds, String endpointIds, boolean includeCatalog)
|
||||
throws ClientProtocolException {
|
||||
String newUri = uri.toString() + "/v2.0/tokens/" + token;
|
||||
return verifyUUIDToken(token, newUri, null, serviceIds, endpointIds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object validateTokenForServiceEndpointV3(String token,
|
||||
Map<String, String> 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);
|
||||
int code = response.getStatusLine().getStatusCode();
|
||||
if (code == 404) {
|
||||
throw new AuthException("Authorization failed for token: " + token);
|
||||
}
|
||||
if (code != 200) {
|
||||
adminToken = null;
|
||||
throw new AuthException("Failed to validate via HTTP " + code
|
||||
+ " " +response.getStatusLine().getReasonPhrase());
|
||||
}
|
||||
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.getAdminAuthMethod().isEmpty()) {
|
||||
get.setHeader(new BasicHeader(TOKEN, getAdminToken()));
|
||||
}
|
||||
try {
|
||||
response = client.execute(get);
|
||||
} 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();
|
||||
}
|
||||
} 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());
|
||||
if (appConfig.getAdminProject() != null && !appConfig.getAdminProject().isEmpty()) {
|
||||
bfr.append("\"},\"scope\": { \"project\": { \"id\": \"");
|
||||
bfr.append(appConfig.getAdminProject());
|
||||
bfr.append("\"}}}}}}");
|
||||
} else {
|
||||
bfr.append("\"}}}}}");
|
||||
}
|
||||
} else if (appConfig.getAdminAuthMethod().equalsIgnoreCase(ACCESSKEY)) {
|
||||
bfr.append("{\"auth\": {\"identity\": {\"methods\": [\"accessKey\"], \"accessKey\": { \"accessKey\": \"");
|
||||
bfr.append(appConfig.getAdminAccessKey());
|
||||
bfr.append("\", \"secretKey\": \"");
|
||||
bfr.append(appConfig.getAdminSecretKey());
|
||||
if (appConfig.getAdminProject() != null && !appConfig.getAdminProject().isEmpty()) {
|
||||
bfr.append("\"},\"scope\": { \"project\": { \"id\": \"");
|
||||
bfr.append(appConfig.getAdminProject());
|
||||
bfr.append("\"}}}}}");
|
||||
} else {
|
||||
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() {
|
||||
}
|
||||
|
||||
/* @Override
|
||||
public AuthResponse validateSignature(SigAuthRequest request) {
|
||||
// TODO Auto-generated method stub
|
||||
return null;
|
||||
}*/
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package com.hp.csbu.cc.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();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
package com.hp.csbu.cc.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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package com.hp.csbu.cc.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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,283 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.SimpleTimeZone;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
|
||||
import net.rubyeye.xmemcached.MemcachedClient;
|
||||
import net.rubyeye.xmemcached.XMemcachedClientBuilder;
|
||||
import net.rubyeye.xmemcached.exception.MemcachedException;
|
||||
import net.rubyeye.xmemcached.utils.AddrUtil;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
//import com.hp.csbu.cc.security.cs.thrift.service.AuthResponseV2;
|
||||
//import com.hp.csbu.cc.security.cs.thrift.service.AuthResponseV3;
|
||||
|
||||
/**
|
||||
* An internal class to allow encryption and decryption of validated tokens
|
||||
* stored in memcache.
|
||||
*
|
||||
* @author liemmn
|
||||
*
|
||||
*/
|
||||
public class MemcacheCrypt {
|
||||
// GMT date format for expiration time stamp in token
|
||||
static SimpleDateFormat expiryFormat;
|
||||
static {
|
||||
expiryFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
Calendar cal = Calendar.getInstance(new SimpleTimeZone(0, "GMT"));
|
||||
expiryFormat.setCalendar(cal);
|
||||
}
|
||||
|
||||
// character set to use for converting between chars and bytes
|
||||
private static final String CHARSET_NAME = "UTF-8";
|
||||
|
||||
// message digest algorithm
|
||||
private static final String DIGEST_ALGORITHM = "SHA-256";
|
||||
|
||||
// key algorithm
|
||||
private static final String KEY_ALGORITHM = "AES";
|
||||
|
||||
// cipher algorithm
|
||||
private static final String CIPHER_ALGORITHM = KEY_ALGORITHM
|
||||
+ "/CBC/PKCS5Padding";
|
||||
|
||||
// Thee password
|
||||
private static final String PASSWORD = "G0n30ffTehC11ff!";
|
||||
|
||||
// Wrapped memcache client instance
|
||||
//private MemcachedClient client;
|
||||
private TokenCache client;
|
||||
|
||||
// Cache value to be encrypted or not
|
||||
private boolean isEncrypted;
|
||||
|
||||
// Thee faithful logger
|
||||
private static final Logger logger = LoggerFactory
|
||||
.getLogger(MemcacheCrypt.class);
|
||||
|
||||
/**
|
||||
* Construct a memcache client instance.
|
||||
*
|
||||
* @param cacheHosts
|
||||
* List of memcache servers
|
||||
* @param isEncrypted
|
||||
* Uses encryption or not
|
||||
* @throws IOException
|
||||
*/
|
||||
public MemcacheCrypt(String cacheHosts, boolean isEncrypted)
|
||||
throws IOException {
|
||||
XMemcachedClientBuilder builder = new XMemcachedClientBuilder(
|
||||
AddrUtil.getAddresses(cacheHosts));
|
||||
this.client = builder.build();
|
||||
this.isEncrypted = isEncrypted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shutdown this client instance.
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void shutdown() throws IOException {
|
||||
client.shutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Store given token into memcache.
|
||||
*
|
||||
* @param token
|
||||
* Token
|
||||
* @param auth
|
||||
* Token info
|
||||
* @throws TimeoutException
|
||||
* @throws InterruptedException
|
||||
* @throws MemcachedException
|
||||
*/
|
||||
public void putToken(String token, Object auth) throws TimeoutException,
|
||||
InterruptedException, MemcachedException {
|
||||
String expires = null;
|
||||
/* if (auth instanceof AuthResponseV2) {
|
||||
expires = ((AuthResponseV2) auth).getTokenInfo().getExpires();
|
||||
} else {
|
||||
expires = ((AuthResponseV3) auth).getToken().getExpires_at();
|
||||
} */
|
||||
if (isEncrypted) {
|
||||
auth = encrypt(token, PASSWORD, auth);
|
||||
}
|
||||
client.set("tokens/" + token, expireFromNow(expires), auth);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a token, or null if no token found in cache.
|
||||
*
|
||||
* @param token
|
||||
* Token
|
||||
* @param timeout
|
||||
* Timeout waiting to get token
|
||||
* @return Token info
|
||||
* @throws TimeoutException
|
||||
* @throws InterruptedException
|
||||
* @throws MemcachedException
|
||||
*/
|
||||
public Object getToken(String token, long timeout) throws TimeoutException,
|
||||
InterruptedException, MemcachedException {
|
||||
Object o = client.get("tokens/" + token, timeout);
|
||||
/*if (o instanceof AuthResponseV2) {
|
||||
return (AuthResponseV2) o;
|
||||
} else if (o instanceof AuthResponseV3) {
|
||||
return (AuthResponseV3) o;
|
||||
} else if (o instanceof byte[]) {
|
||||
return decrypt(token, PASSWORD, (byte[]) o);
|
||||
}
|
||||
*/
|
||||
if (o instanceof byte[]) {
|
||||
return decrypt(token, PASSWORD, (byte[]) o);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
// Test method... Don't use!
|
||||
void setEncrypted(boolean isEncrypted) {
|
||||
this.isEncrypted = isEncrypted;
|
||||
}
|
||||
|
||||
// Expiration from now in seconds
|
||||
private int expireFromNow(String expires) {
|
||||
Date tokenDate = null;
|
||||
try {
|
||||
tokenDate = expiryFormat.parse(expires);
|
||||
} catch (ParseException e) {
|
||||
logger.error("Error parsing token expiration: " + expires);
|
||||
}
|
||||
Date current = new Date();
|
||||
return (int) ((tokenDate.getTime() - current.getTime()) / 1000);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypts the given token information
|
||||
*
|
||||
* @param token
|
||||
* Token
|
||||
* @param password
|
||||
* Password used for encryption/decryption
|
||||
* @param auth
|
||||
* Token info to encrypt
|
||||
* @return Encrypted token info
|
||||
*/
|
||||
static byte[] encrypt(final String token, final String password,
|
||||
final Object tokenData) {
|
||||
byte[] encryptedAuth = null;
|
||||
ByteArrayOutputStream baos = null;
|
||||
|
||||
try {
|
||||
// Compute key and iv from token and password
|
||||
Secret secret = genSecret(token, password);
|
||||
|
||||
// Serialize the token info
|
||||
baos = new ByteArrayOutputStream();
|
||||
ObjectOutputStream os = new ObjectOutputStream(baos);
|
||||
/* if (tokenData instanceof AuthResponseV2) {
|
||||
os.writeObject((AuthResponseV2) tokenData);
|
||||
} else {
|
||||
os.writeObject((AuthResponseV3) tokenData);
|
||||
}*/
|
||||
|
||||
byte[] data = baos.toByteArray();
|
||||
|
||||
// Performs 128-AES encryption
|
||||
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
|
||||
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(secret.key,
|
||||
KEY_ALGORITHM), new IvParameterSpec(secret.iv));
|
||||
encryptedAuth = cipher.doFinal(data);
|
||||
} catch (Exception e) {
|
||||
throw new EncryptionException("Failed to encrypt " + token, e);
|
||||
} finally {
|
||||
if (baos != null)
|
||||
try {
|
||||
baos.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
return encryptedAuth;
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypts the given token info data.
|
||||
*
|
||||
* @param token
|
||||
* Token
|
||||
* @param password
|
||||
* Password used for encryption/decryption.
|
||||
* @param data
|
||||
* Token info data
|
||||
* @return Token info
|
||||
*/
|
||||
static Object decrypt(final String token, final String password,
|
||||
final byte[] data) {
|
||||
ByteArrayInputStream bais = null;
|
||||
Object auth = null;
|
||||
|
||||
try {
|
||||
// Compute key and iv from token and password
|
||||
Secret secret = genSecret(token, password);
|
||||
|
||||
// Performs 128-AES decryption
|
||||
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM);
|
||||
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(secret.key,
|
||||
KEY_ALGORITHM), new IvParameterSpec(secret.iv));
|
||||
byte[] decryptedAuth = cipher.doFinal(data);
|
||||
|
||||
// Deserialize the token info
|
||||
bais = new ByteArrayInputStream(decryptedAuth);
|
||||
ObjectInputStream ois = new ObjectInputStream(bais);
|
||||
auth = ois.readObject();
|
||||
bais.close();
|
||||
} catch (Exception e) {
|
||||
throw new DecryptionException("Failed to decrypt " + token, e);
|
||||
} finally {
|
||||
if (bais != null)
|
||||
try {
|
||||
bais.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
return auth;
|
||||
}
|
||||
|
||||
// Compute key and iv from token and password
|
||||
private static Secret genSecret(final String token, final String password)
|
||||
throws UnsupportedEncodingException, NoSuchAlgorithmException {
|
||||
MessageDigest md = MessageDigest.getInstance(DIGEST_ALGORITHM);
|
||||
byte[] seed = (token + password).getBytes(CHARSET_NAME);
|
||||
byte[] pw = md.digest(seed);
|
||||
Secret secret = new Secret();
|
||||
System.arraycopy(pw, 0, secret.key, 0, 16);
|
||||
System.arraycopy(pw, 16, secret.iv, 0, 16);
|
||||
Arrays.fill(pw, (byte) 0x00);
|
||||
return secret;
|
||||
}
|
||||
|
||||
// Data object to hold the key and iv for encryption/decryption
|
||||
private static final class Secret {
|
||||
byte[] key = new byte[16];
|
||||
byte[] iv = new byte[16];
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
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;
|
||||
|
||||
import com.hp.csbu.cc.middleware.AuthConstants.IdentityStatus;
|
||||
import com.hp.csbu.cc.security.cs.thrift.service.AuthResponse;
|
||||
import com.hp.csbu.cc.security.cs.thrift.service.SigAuthRequest;
|
||||
|
||||
public class S3SignatureAuth implements Filter, AuthConstants {
|
||||
|
||||
private final Config appConfig = Config.getInstance();
|
||||
private FilterConfig filterConfig;
|
||||
|
||||
// Thee faithful logger
|
||||
private static final Logger logger = LoggerFactory
|
||||
.getLogger(S3SignatureAuth.class);
|
||||
|
||||
private static final String SIGNATURE_NOT_FOUND = "Invalid Credentials: Token or Signature not found in the request";
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
FilterUtils.destroyFilter();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest req, ServletResponse resp,
|
||||
FilterChain chain) throws IOException, ServletException {
|
||||
AuthResponse auth = null;
|
||||
if (!appConfig.isInitialized()) {
|
||||
appConfig.initialize(filterConfig);
|
||||
}
|
||||
// Flow has reached here by setting DelayAuthDecision.
|
||||
// Check if the token validation has failed and then continue to
|
||||
// signatue validation.
|
||||
if (req.getAttribute(AUTH_IDENTITY_STATUS).equals(
|
||||
IdentityStatus.Invalid.toString())) {
|
||||
HPS3Signer s3Signer = new HPS3Signer();
|
||||
if (isS3Request(req)) {
|
||||
AuthClient client = null;
|
||||
try {
|
||||
SigAuthRequest signedRequest = s3Signer.sign(req,
|
||||
appConfig.getServiceIds(),
|
||||
appConfig.getEndpointIds());
|
||||
client = appConfig.getFactory().getClient();
|
||||
auth = client.validateSignature(signedRequest);
|
||||
|
||||
// Return to connection pool for re-use
|
||||
appConfig.getFactory().recycle(client);
|
||||
} catch (Exception ex) {
|
||||
if (client != null)
|
||||
appConfig.getFactory().discard(client);
|
||||
SignatureExceptionHandler handler = ExceptionHandlerUtil
|
||||
.lookUpSignatureException(ex);
|
||||
handler.onException(ex, resp);
|
||||
}
|
||||
} else {
|
||||
logger.error(HttpServletResponse.SC_UNAUTHORIZED
|
||||
+ SIGNATURE_NOT_FOUND);
|
||||
((HttpServletResponse) resp).sendError(
|
||||
HttpServletResponse.SC_UNAUTHORIZED,
|
||||
SIGNATURE_NOT_FOUND);
|
||||
}
|
||||
req = FilterUtils.wrapRequest(req, auth);
|
||||
}
|
||||
// Continue in the filter chain as DelayAuthDecision has been set.
|
||||
chain.doFilter(req, resp);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
this.filterConfig = filterConfig;
|
||||
}
|
||||
|
||||
private boolean isS3Request(ServletRequest req) {
|
||||
if (((HttpServletRequest) req).getHeader("Authorization") != null
|
||||
|| ((req.getParameter("AWSAccessKeyId")) != null && req
|
||||
.getParameter("Signature") != null)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package com.hp.csbu.cc.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);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
//import org.apache.thrift.TException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
//import com.hp.csbu.cc.security.cs.thrift.service.ResourceException;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
/*ResourceException {
|
||||
@Override
|
||||
public void onException(Exception e, ServletResponse resp) {
|
||||
// ResourceException re = (ResourceException) e;
|
||||
logger.error(HttpServletResponse.SC_UNAUTHORIZED
|
||||
+ " " + re);
|
||||
String statusText = re.getDetail();
|
||||
if (statusText == null || statusText.isEmpty()) {
|
||||
statusText = ExceptionHandlerUtil.getStatusText(HttpServletResponse.SC_UNAUTHORIZED);
|
||||
}
|
||||
try {
|
||||
((HttpServletResponse) resp).sendError(
|
||||
HttpServletResponse.SC_UNAUTHORIZED, statusText);
|
||||
} 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);
|
||||
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
public interface Signer {
|
||||
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.thrift.TException;
|
||||
|
||||
import com.hp.csbu.cc.security.cs.thrift.service.AuthResponse;
|
||||
//import com.hp.csbu.cc.security.cs.thrift.service.AuthResponseV2;
|
||||
//import com.hp.csbu.cc.security.cs.thrift.service.AuthResponseV3;
|
||||
import com.hp.csbu.cc.security.cs.thrift.service.CsThriftService.Client;
|
||||
import com.hp.csbu.cc.security.cs.thrift.service.ResourceException;
|
||||
import com.hp.csbu.cc.security.cs.thrift.service.SigAuthRequest;
|
||||
|
||||
/**
|
||||
* An AuthClient adapter for Thrift.
|
||||
*
|
||||
* @author liemmn
|
||||
*
|
||||
*/
|
||||
public class ThriftAuthClient implements AuthClient {
|
||||
private Client thrift;
|
||||
|
||||
public ThriftAuthClient(Client client) {
|
||||
this.thrift = client;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
thrift.getInputProtocol().getTransport().close();
|
||||
thrift.getOutputProtocol().getTransport().close();
|
||||
thrift = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthResponse validateSignature(SigAuthRequest request)
|
||||
throws ResourceException, TException {
|
||||
return thrift.validateSignature(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
/*public AuthResponseV2 validateTokenForServiceEndpointV2(String token,
|
||||
String serviceIds, String endpointIds, boolean includeCatalog)
|
||||
throws ResourceException, TException {
|
||||
return thrift.validateTokenForEndpointWithCatalog(token, null,
|
||||
serviceIds, endpointIds, includeCatalog);
|
||||
|
||||
} */
|
||||
public Object validateTokenForServiceEndpointV2(String token,
|
||||
String serviceIds, String endpointIds, boolean includeCatalog)
|
||||
throws ResourceException, TException {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
/*public AuthResponseV3 validateTokenForServiceEndpointV3(String token,
|
||||
Map<String, String> inputParams)
|
||||
throws ResourceException, TException {
|
||||
return thrift.validateTokenApiForEndpoint(token, inputParams);
|
||||
} */
|
||||
|
||||
public Object validateTokenForServiceEndpointV3(String token,
|
||||
Map<String, String> inputParams)
|
||||
throws ResourceException, TException {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
import org.apache.commons.pool.impl.GenericObjectPool;
|
||||
|
||||
/**
|
||||
* A Thrift factory.
|
||||
*
|
||||
* @author liemmn
|
||||
*
|
||||
*/
|
||||
public class ThriftClientFactory extends AuthClientFactory {
|
||||
|
||||
ThriftClientFactory(String host, int port,
|
||||
int timeout, boolean clientAuth, String keyStore, String keyPass,
|
||||
String trustStore, String trustPass) {
|
||||
pool = new GenericObjectPool(new ThriftClientPoolFactory(host, port,
|
||||
timeout, clientAuth, keyStore, keyPass, trustStore, trustPass));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
import org.apache.commons.pool.BasePoolableObjectFactory;
|
||||
import org.apache.thrift.protocol.TCompactProtocol;
|
||||
import org.apache.thrift.protocol.TProtocol;
|
||||
import org.apache.thrift.transport.TSSLTransportFactory;
|
||||
import org.apache.thrift.transport.TSocket;
|
||||
|
||||
import com.hp.csbu.cc.security.cs.thrift.service.CsThriftService;
|
||||
|
||||
/**
|
||||
* ThriftConnection pool factory. Based on Apache Commons Pool.
|
||||
*
|
||||
* @author liemmn
|
||||
*
|
||||
*/
|
||||
public class ThriftClientPoolFactory extends BasePoolableObjectFactory {
|
||||
private static final String PROTOCOL = "TLS";
|
||||
private static final String[] CIPHER_SUITES = new String[] {
|
||||
"TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
|
||||
"SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
"TLS_RSA_WITH_AES_128_CBC_SHA", "SSL_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||
"TLS_DHE_DSS_WITH_AES_128_CBC_SHA",
|
||||
"SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA" };
|
||||
|
||||
private String host;
|
||||
private int port;
|
||||
private int timeout;
|
||||
private boolean clientAuth;
|
||||
private String keyStore;
|
||||
private String keyPass;
|
||||
private String trustStore;
|
||||
private String trustPass;
|
||||
|
||||
|
||||
public ThriftClientPoolFactory(String host, int port, int timeout,
|
||||
boolean clientAuth, String keyStore, String keyPass,
|
||||
String trustStore, String trustPass) {
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.timeout = timeout;
|
||||
this.clientAuth = clientAuth;
|
||||
this.keyStore = keyStore;
|
||||
this.keyPass = keyPass;
|
||||
this.trustStore = trustStore;
|
||||
this.trustPass = trustPass;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AuthClient makeObject() {
|
||||
TSSLTransportFactory.TSSLTransportParameters params = new TSSLTransportFactory.TSSLTransportParameters(
|
||||
PROTOCOL, CIPHER_SUITES, clientAuth);
|
||||
params.setKeyStore(keyStore, keyPass);
|
||||
params.setTrustStore(trustStore, trustPass);
|
||||
|
||||
try {
|
||||
TSocket clientSocket = TSSLTransportFactory.getClientSocket(host,
|
||||
port, timeout, params);
|
||||
TProtocol proto = new TCompactProtocol(clientSocket);
|
||||
return new ThriftAuthClient(new CsThriftService.Client(proto));
|
||||
} catch (Exception e) {
|
||||
throw new AuthConnectionException("Failed to open socket " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroyObject(Object o) {
|
||||
((ThriftAuthClient) o).close();
|
||||
o = null;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,185 @@
|
|||
package com.hp.csbu.cc.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.apache.thrift.transport.TTransportException;
|
||||
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}.
|
||||
* <p>
|
||||
* A token is required to validate. However, if no token is presented, the
|
||||
* filter will set the {@link #AUTH_IDENTITY_STATUS} request parameter to
|
||||
* <code>Invalid</code> 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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);
|
||||
}
|
||||
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 {
|
||||
// Retrieve from cache
|
||||
auth = FilterUtils.getCachedToken(token);
|
||||
if (auth == null) {
|
||||
// Validate credential
|
||||
AuthClient client = null;
|
||||
do {
|
||||
try {
|
||||
client = factory.getClient();
|
||||
if (appConfig.getAuthVersion().equalsIgnoreCase("v2.0")) {
|
||||
auth = client.validateTokenForServiceEndpointV2(token, appConfig.getServiceIds(),
|
||||
appConfig.getEndpointIds(), appConfig.isIncludeCatalog());
|
||||
} else {
|
||||
auth = client.validateTokenForServiceEndpointV3(token, getInputParams());
|
||||
}
|
||||
// Cache token
|
||||
FilterUtils.cacheToken(token, auth);
|
||||
// Return to connection pool for re-use
|
||||
factory.recycle(client);
|
||||
logger.debug("Successful Authentication");
|
||||
break;
|
||||
} catch (TTransportException t) {
|
||||
if (client != null)
|
||||
factory.discard(client);
|
||||
if (numberOfTries < retries) {
|
||||
FilterUtils.pause(pauseTime);
|
||||
logger.debug("Retrying connection after "
|
||||
+ pauseTime + " seconds.");
|
||||
numberOfTries++;
|
||||
continue;
|
||||
|
||||
} else {
|
||||
TokenExceptionHandler handler = TokenExceptionHandler
|
||||
.valueOf("TException");
|
||||
handler.onException(t, resp, token);
|
||||
}
|
||||
return;
|
||||
} catch (ClientProtocolException c) {
|
||||
if (client != null)
|
||||
factory.discard(client);
|
||||
if (numberOfTries < retries) {
|
||||
FilterUtils.pause(pauseTime);
|
||||
logger.debug("Retrying connection after "
|
||||
+ pauseTime + " seconds.");
|
||||
numberOfTries++;
|
||||
continue;
|
||||
|
||||
} else {
|
||||
TokenExceptionHandler handler = TokenExceptionHandler
|
||||
.valueOf("ClientProtocolException");
|
||||
handler.onException(c, resp, token);
|
||||
}
|
||||
return;
|
||||
}catch (Exception ex) {
|
||||
if (client != null)
|
||||
factory.recycle(client);
|
||||
TokenExceptionHandler handler = ExceptionHandlerUtil
|
||||
.lookUpTokenException(ex);
|
||||
handler.onException(ex, resp, token);
|
||||
return;
|
||||
}
|
||||
} while (numberOfTries <= retries);
|
||||
} else {
|
||||
// Got a cached token!
|
||||
logger.debug("Got cached token: " + token);
|
||||
}
|
||||
}
|
||||
req = FilterUtils.wrapRequest(req, auth);
|
||||
logger.debug("TokenAuth: Forwarding down stream to next filter/servlet");
|
||||
// Forward downstream...
|
||||
chain.doFilter(req, resp);
|
||||
}
|
||||
|
||||
private Map<String, String> getInputParams() {
|
||||
Map<String, String> inputParams = new HashMap<String, String>();
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package com.hp.csbu.cc.middleware;
|
||||
|
||||
import org.apache.commons.collections4.map.PassiveExpiringMap;
|
||||
/**
|
||||
* Created by johnderr on 6/9/14.
|
||||
*/
|
||||
public class TokenCache<K,V> {
|
||||
private PassiveExpiringMap<K,V> map;
|
||||
|
||||
public TokenCache(Long timeToExpire) {
|
||||
map = new PassiveExpiringMap<>(timeToExpire);
|
||||
}
|
||||
|
||||
public V getToken(K key) {
|
||||
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
public void put(K key, V value) {
|
||||
map.put(key,value);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package com.hp.csbu.cc.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;
|
||||
//import com.hp.csbu.cc.security.cs.thrift.service.ResourceException;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
},
|
||||
/*ResourceException {
|
||||
@Override
|
||||
public void onException(Exception e, ServletResponse resp, String token) {
|
||||
ResourceException re = (ResourceException) e;
|
||||
logger.error(HttpServletResponse.SC_UNAUTHORIZED + " " + token
|
||||
+ " " + re);
|
||||
String statusText = re.getDetail();
|
||||
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);
|
||||
}
|
||||
}
|
||||
},*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
final Logger logger = LoggerFactory.getLogger(TokenExceptionHandler.class);
|
||||
abstract void onException(Exception e, ServletResponse resp, String token);
|
||||
}
|
|
@ -34,7 +34,7 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import com.hpcloud.mon.resource.exception.Exceptions;
|
||||
import com.hpcloud.mon.resource.exception.Exceptions.FaultType;
|
||||
import com.hp.csbu.cc.middleware.ExceptionHandler.*;
|
||||
//import com.hp.csbu.cc.middleware.ExceptionHandler.*;
|
||||
|
||||
/**
|
||||
* Authenticates requests using header information from the CsMiddleware. Provides the X-TENANT-ID
|
||||
|
|
Loading…
Reference in New Issue