Always use adminAuthMethod value

Previously, it would use token authentication if adminToken was set
regardless of the value of adminAuthMethod

Also, remove authentication using Keystone v2 since it will be
deprecated shortly

Remove special HP handling for endpoints and services since it
isn't required anymore

Simplify the code by getting rid of some unneeded generics

Closes-Bug: 1403175

Change-Id: I27e563d68e5266703111f82ab032dc13131f1304
This commit is contained in:
Craig Bryant 2015-02-17 16:02:33 -07:00
parent 6c1fd1911c
commit b27d5db96c
6 changed files with 61 additions and 280 deletions

View File

@ -1,8 +1,6 @@
package monasca.common.middleware;
import java.util.Map;
import org.apache.http.client.ClientProtocolException;
import org.apache.thrift.TException;
@ -12,12 +10,6 @@ import org.apache.thrift.TException;
* @author liemmn
*/
public interface AuthClient {
public Object validateTokenForServiceEndpointV2(String token,
String serviceIds, String endpointIds, boolean includeCatalog)
throws TException, ClientProtocolException;
public Object validateTokenForServiceEndpointV3(String token,
Map<String, String> inputParams) throws TException, ClientProtocolException;
public String validateTokenForServiceEndpointV3(String token) throws TException, ClientProtocolException;
}

View File

@ -8,8 +8,6 @@ import javax.servlet.ServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
public class Config implements AuthConstants {
// Thee faithful logger
@ -18,23 +16,17 @@ public class Config implements AuthConstants {
private static final Config instance = new Config();
private static final String PASSWORD = "password";
private static final String ACCESS_KEY = "accesskey";
public static final String TOKEN = "token";
public static final String PASSWORD = "password";
// Application wide init param -- ServletContext
private ServletContext context = null;
private TokenCache<String, String> client = null;
private TokenCache 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;
//the time to cache token
private long timeToCacheToken;
@ -45,9 +37,6 @@ public class Config implements AuthConstants {
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;
@ -70,16 +59,11 @@ public class Config implements AuthConstants {
return instance;
}
public synchronized void initialize(FilterConfig config, ServletRequest req, Map<String, String> map) throws ServletException {
public synchronized void initialize(FilterConfig config, ServletRequest req) throws ServletException {
this.context = config.getServletContext();
this.filterConfig = config;
try {
// Initialize serviceIds...
serviceIds = filterConfig.getInitParameter(SERVICE_IDS);
// Initialize endpointIds...
endpointIds = filterConfig.getInitParameter(ENDPOINT_IDS);
// Initialize auth server connection parameters...
@ -87,16 +71,6 @@ public class Config implements AuthConstants {
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 Certificates
String keyStore = filterConfig.getInitParameter(KEYSTORE);
@ -126,7 +100,7 @@ public class Config implements AuthConstants {
maxActive, maxIdle, evictPeriod, minIdleTime, adminToken);
verifyRequiredParamsForAuthMethod();
this.client = new TokenCache<>(maxTokenCacheSize, timeToCacheToken, map);
this.client = new TokenCache(maxTokenCacheSize, timeToCacheToken);
logger.info("Using https {}", useHttps);
if (useHttps) {
logger.info("Auth host (2-way SSL: " + clientAuth + "): " + host);
@ -142,6 +116,10 @@ public class Config implements AuthConstants {
}
}
private boolean isEmpty(final String value) {
return value == null || value.isEmpty();
}
public boolean isInitialized() {
return initialized;
}
@ -195,16 +173,11 @@ public class Config implements AuthConstants {
return includeCatalog;
}
protected String getAuthVersion() {
return authVersion;
}
protected ServletContext getConfig() {
return context;
}
protected TokenCache<String, String> getClient() {
protected TokenCache getClient() {
return client;
}
@ -212,14 +185,6 @@ public class Config implements AuthConstants {
return factory;
}
protected String getServiceIds() {
return serviceIds;
}
protected String getEndpointIds() {
return endpointIds;
}
protected boolean isDelayAuthDecision() {
return delayAuthDecision;
}
@ -240,15 +205,16 @@ public class Config implements AuthConstants {
this.timeToCacheToken = timeToCachedToken;
}
public void setClient(TokenCache<String, String> client) {
public void setClient(TokenCache client) {
this.client = client;
}
@SuppressWarnings("unchecked")
private <T> T getValue(String paramName, T defaultValue) {
Class<?> type = defaultValue.getClass();
String initparamValue = filterConfig.getInitParameter(paramName);
if (initparamValue != null && !initparamValue.isEmpty()) {
if (!isEmpty(initparamValue)) {
if (type.equals(Integer.class)) {
int paramValue = Integer.parseInt(initparamValue);
return (T) type.cast(paramValue);
@ -266,20 +232,20 @@ public class Config implements AuthConstants {
}
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 AdminAuthException(msg);
if (isEmpty(getAdminAuthMethod()) || getAdminAuthMethod().equalsIgnoreCase(TOKEN)) {
if (isEmpty(getAdminToken())) {
throw new AdminAuthException(String.format(
"adminToken must be set if adminAuthMethod is %s.", TOKEN));
}
} 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 AdminAuthException(msg);
} else if (getAdminAuthMethod().equalsIgnoreCase(PASSWORD)) {
if (isEmpty(getAdminUser()) || isEmpty(getAdminPassword())) {
throw new AdminAuthException(String.format(
"adminUser and adminPassword must be set if adminAuthMethod is %s.", PASSWORD));
}
} else {
throw new AdminAuthException(String.format(
"Unrecognized value '%s' for adminAuthMethod. Valid values are %s or %s",
getAdminAuthMethod(), TOKEN, PASSWORD));
}
}
}

View File

@ -4,14 +4,12 @@ package monasca.common.middleware;
import static monasca.common.middleware.AuthConstants.AUTH_IDENTITY_STATUS;
import static monasca.common.middleware.AuthConstants.AUTH_ROLES;
import static monasca.common.middleware.AuthConstants.AUTH_TENANT_NAME;
import static monasca.common.middleware.AuthConstants.AUTH_USER_ID;
import static monasca.common.middleware.AuthConstants.AUTH_DOMAIN_ID;
import static monasca.common.middleware.AuthConstants.AUTH_DOMAIN_NAME;
import static monasca.common.middleware.AuthConstants.AUTH_PROJECT_ID;
import static monasca.common.middleware.AuthConstants.AUTH_PROJECT_NAME;
import static monasca.common.middleware.AuthConstants.AUTH_TENANT_ID;
import static monasca.common.middleware.AuthConstants.AUTH_USER_NAME;
import static monasca.common.middleware.AuthConstants.IdentityStatus;
import static monasca.common.middleware.AuthConstants.AUTH_PROJECT_DOMAIN_ID;
@ -22,15 +20,12 @@ import static monasca.common.middleware.AuthConstants.AUTH_HP_IDM_ROLES;
import static monasca.common.middleware.AuthConstants.AUTH_SERVICE_CATALOG;
import java.io.IOException;
import java.lang.reflect.Modifier;
import java.util.Iterator;
import javax.servlet.ServletRequest;
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;
@ -44,17 +39,13 @@ public class 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() {
TokenCache<String, String> client = appConfig.getClient();
TokenCache client = appConfig.getClient();
if (client != null)
appConfig.setClient(null);
@ -68,12 +59,7 @@ public class FilterUtils {
public static ServletRequest wrapRequestFromHttpResponse(
ServletRequest req, String data) {
if (appConfig.getAuthVersion().equalsIgnoreCase("v2.0")) {
wrapRequestFromHttpV2Response(req, data);
} else {
wrapRequestFromHttpV3Response(req, data);
}
wrapRequestFromHttpV3Response(req, data);
return req;
}
@ -103,7 +89,7 @@ public class FilterUtils {
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())) {
if (!projectDomain.get("id").equals(JsonNull.INSTANCE)) {
req.setAttribute(AUTH_PROJECT_DOMAIN_ID, projectDomain
.get("id").getAsString());
}
@ -161,71 +147,6 @@ public class FilterUtils {
}
}
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,
@ -252,7 +173,7 @@ public class FilterUtils {
public static void pause(long pauseTime) {
try {
Thread.currentThread().sleep(pauseTime);
Thread.sleep(pauseTime);
} catch (InterruptedException e) {
logger.debug("Thread is interrupted while sleeping before "
+ pauseTime + " seconds. ");

View File

@ -13,7 +13,6 @@ 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;
@ -36,9 +35,6 @@ import com.google.gson.JsonPrimitive;
public class HttpAuthClient implements AuthClient {
private static final Logger logger = LoggerFactory.getLogger(HttpAuthClient.class);
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 {
@ -58,32 +54,17 @@ public class HttpAuthClient implements AuthClient {
}
@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 {
public String validateTokenForServiceEndpointV3(String token) 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);
return verifyUUIDToken(token, newUri, header);
}
private Object verifyUUIDToken(String token, String newUri,
Header[] header, String serviceIds, String endpointIds)
private String verifyUUIDToken(String token, String newUri,
Header[] header)
throws ClientProtocolException {
HttpResponse response = sendGet(newUri, header, serviceIds, endpointIds);
HttpResponse response = sendGet(newUri, header);
HttpEntity entity = response.getEntity();
int code = response.getStatusLine().getStatusCode();
@ -146,20 +127,10 @@ public class HttpAuthClient implements AuthClient {
return response;
}
private HttpResponse sendGet(String newUri, Header[] headers,
String serviceIds, String endpointIds)
private HttpResponse sendGet(String newUri, Header[] headers)
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");
@ -170,12 +141,12 @@ public class HttpAuthClient implements AuthClient {
}
}
if(!appConfig.getAdminToken().isEmpty()) {
get.setHeader(new BasicHeader(TOKEN, appConfig.getAdminToken()));
}
else if (!appConfig.getAdminAuthMethod().isEmpty()) {
get.setHeader(new BasicHeader(TOKEN, getAdminToken()));
}
if (appConfig.getAdminAuthMethod().equalsIgnoreCase(Config.TOKEN)) {
get.setHeader(new BasicHeader(TOKEN, appConfig.getAdminToken()));
}
else {
get.setHeader(new BasicHeader(TOKEN, getAdminToken()));
}
try {
response = client.execute(get);
@ -229,58 +200,17 @@ public class HttpAuthClient implements AuthClient {
}
}
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();
}
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 AdminAuthException("Invalid V2 authentication request "
+ e);
}
} else {
String msg = String.format("Admin auth method %s not supported",appConfig.getAdminAuthMethod());
throw new AdminAuthException(msg);
}
}
private String buildAuth(final String userName, final String password) {
final JsonObject domain = new JsonObject();
domain.addProperty("id", "default");
@ -304,7 +234,7 @@ public class HttpAuthClient implements AuthClient {
private StringEntity getUnscopedV3AdminTokenRequest() {
final String body;
if (appConfig.getAdminAuthMethod().equalsIgnoreCase(PASSWORD)) {
if (appConfig.getAdminAuthMethod().equalsIgnoreCase(Config.PASSWORD)) {
body = buildAuth(appConfig.getAdminUser(), appConfig.getAdminPassword());
} else {
String msg = String.format("Admin auth method %s not supported",appConfig.getAdminAuthMethod());

View File

@ -1,8 +1,6 @@
package monasca.common.middleware;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
@ -41,10 +39,6 @@ import org.slf4j.LoggerFactory;
public class TokenAuth implements Filter, monasca.common.middleware.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 monasca.common.middleware.Config appConfig = Config.getInstance();
@ -80,7 +74,7 @@ public class TokenAuth implements Filter, monasca.common.middleware.AuthConstant
Object auth = null;
int numberOfTries = 0;
if (!appConfig.isInitialized()) {
appConfig.initialize(filterConfig, req, getInputParams());
appConfig.initialize(filterConfig, req);
}
int retries = appConfig.getRetries();
long pauseTime = appConfig.getPauseTime();
@ -157,19 +151,4 @@ public class TokenAuth implements Filter, monasca.common.middleware.AuthConstant
// 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;
}
}

View File

@ -6,40 +6,33 @@ import org.apache.thrift.TException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
public class TokenCache<K, V> {
public class TokenCache {
private final LoadingCache<K, V> cache;
private final LoadingCache<String, String> cache;
private final Config appConfig = Config.getInstance();
private AuthClientFactory factory;
private AuthClient client;
private static final Logger logger = LoggerFactory
.getLogger(TokenCache.class);
public TokenCache(final long maxSize, final long timeToExpire, final Map<String, String> map) {
public TokenCache(final long maxSize, final long timeToExpire) {
factory = appConfig.getFactory();
cache = CacheBuilder.newBuilder().maximumSize(maxSize)
.expireAfterWrite(timeToExpire, TimeUnit.SECONDS)
.build(new CacheLoader<K, V>() {
public V load(K key) throws TException, ClientProtocolException {
.build(new CacheLoader<String, String>() {
public String load(String key) throws TException, ClientProtocolException {
V value = null;
String value = null;
AuthClient client = null;
try {
client = factory.getClient();
if (appConfig.getAuthVersion().equals("v2.0")) {
value = (V) client.validateTokenForServiceEndpointV2((String) key, appConfig.getServiceIds(),
appConfig.getEndpointIds(), appConfig.isIncludeCatalog());
} else {
value = (V) client.validateTokenForServiceEndpointV3((String) key, map);
}
value = client.validateTokenForServiceEndpointV3(key);
} finally {
if (client != null)
factory.recycle(client);
@ -49,8 +42,8 @@ public class TokenCache<K, V> {
});
}
public V getToken(K key) throws ClientProtocolException {
V value = null;
public String getToken(String key) throws ClientProtocolException {
String value = null;
try {
value = cache.get(key);
} catch (ExecutionException e) {
@ -60,7 +53,7 @@ public class TokenCache<K, V> {
return value;
}
public void put(K key, V value) {
public void put(String key, String value) {
cache.put(key, value);
}