Skip to content

Commit

Permalink
Used IS Rest APIs instead of the SOAP APIs for all the functionalities
Browse files Browse the repository at this point in the history
  • Loading branch information
rnavagamuwa committed Mar 27, 2019
1 parent 1563761 commit d060423
Show file tree
Hide file tree
Showing 9 changed files with 61 additions and 359 deletions.
7 changes: 2 additions & 5 deletions sample/src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
spring.thymeleaf.cache=false
#logging.level.web=debug
xacml.pdp.url.authorize=https://localhost:9443/api/identity/entitlement/decision/pdp
xacml.pdp.url.resource.list=https://localhost:9443/api/identity/entitlement/decision/home
xacml.pdp.url.entitlement.service=https://localhost:9443/services/EntitlementService
xacml.pdp.url.entitlement.service=https://localhost:9443/api/identity/entitlement/decision
xacml.pdp.trustStore=truststore
xacml.pdp.trustStore.password=password
xacml.pdp.keyStore=keystore
xacml.pdp.keyStore.password=password
xacml.pdp.keyStore.cert.alias=randika-client
xacml.pdp.keyStore.password=password
29 changes: 0 additions & 29 deletions sdk/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -64,36 +64,7 @@
<artifactId>spring-ws-core</artifactId>
</dependency>

<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>

</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.13.1</version>
<executions>
<execution>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
<configuration>
<schemaLanguage>WSDL</schemaLanguage>
<generatePackage>org.wso2.spring.security.abac.soaputils.wsdl</generatePackage>
<schemaDirectory>src/main/resources</schemaDirectory>
<schemaIncludes>
<include>EntitlementService.wsdl</include>
</schemaIncludes>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<commons-io.version>2.6</commons-io.version>
<org.json.version>20180813</org.json.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import org.springframework.security.access.PermissionEvaluator;
import org.springframework.security.core.Authentication;
import org.wso2.spring.security.abac.util.AuthRequestBuilder;
import org.wso2.spring.security.abac.util.XacmlAuthRequestBuilder;

import java.io.Serializable;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
package org.wso2.spring.security.abac;

import org.json.JSONObject;
import org.wso2.spring.security.abac.soaputils.wsdl.EntitledResultSetDTO;

import java.util.Optional;
import javax.xml.bind.JAXBElement;

/**
* @author Randika Navagamuwa
Expand All @@ -15,6 +13,6 @@ public interface AttributeHandler {

Optional<JSONObject> getApiResourceList();

JAXBElement<EntitledResultSetDTO> getEntitledAttributes(String subjectName, String resourceName, String subjectId, String action,
boolean enableChildSearch);
Optional<JSONObject> getEntitledAttributes(String subjectName, String resourceName, String subjectId, String action,
boolean enableChildSearch);
}
Original file line number Diff line number Diff line change
@@ -1,51 +1,32 @@
package org.wso2.spring.security.abac;

import org.apache.http.Header;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.ssl.SSLContextBuilder;
import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.support.PropertiesLoaderUtils;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.http.*;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.oxm.jaxb.Jaxb2Marshaller;
import org.springframework.util.ResourceUtils;
import org.springframework.web.client.RestTemplate;
import org.springframework.ws.transport.http.HttpComponentsMessageSender;
import org.wso2.spring.security.abac.cache.Cache;
import org.wso2.spring.security.abac.cache.CacheManager;
import org.wso2.spring.security.abac.cache.EhCacheManager;
import org.wso2.spring.security.abac.soaputils.CustomSSLHttpClientFactory;
import org.wso2.spring.security.abac.soaputils.EntitlementServiceClient;
import org.wso2.spring.security.abac.soaputils.wsdl.EntitledResultSetDTO;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Properties;
import javax.net.ssl.SSLContext;
import javax.xml.bind.JAXBElement;

/**
* @author Randika Navagamuwa
Expand All @@ -55,103 +36,60 @@ public class XacmlAttributeHandler implements AttributeHandler {

private static final Logger logger = LoggerFactory.getLogger(XacmlAttributeHandler.class);

private static String XACML_PDP_AUTHORIZE_URL;
private static String XACML_PDP_RESOURCE_LIST_URL;
private static String XACML_PDP_ENTITLEMENT_SERVICE_URL;
private static String TRUST_STORE;
private static String TRUST_STORE_PASSWORD;
private static String KEY_STORE;
private static String KEY_STORE_PASSWORD;
private static String CERT_ALIAS;

private SSLContext sslContext;
protected HttpClient httpClient;
private HttpHeaders restHeaders;
private List<Header> soapHeaders;
private CustomSSLHttpClientFactory customSSLHttpClientFactory;
private EntitlementServiceClient entitlementServiceClient;

private Cache<String, String> authCache;
private Cache<String, JAXBElement<EntitledResultSetDTO>> entitlementServiceCache;
private Cache<String, JSONObject> entitlementAttributesCache;
private Cache<String, JSONObject> apiResourceListCache;

public XacmlAttributeHandler() {

try {
Properties properties = PropertiesLoaderUtils
.loadAllProperties("application.properties");
XACML_PDP_AUTHORIZE_URL = properties.getProperty("xacml.pdp.url.authorize");
XACML_PDP_RESOURCE_LIST_URL = properties.getProperty("xacml.pdp.url.resource.list");
XACML_PDP_ENTITLEMENT_SERVICE_URL = properties.getProperty("xacml.pdp.url.entitlement.service");
TRUST_STORE = properties.getProperty("xacml.pdp.trustStore");
TRUST_STORE_PASSWORD = properties.getProperty("xacml.pdp.trustStore.password");
KEY_STORE = properties.getProperty("xacml.pdp.keyStore");
KEY_STORE_PASSWORD = properties.getProperty("xacml.pdp.keyStore.password");
CERT_ALIAS = properties.getProperty("xacml.pdp.keyStore.cert.alias");

} catch (IOException e) {

logger.error("Failed to read properties from application.properties", e);
stopApplication();
}

if (XACML_PDP_AUTHORIZE_URL == null) {

logger.error("xacml.pdp.url.authorize property is null null in application.properties");
stopApplication();
}

if (XACML_PDP_RESOURCE_LIST_URL == null) {

logger.error("xacml.pdp.url.resource.list property is null in application.properties");
stopApplication();
}

if (XACML_PDP_ENTITLEMENT_SERVICE_URL == null) {

logger.error("xacml.pdp.url.entitlement.service property is null in application.properties");
stopApplication();
}

CacheManager cacheManager = EhCacheManager.getInstance();
this.authCache = cacheManager.getCache("authCache", String.class, String.class, 60, 100);
this.entitlementAttributesCache = cacheManager.getCache("entitlementCache", String.class, JSONObject.class, 60, 100);
this.apiResourceListCache = cacheManager.getCache("apiResourceList", String.class, JSONObject.class, 60, 100);

try {
this.sslContext = SSLContextBuilder
.create()
.loadKeyMaterial(loadPfx("classpath:".concat(KEY_STORE), KEY_STORE_PASSWORD.toCharArray()),
KEY_STORE_PASSWORD.toCharArray())
.loadTrustMaterial(ResourceUtils.getFile("classpath:".concat(TRUST_STORE)),
TRUST_STORE_PASSWORD.toCharArray())
.build();

this.customSSLHttpClientFactory = new CustomSSLHttpClientFactory(
new FileSystemResource(ResourceUtils.getFile("classpath:".concat(KEY_STORE))),
KEY_STORE_PASSWORD,
"JKS",
new FileSystemResource(ResourceUtils.getFile("classpath:".concat(TRUST_STORE))),
TRUST_STORE_PASSWORD,
new String[]{"TLSv1"},
CERT_ALIAS);

this.soapHeaders = new ArrayList<>();
//todo use mutual SSL
soapHeaders.add(new BasicHeader("Authorization", "Basic YWRtaW46YWRtaW4="));

CacheManager cacheManager = EhCacheManager.getInstance();
this.authCache = cacheManager.getCache("authCache", String.class, String.class, 60, 100);
this.entitlementServiceCache = cacheManager.getCache("entitlementCache", String.class, JAXBElement.class, 60, 100);
this.apiResourceListCache = cacheManager.getCache("apiResourceList", String.class, JSONObject.class, 60, 100);

Jaxb2Marshaller marshaller = new Jaxb2Marshaller();
marshaller.setContextPath("org.wso2.spring.security.abac.soaputils.wsdl");

this.entitlementServiceClient = new EntitlementServiceClient(XACML_PDP_ENTITLEMENT_SERVICE_URL);
this.entitlementServiceClient.setMarshaller(marshaller);
this.entitlementServiceClient.setUnmarshaller(marshaller);
this.entitlementServiceClient.setMessageSender(new HttpComponentsMessageSender(
HttpClientBuilder
this.httpClient = HttpClients
.custom()
.setSSLContext(SSLContextBuilder
.create()
.setSSLSocketFactory(new SSLConnectionSocketFactory(this.sslContext, NoopHostnameVerifier.INSTANCE))
.addInterceptorFirst(new HttpComponentsMessageSender.RemoveSoapHeadersInterceptor())
.setDefaultHeaders(this.soapHeaders)
.build()));
.loadKeyMaterial(loadPfx("classpath:".concat(KEY_STORE), KEY_STORE_PASSWORD.toCharArray()),
KEY_STORE_PASSWORD.toCharArray())
.loadTrustMaterial(ResourceUtils.getFile("classpath:".concat(TRUST_STORE)),
TRUST_STORE_PASSWORD.toCharArray())
.build())
.build();

} catch (Exception e) {

logger.error("Failed to read trustStore/keyStore", e);
Expand All @@ -173,18 +111,14 @@ public boolean authorize(String authRequest) {

if (cachedResponse == null) {

HttpClient client = HttpClients.custom()
.setSSLContext(sslContext)
.build();

RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder().requestFactory(() ->
new HttpComponentsClientHttpRequestFactory(client));
new HttpComponentsClientHttpRequestFactory(this.httpClient));
RestTemplate rt = restTemplateBuilder.build();

HttpEntity<String> entity = new HttpEntity<>(authRequest, this.restHeaders);

ResponseEntity response = rt.postForEntity(XACML_PDP_AUTHORIZE_URL, entity, String.class);
if (response.getStatusCode() != HttpStatus.OK || response.getBody() == null) {
ResponseEntity response = rt.postForEntity(XACML_PDP_ENTITLEMENT_SERVICE_URL + "/pdp", entity, String.class);
if (response.getStatusCode() != HttpStatus.OK) {
return false;
}
cachedResponse = response.getBody().toString();
Expand All @@ -210,39 +144,35 @@ public boolean authorize(String authRequest) {
@Override
public Optional<JSONObject> getApiResourceList() {

JSONObject cachedObject = this.apiResourceListCache.get(XACML_PDP_RESOURCE_LIST_URL);
JSONObject cachedObject = this.apiResourceListCache.get(XACML_PDP_ENTITLEMENT_SERVICE_URL + "/home");

if (cachedObject != null) {

return Optional.of(cachedObject);
}

HttpClient client = HttpClients.custom()
.setSSLContext(sslContext)
.build();

RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder().requestFactory(() ->
new HttpComponentsClientHttpRequestFactory(client));
new HttpComponentsClientHttpRequestFactory(this.httpClient));
RestTemplate rt = restTemplateBuilder.build();

HttpEntity<String> entity = new HttpEntity<>(this.restHeaders);

ResponseEntity response = rt.getForEntity(XACML_PDP_RESOURCE_LIST_URL, String.class, entity);
ResponseEntity response = rt.getForEntity(XACML_PDP_ENTITLEMENT_SERVICE_URL + "/home", String.class, entity);

if (response.getStatusCode() != HttpStatus.OK || response.getBody() == null) {
if (response.getStatusCode() != HttpStatus.OK) {

return Optional.empty();
}

return Optional.of(this.apiResourceListCache.putIfAbsent(XACML_PDP_RESOURCE_LIST_URL,
return Optional.of(this.apiResourceListCache.putIfAbsent(XACML_PDP_ENTITLEMENT_SERVICE_URL + "/home",
new JSONObject(response.getBody().toString())));

}

@Override
public JAXBElement<EntitledResultSetDTO> getEntitledAttributes(String subjectName, String resourceName,
String subjectId, String action,
boolean enableChildSearch) {
public Optional<JSONObject> getEntitledAttributes(String subjectName, String resourceName,
String subjectId, String action,
boolean enableChildSearch) {

String key = Base64
.getEncoder()
Expand All @@ -252,14 +182,34 @@ public JAXBElement<EntitledResultSetDTO> getEntitledAttributes(String subjectNam
.concat(action)
.concat(String.valueOf(enableChildSearch)).getBytes());

JAXBElement<EntitledResultSetDTO> resultSet = this.entitlementServiceCache.get(key);
JSONObject resultSet = this.entitlementAttributesCache.get(key);

if (resultSet != null) {
return resultSet;
return Optional.of(resultSet);
}

String jsonRequest = "{\n" +
" \"subjectName\" : \"" + subjectName + "\",\n" +
" \"resourceName\": \"" + resourceName + "\",\n" +
" \"enableChildSearch\" : \"" + enableChildSearch + "\",\n" +
" \"subjectId\":\"" + subjectId + "\",\n" +
" \"action\":\"" + action + "\"\n" +
" \n" +
"}";

RestTemplateBuilder restTemplateBuilder = new RestTemplateBuilder().requestFactory(() ->
new HttpComponentsClientHttpRequestFactory(this.httpClient));
RestTemplate rt = restTemplateBuilder.build();

HttpEntity<String> entity = new HttpEntity<>(jsonRequest, this.restHeaders);

ResponseEntity response = rt.postForEntity(XACML_PDP_ENTITLEMENT_SERVICE_URL + "/entitled-attribs", entity, String.class);

if (response.getStatusCode() != HttpStatus.OK || response.getBody() == null) {
return Optional.empty();
}

return this.entitlementServiceCache.putIfAbsent(key, this.entitlementServiceClient.
getEntitledAttributes(subjectName, resourceName, subjectId, action, enableChildSearch).getReturn());
return Optional.of(this.entitlementAttributesCache.putIfAbsent(key, new JSONObject(response.getBody().toString())));

}

Expand Down
Loading

0 comments on commit d060423

Please sign in to comment.