/*
* Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
*
* WSO2 Inc. 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.wso2.carbon.identity.entitlement.proxy.thrift;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.thrift.TException;
import org.apache.thrift.protocol.TBinaryProtocol;
import org.apache.thrift.protocol.TProtocol;
import org.apache.thrift.transport.TSSLTransportFactory;
import org.apache.thrift.transport.TTransport;
import org.wso2.carbon.identity.entitlement.proxy.AbstractEntitlementServiceClient;
import org.wso2.carbon.identity.entitlement.proxy.Attribute;
import org.wso2.carbon.identity.entitlement.proxy.ProxyConstants;
import org.wso2.carbon.identity.entitlement.proxy.XACMLRequetBuilder;
import org.wso2.carbon.identity.entitlement.proxy.exception.EntitlementProxyException;
import org.wso2.carbon.identity.entitlement.proxy.generatedCode.EntitlementException;
import org.wso2.carbon.identity.entitlement.proxy.generatedCode.EntitlementThriftClient;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class ThriftEntitlementServiceClient extends AbstractEntitlementServiceClient {
private static final Log log = LogFactory.getLog(ThriftEntitlementServiceClient.class);
public static final String URN_OASIS_NAMES_TC_XACML_1_0_SUBJECT_CATEGORY_ACCESS_SUBJECT = "urn:oasis:names:tc:xacml:1.0:subject-category:access-subject";
public static final String URN_OASIS_NAMES_TC_XACML_3_0_ATTRIBUTE_CATEGORY_ACTION = "urn:oasis:names:tc:xacml:3.0:attribute-category:action";
public static final String URN_OASIS_NAMES_TC_XACML_1_0_ACTION_ACTION_ID = "urn:oasis:names:tc:xacml:1.0:action:action-id";
public static final String URN_OASIS_NAMES_TC_XACML_3_0_ATTRIBUTE_CATEGORY_RESOURCE = "urn:oasis:names:tc:xacml:3.0:attribute-category:resource";
public static final String URN_OASIS_NAMES_TC_XACML_1_0_RESOURCE_RESOURCE_ID = "urn:oasis:names:tc:xacml:1.0:resource:resource-id";
public static final String URN_OASIS_NAMES_TC_XACML_3_0_ATTRIBUTE_CATEGORY_ENVIRONMENT = "urn:oasis:names:tc:xacml:3.0:attribute-category:environment";
public static final String URN_OASIS_NAMES_TC_XACML_1_0_ENVIRONMENT_ENVIRONMENT_ID = "urn:oasis:names:tc:xacml:1.0:environment:environment-id";
private String trustStore = System.getProperty(ProxyConstants.TRUST_STORE);
private String trustStorePass = System.getProperty(ProxyConstants.TRUST_STORE_PASSWORD);
private String serverUrl;
private String userName;
private String password;
private String thriftHost;
private int thriftPort;
private boolean reuseSession = true;
private Map<String, Authenticator> authenticators = new ConcurrentHashMap<>();
public ThriftEntitlementServiceClient(String serverUrl, String username, String password, String thriftHost, int thriftPort, boolean reuseSession) {
this.serverUrl = serverUrl;
this.userName = username;
this.password = password;
this.thriftHost = thriftHost;
this.thriftPort = thriftPort;
this.reuseSession = reuseSession;
}
@Override
public String getDecision(Attribute[] attributes, String appId) throws Exception {
String xacmlRequest = XACMLRequetBuilder.buildXACML3Request(attributes);
EntitlementThriftClient.Client client = getThriftClient();
Authenticator authenticator = getAuthenticator(serverUrl, userName, password);
return getDecision(xacmlRequest, client, authenticator);
}
@Override
public boolean subjectCanActOnResource(String subjectType, String alias, String actionId,
String resourceId, String domainId, String appId) throws Exception {
Attribute subjectAttribute = new Attribute(URN_OASIS_NAMES_TC_XACML_1_0_SUBJECT_CATEGORY_ACCESS_SUBJECT, subjectType, ProxyConstants.DEFAULT_DATA_TYPE, alias);
Attribute actionAttribute = new Attribute(URN_OASIS_NAMES_TC_XACML_3_0_ATTRIBUTE_CATEGORY_ACTION, URN_OASIS_NAMES_TC_XACML_1_0_ACTION_ACTION_ID, ProxyConstants.DEFAULT_DATA_TYPE, actionId);
Attribute resourceAttribute = new Attribute(URN_OASIS_NAMES_TC_XACML_3_0_ATTRIBUTE_CATEGORY_RESOURCE,
URN_OASIS_NAMES_TC_XACML_1_0_RESOURCE_RESOURCE_ID, ProxyConstants.DEFAULT_DATA_TYPE, resourceId);
Attribute environmentAttribute = new Attribute(URN_OASIS_NAMES_TC_XACML_3_0_ATTRIBUTE_CATEGORY_ENVIRONMENT, URN_OASIS_NAMES_TC_XACML_1_0_ENVIRONMENT_ENVIRONMENT_ID, ProxyConstants.DEFAULT_DATA_TYPE, domainId);
Attribute[] tempArr = {subjectAttribute, actionAttribute, resourceAttribute, environmentAttribute};
String xacmlRequest = XACMLRequetBuilder.buildXACML3Request(tempArr);
EntitlementThriftClient.Client client = getThriftClient();
Authenticator authenticator = getAuthenticator(serverUrl, userName, password);
String decision = getDecision(xacmlRequest, client, authenticator);
if (decision != null) {
return decision.contains("Permit");
} else {
return false;
}
}
@Override
public boolean subjectCanActOnResource(String subjectType, String alias, String actionId,
String resourceId, Attribute[] attributes, String domainId, String appId) throws Exception {
Attribute[] attrs = new Attribute[attributes.length + 4];
attrs[0] = new Attribute(URN_OASIS_NAMES_TC_XACML_1_0_SUBJECT_CATEGORY_ACCESS_SUBJECT, subjectType, ProxyConstants.DEFAULT_DATA_TYPE, alias);
for (int i = 0; i < attributes.length; i++) {
attrs[i + 1] = new Attribute(URN_OASIS_NAMES_TC_XACML_1_0_SUBJECT_CATEGORY_ACCESS_SUBJECT, attributes[i].getType(),
attributes[i].getId(), attributes[i].getValue());
}
attrs[attrs.length - 3] = new Attribute(URN_OASIS_NAMES_TC_XACML_3_0_ATTRIBUTE_CATEGORY_ACTION, URN_OASIS_NAMES_TC_XACML_1_0_ACTION_ACTION_ID, ProxyConstants.DEFAULT_DATA_TYPE, actionId);
attrs[attrs.length - 2] = new Attribute(URN_OASIS_NAMES_TC_XACML_3_0_ATTRIBUTE_CATEGORY_RESOURCE, URN_OASIS_NAMES_TC_XACML_1_0_RESOURCE_RESOURCE_ID, ProxyConstants.DEFAULT_DATA_TYPE, resourceId);
attrs[attrs.length - 1] = new Attribute(URN_OASIS_NAMES_TC_XACML_3_0_ATTRIBUTE_CATEGORY_ENVIRONMENT, URN_OASIS_NAMES_TC_XACML_1_0_ENVIRONMENT_ENVIRONMENT_ID, ProxyConstants.DEFAULT_DATA_TYPE, domainId);
String xacmlRequest = XACMLRequetBuilder.buildXACML3Request(attrs);
EntitlementThriftClient.Client client = getThriftClient();
Authenticator authenticator = getAuthenticator(serverUrl, userName, password);
String decision = getDecision(xacmlRequest, client, authenticator);
if (decision != null) {
return decision.contains("Permit");
} else {
return false;
}
}
@Override
public List<String> getResourcesForAlias(String alias, String appId) {
return new ArrayList<>();
}
@Override
public List<String> getActionableResourcesForAlias(String alias, String appId) {
return new ArrayList<>();
}
@Override
public List<String> getActionsForResource(String alias, String resources, String appId) {
return new ArrayList<>();
}
@Override
public List<String> getActionableChildResourcesForAlias(String alias, String parentResource,
String action, String appId) throws Exception {
return new ArrayList<>();
}
private String getDecision(String xacmlRequest, EntitlementThriftClient.Client client, Authenticator authenticator)
throws EntitlementProxyException {
try {
return client.getDecision(xacmlRequest, authenticator.getSessionId(false));
} catch (TException e) {
if (log.isDebugEnabled()) {
log.debug("Thrift entitlement exception : ", e);
}
throw new EntitlementProxyException("Error while getting decision from PDP using " +
"ThriftEntitlementServiceClient", e);
} catch (EntitlementException e) {
if (log.isDebugEnabled()) {
log.debug("Exception occurred : ", e);
}
try {
return client.getDecision(xacmlRequest, authenticator.getSessionId(true));
} catch (TException | EntitlementException e1) {
throw new EntitlementProxyException("Error occurred while getting the decision from PDP using " +
"ThriftEntitlementServiceClient", e1);
} catch (EntitlementProxyException e1) {
throw new EntitlementProxyException("Error occurred while re-authenticating the thrift client", e1);
}
}
}
private Authenticator getAuthenticator(String serverUrl, String userName, String password)
throws Exception {
if (reuseSession && authenticators.containsKey(serverUrl)) {
return authenticators.get(serverUrl);
}
Authenticator authenticator = new Authenticator(userName, password, serverUrl + "thriftAuthenticator");
authenticators.put(serverUrl, authenticator);
return authenticator;
}
private EntitlementThriftClient.Client getThriftClient() throws Exception {
TSSLTransportFactory.TSSLTransportParameters param = new TSSLTransportFactory.TSSLTransportParameters();
param.setTrustStore(trustStore, trustStorePass);
TTransport transport;
transport = TSSLTransportFactory.getClientSocket(thriftHost, thriftPort, ProxyConstants.THRIFT_TIME_OUT, param);
TProtocol protocol = new TBinaryProtocol(transport);
return new EntitlementThriftClient.Client(protocol);
}
}