adding XACML based fine grained authorization on API calls.
Project: http://git-wip-us.apache.org/repos/asf/airavata/repo Commit: http://git-wip-us.apache.org/repos/asf/airavata/commit/d3ac7ceb Tree: http://git-wip-us.apache.org/repos/asf/airavata/tree/d3ac7ceb Diff: http://git-wip-us.apache.org/repos/asf/airavata/diff/d3ac7ceb Branch: refs/heads/master Commit: d3ac7ceb611b3ed853e828c8492927020aacc72a Parents: 9c02f24 Author: hasinitg <hasi7...@gmail.com> Authored: Sat Aug 1 16:01:13 2015 +0530 Committer: hasinitg <hasi7...@gmail.com> Committed: Sat Aug 1 16:01:13 2015 +0530 ---------------------------------------------------------------------- .../api/server/security/DefaultXACMLPEP.java | 54 +++++++++++++++++--- .../server/security/SecurityInterceptor.java | 1 - distribution/src/main/assembly/bin-assembly.xml | 1 + .../apache/airavata/common/utils/Constants.java | 6 +++ .../resources/airavata-default-xacml-policy.xml | 33 +++++++----- .../airavata/secure/sample/SecureClient.java | 5 +- 6 files changed, 79 insertions(+), 21 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/airavata/blob/d3ac7ceb/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 index 371b35d..e61904c 100644 --- 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 @@ -27,10 +27,21 @@ import org.apache.axis2.AxisFault; import org.apache.axis2.context.ConfigurationContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; import org.wso2.carbon.identity.entitlement.stub.EntitlementServiceStub; import org.wso2.carbon.identity.entitlement.stub.EntitlementServiceException; import org.wso2.carbon.utils.CarbonUtils; +import org.xml.sax.SAXException; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; import java.rmi.Remote; import java.rmi.RemoteException; import java.util.Map; @@ -71,10 +82,15 @@ public class DefaultXACMLPEP { 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); + decision = parseDecisionString(decisionString); + if (Constants.NOT_APPLICABLE.equals(decision) || Constants.INDETERMINATE.equals(decision) || + Constants.DENY.equals(decision) || decision == null) { + logger.error("Authorization decision is: " + decision); throw new AiravataSecurityException("Error in authorizing the user."); + } else if (Constants.PERMIT.equals(decision)) { + return true; + } else { + return false; } } catch (RemoteException e) { logger.error(e.getMessage(), e); @@ -83,10 +99,36 @@ public class DefaultXACMLPEP { logger.error(e.getMessage(), e); throw new AiravataSecurityException("Error in authorizing the user."); } - return Boolean.valueOf(decision); } - private String parseDecisionString(String decisionString) { - + /** + * This parses the XML based authorization response by the PDP and returns the decision string. + * + * @param decisionString + * @return + * @throws AiravataSecurityException + */ + private String parseDecisionString(String decisionString) throws AiravataSecurityException { + try { + DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance(); + InputStream inputStream = new ByteArrayInputStream(decisionString.getBytes("UTF-8")); + Document doc = docBuilderFactory.newDocumentBuilder().parse(inputStream); + Node resultNode = doc.getDocumentElement().getFirstChild(); + Node decisionNode = resultNode.getFirstChild(); + String decision = decisionNode.getTextContent(); + return decision; + } catch (ParserConfigurationException e) { + logger.error(e.getMessage(), e); + throw new AiravataSecurityException("Error in parsing XACML authorization response."); + } catch (UnsupportedEncodingException e) { + logger.error(e.getMessage(), e); + throw new AiravataSecurityException("Error in parsing XACML authorization response."); + } catch (SAXException e) { + logger.error(e.getMessage(), e); + throw new AiravataSecurityException("Error in parsing XACML authorization response."); + } catch (IOException e) { + logger.error("Error in parsing XACML authorization response."); + throw new AiravataSecurityException("Error in parsing XACML authorization response."); + } } } http://git-wip-us.apache.org/repos/asf/airavata/blob/d3ac7ceb/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 ff47e5a..1f9cd90 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 @@ -45,7 +45,6 @@ public class SecurityInterceptor implements MethodInterceptor { //obtain the authz token from the input parameters AuthzToken authzToken = (AuthzToken) invocation.getArguments()[0]; //authorize the API call - 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); http://git-wip-us.apache.org/repos/asf/airavata/blob/d3ac7ceb/distribution/src/main/assembly/bin-assembly.xml ---------------------------------------------------------------------- diff --git a/distribution/src/main/assembly/bin-assembly.xml b/distribution/src/main/assembly/bin-assembly.xml index c00c2e2..e399291 100644 --- a/distribution/src/main/assembly/bin-assembly.xml +++ b/distribution/src/main/assembly/bin-assembly.xml @@ -105,6 +105,7 @@ <include>gsissh.properties</include> <include>airavata.jks</include> <include>client_truststore.jks</include> + <include>airavata-default-xacml-policy.xml</include> </includes> </fileSet> http://git-wip-us.apache.org/repos/asf/airavata/blob/d3ac7ceb/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 e373316..215a313 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 @@ -44,6 +44,12 @@ public final class Constants { public static final String TLS_CLIENT_TIMEOUT = "TLS.client.timeout"; public static final String API_METHOD_NAME = "api.method.name"; + //constants in XACML authorization response. + public static final String NOT_APPLICABLE = "NotApplicable"; + public static final String INDETERMINATE = "Indeterminate"; + public static final String DENY = "Deny"; + public static final String PERMIT = "Permit"; + //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"; http://git-wip-us.apache.org/repos/asf/airavata/blob/d3ac7ceb/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 index 7aa42fe..ab3208d 100644 --- a/modules/configuration/server/src/main/resources/airavata-default-xacml-policy.xml +++ b/modules/configuration/server/src/main/resources/airavata-default-xacml-policy.xml @@ -1,4 +1,4 @@ -<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" PolicyId="airavata-policy-uploaded" +<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" PolicyId="airavata-policy" RuleCombiningAlgId="urn:oasis:names:tc:xacml:3.0:rule-combining-algorithm:permit-overrides" Version="1.0"> <Target/> <Rule Effect="Permit" RuleId="admin-permit"> @@ -29,18 +29,25 @@ <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> +/airavata/addGateway| +/airavata/deleteteway| +/airavata/updateGateway| +/airavata/registerApplicationModule| +/airavata/deleteApplicationModule| +/airavata/getAllApplicationInterfaces| +/airavata/updateApplicationInterface| +/airavata/deleteApplicationInterface| +/airavata/getAllComputeResourceNames| +/airavata/getAllApplicationDeployments| +/airavata/updateApplicationDeployment| +/airavata/registerApplicationDeployment| +/airavata/deleteApplicationDeployment| +/airavata/getAllAppModules| +/airavata/getApplicationInterface| +/airavata/getApplicationInputs| +/airavata/getApplicationOutputs| +/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"/> http://git-wip-us.apache.org/repos/asf/airavata/blob/d3ac7ceb/samples/java-client/secure-client/src/main/java/org/apache/airavata/secure/sample/SecureClient.java ---------------------------------------------------------------------- diff --git a/samples/java-client/secure-client/src/main/java/org/apache/airavata/secure/sample/SecureClient.java b/samples/java-client/secure-client/src/main/java/org/apache/airavata/secure/sample/SecureClient.java index 36b1783..ac34c18 100644 --- a/samples/java-client/secure-client/src/main/java/org/apache/airavata/secure/sample/SecureClient.java +++ b/samples/java-client/secure-client/src/main/java/org/apache/airavata/secure/sample/SecureClient.java @@ -151,6 +151,9 @@ public class SecureClient { } } else if (grantType == 2) { System.out.println("Obtaining OAuth access token via 'Client Credential' grant type...' grant type...."); + System.out.println("Please enter the user name to be passed: "); + String userNameInput = scanner.next(); + userName = userNameInput.trim(); } /***************************** Finish obtaining input from user*******************************************/ @@ -176,7 +179,7 @@ public class SecureClient { AuthzToken authzToken = new AuthzToken(); authzToken.setAccessToken(acTk); Map<String, String> claimsMap = new HashMap<>(); - claimsMap.put("userName", "hasinitg"); + claimsMap.put("userName", userName); claimsMap.put("email", "has...@gmail.com"); authzToken.setClaimsMap(claimsMap); String version = client.getAPIVersion(authzToken);