You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by sm...@apache.org on 2015/08/17 06:09:05 UTC
[03/10] airavata git commit: adding XACML based authorization for API
calls.
adding XACML based authorization for API calls.
Project: http://git-wip-us.apache.org/repos/asf/airavata/repo
Commit: http://git-wip-us.apache.org/repos/asf/airavata/commit/9c02f24d
Tree: http://git-wip-us.apache.org/repos/asf/airavata/tree/9c02f24d
Diff: http://git-wip-us.apache.org/repos/asf/airavata/diff/9c02f24d
Branch: refs/heads/master
Commit: 9c02f24d99c139b7dcc38b6fcddd17dd935c8e73
Parents: 7ef8368
Author: hasinitg <ha...@gmail.com>
Authored: Sat Aug 1 01:19:34 2015 +0530
Committer: hasinitg <ha...@gmail.com>
Committed: Sat Aug 1 01:19:34 2015 +0530
----------------------------------------------------------------------
airavata-api/airavata-api-server/pom.xml | 8 +-
.../security/AiravataSecurityManager.java | 4 +-
.../DefaultAiravataSecurityManager.java | 21 ++++-
.../api/server/security/DefaultOAuthClient.java | 55 +++---------
.../api/server/security/DefaultXACMLPEP.java | 92 ++++++++++++++++++++
.../server/security/SecurityInterceptor.java | 17 +++-
.../apache/airavata/common/utils/Constants.java | 6 ++
.../resources/airavata-default-xacml-policy.xml | 62 +++++++++++++
8 files changed, 211 insertions(+), 54 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c02f24d/airavata-api/airavata-api-server/pom.xml
----------------------------------------------------------------------
diff --git a/airavata-api/airavata-api-server/pom.xml b/airavata-api/airavata-api-server/pom.xml
index 7cd0f3b..543bbaa 100644
--- a/airavata-api/airavata-api-server/pom.xml
+++ b/airavata-api/airavata-api-server/pom.xml
@@ -8,7 +8,8 @@
ANY ~ KIND, either express or implied. See the License for the specific language governing permissions and limitations under
the License. -->
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
@@ -107,6 +108,11 @@
<version>4.2.0</version>
</dependency>
<dependency>
+ <groupId>org.wso2.carbon</groupId>
+ <artifactId>org.wso2.carbon.identity.entitlement.stub</artifactId>
+ <version>4.2.1</version>
+ </dependency>
+ <dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>4.0</version>
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c02f24d/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/AiravataSecurityManager.java
----------------------------------------------------------------------
diff --git a/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/AiravataSecurityManager.java b/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/AiravataSecurityManager.java
index 348675f..37c348c 100644
--- a/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/AiravataSecurityManager.java
+++ b/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/AiravataSecurityManager.java
@@ -23,6 +23,8 @@ package org.apache.airavata.api.server.security;
import org.apache.airavata.model.security.AuthzToken;
import org.apache.airavata.security.AiravataSecurityException;
+import java.util.Map;
+
public interface AiravataSecurityManager {
- public boolean isUserAuthorized(AuthzToken authzToken) throws AiravataSecurityException;
+ public boolean isUserAuthorized(AuthzToken authzToken, Map<String, String> metaData) throws AiravataSecurityException;
}
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c02f24d/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/DefaultAiravataSecurityManager.java
----------------------------------------------------------------------
diff --git a/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/DefaultAiravataSecurityManager.java b/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/DefaultAiravataSecurityManager.java
index 9d7c959..6230310 100644
--- a/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/DefaultAiravataSecurityManager.java
+++ b/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/DefaultAiravataSecurityManager.java
@@ -24,6 +24,7 @@ import org.apache.airavata.common.exception.ApplicationSettingsException;
import org.apache.airavata.common.utils.ServerSettings;
import org.apache.airavata.model.security.AuthzToken;
import org.apache.airavata.security.AiravataSecurityException;
+import org.apache.airavata.security.util.TrustStoreManager;
import org.apache.axis2.AxisFault;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.ConfigurationContextFactory;
@@ -31,22 +32,36 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.wso2.carbon.identity.oauth2.stub.dto.OAuth2TokenValidationResponseDTO;
+import java.util.Map;
+
/**
* This enforces authentication and authorization on Airavata API calls.
*/
public class DefaultAiravataSecurityManager implements AiravataSecurityManager {
private final static Logger logger = LoggerFactory.getLogger(DefaultAiravataSecurityManager.class);
- public boolean isUserAuthorized(AuthzToken authzToken) throws AiravataSecurityException {
+ public boolean isUserAuthorized(AuthzToken authzToken, Map<String, String> metaData) throws AiravataSecurityException {
try {
ConfigurationContext configContext =
ConfigurationContextFactory.createConfigurationContextFromFileSystem(null, null);
- //TODO:read following properties from server-settings.properties file.
+
+ //initialize SSL context with the trust store that contains the public cert of WSO2 Identity Server.
+ TrustStoreManager trustStoreManager = new TrustStoreManager();
+ trustStoreManager.initializeTrustStoreManager(ServerSettings.getTrustStorePath(),
+ ServerSettings.getTrustStorePassword());
+
DefaultOAuthClient oauthClient = new DefaultOAuthClient(ServerSettings.getRemoteOauthServerUrl(),
ServerSettings.getAdminUsername(), ServerSettings.getAdminPassword(), configContext);
OAuth2TokenValidationResponseDTO validationResponse = oauthClient.validateAccessToken(
authzToken.getAccessToken());
- return validationResponse.getValid();
+ boolean isOAuthTokenValid = validationResponse.getValid();
+ //if XACML based authorization is enabled, check for role based authorization for the API invocation
+ DefaultXACMLPEP entitlementClient = new DefaultXACMLPEP(ServerSettings.getRemoteOauthServerUrl(),
+ ServerSettings.getAdminUsername(), ServerSettings.getAdminPassword(), configContext);
+ boolean authorizationDecision = entitlementClient.getAuthorizationDecision(authzToken, metaData);
+
+ return (isOAuthTokenValid && authorizationDecision);
+
} catch (AxisFault axisFault) {
logger.error(axisFault.getMessage(), axisFault);
throw new AiravataSecurityException("Error in initializing the configuration context for creating the OAuth validation client.");
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c02f24d/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/DefaultOAuthClient.java
----------------------------------------------------------------------
diff --git a/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/DefaultOAuthClient.java b/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/DefaultOAuthClient.java
index 7996474..e1afacd 100644
--- a/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/DefaultOAuthClient.java
+++ b/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/DefaultOAuthClient.java
@@ -58,47 +58,14 @@ public class DefaultOAuthClient {
*/
public DefaultOAuthClient(String auhorizationServerURL, String username, String password,
ConfigurationContext configCtx) throws AiravataSecurityException {
- String serviceURL = auhorizationServerURL + "OAuth2TokenValidationService";
try {
+ String serviceURL = auhorizationServerURL + "OAuth2TokenValidationService";
stub = new OAuth2TokenValidationServiceStub(configCtx, serviceURL);
CarbonUtils.setBasicAccessSecurityHeaders(username, password, true, stub._getServiceClient());
} catch (AxisFault e) {
logger.error(e.getMessage(), e);
throw new AiravataSecurityException("Error initializing OAuth client.");
}
- /*//TODO:Import the WSO2 IS cert into Airavata trust store.
- try {
- // Get SSL context
- SSLContext sc = SSLContext.getInstance("SSL");
-
- // Create empty HostnameVerifier
- HostnameVerifier hv = new HostnameVerifier() {
- public boolean verify(String urlHostName, SSLSession session) {
- return true;
- }
- };
- HttpsURLConnection.setDefaultHostnameVerifier(hv);
-
- // Create a trust manager that does not validate certificate chains
- TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
- public java.security.cert.X509Certificate[] getAcceptedIssuers() {
- return null;
- }
-
- public void checkClientTrusted(java.security.cert.X509Certificate[] certs,
- String authType) {
- }
-
- public void checkServerTrusted(java.security.cert.X509Certificate[] certs,
- String authType) {
- }
- }};
-
- sc.init(null, trustAllCerts, new java.security.SecureRandom());
- SSLContext.setDefault(sc);
- } catch (Exception e) {
- e.printStackTrace();
- }*/
}
/**
@@ -110,24 +77,22 @@ public class DefaultOAuthClient {
*/
public OAuth2TokenValidationResponseDTO validateAccessToken(String accessToken)
throws AiravataSecurityException {
- OAuth2TokenValidationRequestDTO oauthReq = new OAuth2TokenValidationRequestDTO();
- OAuth2TokenValidationRequestDTO_OAuth2AccessToken token =
- new OAuth2TokenValidationRequestDTO_OAuth2AccessToken();
- token.setIdentifier(accessToken);
- token.setTokenType(BEARER_TOKEN_TYPE);
- oauthReq.setAccessToken(token);
+
try {
- //initialize SSL context with the trust store.
- TrustStoreManager trustStoreManager = new TrustStoreManager();
- trustStoreManager.initializeTrustStoreManager(ServerSettings.getTrustStorePath(), ServerSettings.getTrustStorePassword());
+ OAuth2TokenValidationRequestDTO oauthReq = new OAuth2TokenValidationRequestDTO();
+ OAuth2TokenValidationRequestDTO_OAuth2AccessToken token =
+ new OAuth2TokenValidationRequestDTO_OAuth2AccessToken();
+ token.setIdentifier(accessToken);
+ token.setTokenType(BEARER_TOKEN_TYPE);
+ oauthReq.setAccessToken(token);
return stub.validate(oauthReq);
} catch (RemoteException e) {
logger.error(e.getMessage(), e);
throw new AiravataSecurityException("Error in validating the OAuth access token.");
- } catch (ApplicationSettingsException e) {
+ } /*catch (ApplicationSettingsException e) {
logger.error(e.getMessage(), e);
throw new AiravataSecurityException("Error in reading OAuth configuration.");
- }
+ }*/
}
}
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c02f24d/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/DefaultXACMLPEP.java
----------------------------------------------------------------------
diff --git a/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/DefaultXACMLPEP.java b/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/DefaultXACMLPEP.java
new file mode 100644
index 0000000..371b35d
--- /dev/null
+++ b/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/DefaultXACMLPEP.java
@@ -0,0 +1,92 @@
+/*
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.airavata.api.server.security;
+
+import org.apache.airavata.common.utils.Constants;
+import org.apache.airavata.model.security.AuthzToken;
+import org.apache.airavata.security.AiravataSecurityException;
+import org.apache.axis2.AxisFault;
+import org.apache.axis2.context.ConfigurationContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.wso2.carbon.identity.entitlement.stub.EntitlementServiceStub;
+import org.wso2.carbon.identity.entitlement.stub.EntitlementServiceException;
+import org.wso2.carbon.utils.CarbonUtils;
+
+import java.rmi.Remote;
+import java.rmi.RemoteException;
+import java.util.Map;
+
+/**
+ * This enforces XACML based fine grained authorization on the API calls.
+ */
+public class DefaultXACMLPEP {
+
+ private final static Logger logger = LoggerFactory.getLogger(DefaultXACMLPEP.class);
+ private EntitlementServiceStub entitlementServiceStub;
+
+ public DefaultXACMLPEP(String auhorizationServerURL, String username, String password,
+ ConfigurationContext configCtx) throws AiravataSecurityException {
+ try {
+
+ String PDPURL = auhorizationServerURL + "EntitlementService";
+ entitlementServiceStub = new EntitlementServiceStub(configCtx, PDPURL);
+ CarbonUtils.setBasicAccessSecurityHeaders(username, password, true, entitlementServiceStub._getServiceClient());
+ } catch (AxisFault e) {
+ logger.error(e.getMessage(), e);
+ throw new AiravataSecurityException("Error initializing XACML PEP client.");
+ }
+
+ }
+
+ /**
+ * Send the XACML authorization request to XAML PDP and return the authorization decision.
+ *
+ * @param authzToken
+ * @param metaData
+ * @return
+ */
+ public boolean getAuthorizationDecision(AuthzToken authzToken, Map<String, String> metaData) throws AiravataSecurityException {
+ String decision;
+ try {
+ String subject = authzToken.getClaimsMap().get(Constants.USER_NAME);
+ String action = "/airavata/" + metaData.get(Constants.API_METHOD_NAME);
+ String decisionString = entitlementServiceStub.getDecisionByAttributes(subject, null, action, null);
+ //parse the XML decision string and obtain the decision
+
+ if ("NotApplicable".equals(decision) || "Indeterminate".equals(decision) || decision == null) {
+ logger.error("Authorization Decision is: " + decision);
+ throw new AiravataSecurityException("Error in authorizing the user.");
+ }
+ } catch (RemoteException e) {
+ logger.error(e.getMessage(), e);
+ throw new AiravataSecurityException("Error in authorizing the user.");
+ } catch (EntitlementServiceException e) {
+ logger.error(e.getMessage(), e);
+ throw new AiravataSecurityException("Error in authorizing the user.");
+ }
+ return Boolean.valueOf(decision);
+ }
+
+ private String parseDecisionString(String decisionString) {
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c02f24d/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/SecurityInterceptor.java
----------------------------------------------------------------------
diff --git a/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/SecurityInterceptor.java b/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/SecurityInterceptor.java
index cf8f7e2..ff47e5a 100644
--- a/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/SecurityInterceptor.java
+++ b/airavata-api/airavata-api-server/src/main/java/org/apache/airavata/api/server/security/SecurityInterceptor.java
@@ -19,9 +19,11 @@
*
*/
package org.apache.airavata.api.server.security;
+
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.airavata.common.exception.ApplicationSettingsException;
+import org.apache.airavata.common.utils.Constants;
import org.apache.airavata.common.utils.ServerSettings;
import org.apache.airavata.model.error.AuthorizationException;
import org.apache.airavata.model.security.AuthzToken;
@@ -29,17 +31,24 @@ import org.apache.airavata.security.AiravataSecurityException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.HashMap;
+import java.util.Map;
+
/**
* Interceptor of Airavata API calls for the purpose of applying security.
*/
-public class SecurityInterceptor implements MethodInterceptor{
+public class SecurityInterceptor implements MethodInterceptor {
private final static Logger logger = LoggerFactory.getLogger(SecurityInterceptor.class);
+
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
//obtain the authz token from the input parameters
AuthzToken authzToken = (AuthzToken) invocation.getArguments()[0];
//authorize the API call
- authorize(authzToken);
+ System.out.println("METHOD NAME: " + invocation.getMethod().getName());
+ HashMap<String, String> metaDataMap = new HashMap();
+ metaDataMap.put(Constants.API_METHOD_NAME, invocation.getMethod().getName());
+ authorize(authzToken, metaDataMap);
//set the user identity info in a thread local to be used in downstream execution.
IdentityContext.set(authzToken);
//let the method call procees upon successful authorization
@@ -49,13 +58,13 @@ public class SecurityInterceptor implements MethodInterceptor{
return returnObj;
}
- private void authorize(AuthzToken authzToken) throws AuthorizationException {
+ private void authorize(AuthzToken authzToken, Map<String, String> metaData) throws AuthorizationException {
try {
boolean isAPISecured = ServerSettings.isAPISecured();
if (isAPISecured) {
AiravataSecurityManager securityManager = SecurityManagerFactory.getSecurityManager();
- boolean isAuthz = securityManager.isUserAuthorized(authzToken);
+ boolean isAuthz = securityManager.isUserAuthorized(authzToken, metaData);
if (!isAuthz) {
throw new AuthorizationException("User is not authenticated or authorized.");
}
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c02f24d/modules/commons/src/main/java/org/apache/airavata/common/utils/Constants.java
----------------------------------------------------------------------
diff --git a/modules/commons/src/main/java/org/apache/airavata/common/utils/Constants.java b/modules/commons/src/main/java/org/apache/airavata/common/utils/Constants.java
index a2d032f..e373316 100644
--- a/modules/commons/src/main/java/org/apache/airavata/common/utils/Constants.java
+++ b/modules/commons/src/main/java/org/apache/airavata/common/utils/Constants.java
@@ -42,4 +42,10 @@ public final class Constants {
public static final String KEYSTORE_PATH = "keystore.path";
public static final String KEYSTORE_PASSWORD = "keystore.password";
public static final String TLS_CLIENT_TIMEOUT = "TLS.client.timeout";
+ public static final String API_METHOD_NAME = "api.method.name";
+
+ //Names of the attributes that could be passed in the AuthzToken's claims map.
+ public static final String USER_NAME = "userName";
+ public static final String EMAIL = "email";
+ public static final String ROLE = "role";
}
http://git-wip-us.apache.org/repos/asf/airavata/blob/9c02f24d/modules/configuration/server/src/main/resources/airavata-default-xacml-policy.xml
----------------------------------------------------------------------
diff --git a/modules/configuration/server/src/main/resources/airavata-default-xacml-policy.xml b/modules/configuration/server/src/main/resources/airavata-default-xacml-policy.xml
new file mode 100644
index 0000000..7aa42fe
--- /dev/null
+++ b/modules/configuration/server/src/main/resources/airavata-default-xacml-policy.xml
@@ -0,0 +1,62 @@
+<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" PolicyId="airavata-policy-uploaded"
+ RuleCombiningAlgId="urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:permit-overrides" Version="1.0">
+ <Target/>
+ <Rule Effect="Permit" RuleId="admin-permit">
+ <Target>
+ <AnyOf>
+ <AllOf>
+ <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-regexp-match">
+ <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">/airavata/*</AttributeValue>
+ <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id"
+ Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action"
+ DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"/>
+ </Match>
+ </AllOf>
+ </AnyOf>
+ </Target>
+ <Condition>
+ <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-is-in">
+ <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">admin</AttributeValue>
+ <AttributeDesignator AttributeId="http://wso2.org/claims/role"
+ Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
+ DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"/>
+ </Apply>
+ </Condition>
+ </Rule>
+ <Rule Effect="Permit" RuleId="user-permit">
+ <Target>
+ <AnyOf>
+ <AllOf>
+ <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-regexp-match">
+ <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">^(?:(?!
+ /airavata/addGateway|
+ /airavata/deleteteway|
+ /airavata/updateGateway|
+ /airavata/updateGateway|
+ /airavata/updateGateway|
+ /airavata/updateGateway|
+ /airavata/updateGateway|
+ /airavata/updateGateway|
+ /airavata/updateGateway|
+ /airavata/updateGateway|
+ /airavata/getExperimentStatistics).)*$\r?\n?
+ </AttributeValue>
+ <AttributeDesignator AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id"
+ Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action"
+ DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"/>
+ </Match>
+ </AllOf>
+ </AnyOf>
+ </Target>
+ <Condition>
+ <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-is-in">
+ <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">Internal/everyone</AttributeValue>
+ <AttributeDesignator AttributeId="http://wso2.org/claims/role"
+ Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject"
+ DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"/>
+ </Apply>
+ </Condition>
+ </Rule>
+ <Rule Effect="Deny" RuleId="deny-rule"/>
+</Policy>
+