
org.xlcloud.console.context.AccessEngineClientImpl Maven / Gradle / Ivy
The newest version!
/*
* Copyright 2012 AMG.lab, a Bull Group Company
*
* Licensed 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.xlcloud.console.context;
import java.io.Serializable;
import java.security.AccessController;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.ws.rs.core.Cookie;
import org.apache.log4j.Logger;
import org.xlcloud.config.ConfigParam;
import org.xlcloud.console.context.exceptions.SSOUserTokenInvalidException;
import org.xlcloud.console.performance.AccessEnginePerformanceMonitoring;
import org.xlcloud.logging.LoggingUtils;
import org.xlcloud.rest.exception.InternalErrorException;
import org.xlcloud.service.HttpAction;
import com.iplanet.sso.SSOException;
import com.iplanet.sso.SSOToken;
import com.iplanet.sso.SSOTokenManager;
import com.sun.identity.policy.ActionDecision;
import com.sun.identity.policy.NameNotFoundException;
import com.sun.identity.policy.Policy;
import com.sun.identity.policy.PolicyDecision;
import com.sun.identity.policy.PolicyException;
import com.sun.identity.policy.PolicyManager;
import com.sun.identity.policy.ResourceMatch;
import com.sun.identity.policy.Rule;
import com.sun.identity.policy.client.PolicyEvaluator;
import com.sun.identity.policy.client.PolicyEvaluatorFactory;
import com.sun.identity.security.AMSecurityPropertiesException;
import com.sun.identity.security.AdminTokenAction;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
/**
* Engine responsible for checking access permission basing on user's
* entitlements stored in OpenAM. Uses OpenAM's client-sdk so that all
* evaluations are performed locally (and not in OpenAM)
*
* @author Jakub Wachowski, AMG.net
*/
@AccessEnginePerformanceMonitoring
public class AccessEngineClientImpl implements AccessEngineClient, Serializable {
private static final long serialVersionUID = -707771051501050598L;
private static final Logger LOG = Logger.getLogger(AccessEngineClientImpl.class);
private static final Set ALL_ACTIONS;
static {
Set actions = new HashSet<>();
for (HttpAction ha : HttpAction.values()) {
actions.add(ha.value());
}
ALL_ACTIONS = Collections.unmodifiableSet(actions);
}
@Inject
@ConfigParam
private String realm;
@Inject
@ConfigParam
private String accessTokenValidatorUrl;
@Inject
@AccessEngineRestClient
private Client client;
private PolicyManager policyManager;
@PostConstruct
public void init(){
LOG.debug("Using Jersey client " + client.hashCode());
}
/** {@inheritDoc} */
@Override
public boolean hasAccess(SSOToken userToken, HttpAction action, String path) {
if (LOG.isTraceEnabled()) {
LOG.trace("asserting access for: " + action.value() + " : " + path);
}
try {
Set allowedActions = getAllowedActions(userToken, path);
boolean hasAccess = allowedActions.contains(action.value());
if (LOG.isDebugEnabled()) {
LOG.debug("Access validation for token [" + LoggingUtils.maskPartially("" + userToken.getTokenID()) + "] and resource ["
+ action.value() + " : " + LoggingUtils.maskResource(path) + "]: " + (hasAccess ? "allowed" : "denied"));
}
return hasAccess;
} catch (PolicyException e) {
validateUserToken(userToken);
LOG.error(e.getMessage(), e);
throw new RuntimeException(e);
} catch (SSOException e) {
validateUserToken(userToken);
LOG.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
/** {@inheritDoc} */
@Override
public boolean subjectHasAccess(String policyName, HttpAction action, String path) {
try {
if (policyManager == null) {
policyManager = new PolicyManager(getAppSSOToken(), realm);
}
Policy p = policyManager.getPolicy(policyName);
@SuppressWarnings( "unchecked" )
Set ruleNames = p.getRuleNames();
for (String ruleName : ruleNames) {
Rule r = p.getRule(ruleName);
if (ruleResourceMatches(r, path)) {
@SuppressWarnings( "unchecked" )
Map> actions = r.getActionValues();
Set a = actions.get(action.value());
if (a != null && a.size() == 1 && "allow".equals(a.iterator().next())) {
return true;
}
}
}
} catch (NameNotFoundException e) {
// TODO: if policy does not exists return false (subject does not
// have access)
// LOG.error(e.getMessage(), e);
// throw new RuntimeException(e);
} catch (SSOException e) {
LOG.error(e.getMessage(), e);
throw new RuntimeException(e);
} catch (PolicyException e) {
LOG.error(e.getMessage(), e);
throw new RuntimeException(e);
}
return false;
}
/**
* Returns current application sso token
*
* @return application sso token
*/
public synchronized static SSOToken getAppSSOToken() {
// always ensure token is valid - after OpenAM restart it may be invalid
return getAppSSOToken(true);
}
/**
* @param r
* @param path
* @return
*/
private boolean ruleResourceMatches(Rule r, String path) {
ResourceMatch rm = r.isResourceMatch("xlcRestAppl", path);
if (ResourceMatch.EXACT_MATCH.equals(rm) || ResourceMatch.WILDCARD_MATCH.equals(rm)) {
return true;
}
return false;
}
private static SSOToken getAppSSOToken(boolean refresh) {
SSOToken appToken = null;
try {
appToken = (SSOToken) AccessController.doPrivileged(AdminTokenAction.getInstance());
} catch (AMSecurityPropertiesException aspe) {
String message = "Unable to create an application token";
throw new RuntimeException(message, aspe);
}
if (refresh) {
// ensure the token is valid
try {
SSOTokenManager ssoTokenManager = SSOTokenManager.getInstance();
ssoTokenManager.refreshSession(appToken);
if (!ssoTokenManager.isValidToken(appToken)) {
try {
appToken = (SSOToken) AccessController.doPrivileged(AdminTokenAction.getInstance());
} catch (AMSecurityPropertiesException aspe) {
String message = "Unable to create an application token";
throw new RuntimeException(message, aspe);
}
}
} catch (SSOException ssoe) {
try {
appToken = (SSOToken) AccessController.doPrivileged(AdminTokenAction.getInstance());
} catch (AMSecurityPropertiesException aspe) {
String message = "Unable to create an application token";
throw new RuntimeException(message, aspe);
}
}
}
return appToken;
}
@SuppressWarnings( "unchecked" )
private Set getAllowedActions(SSOToken token, String path) throws PolicyException, SSOException {
PolicyEvaluator pe = PolicyEvaluatorFactory.getInstance().getPolicyEvaluator("xlcRestAppl");
// due to problems with caching in ClientSDK, always evaluate access for
// all actions
PolicyDecision pd = pe.getPolicyDecision(token, path, ALL_ACTIONS);
Set allowedActions = new HashSet();
Map actionDecisions = pd.getActionDecisions();
if (pd.getActionDecisions() != null) {
for (ActionDecision ad : actionDecisions.values()) {
String actionName = ad.getActionName();
Set actions = ad.getValues();
if (actions != null && actions.size() == 1 && "allow".equals(actions.iterator().next())) {
allowedActions.add(actionName);
}
}
}
return allowedActions;
}
/**
* It validates given user token and throws
* {@link SSOUserTokenInvalidException} if token is invalid.
*
* @param userToken
* user token to be validated.
* @throws SSOUserTokenInvalidException
* thrown if the token is invalid.
*/
private void validateUserToken(SSOToken userToken) throws SSOUserTokenInvalidException {
try {
if (!SSOTokenManager.getInstance().isValidToken(userToken)) {
throw new SSOUserTokenInvalidException("User's SSO token is invalid.");
}
} catch (SSOException e) {
// SSOException may occur if SSOTokenManager.getInstance() failed,
// then we are unable to validate user token.
LOG.error(e, e);
throw new RuntimeException(e.getMessage(), e);
}
}
@Override
public boolean isTokenValid(String accessToken) {
WebResource resource = client.resource(accessTokenValidatorUrl + "/" + accessToken);
ClientResponse response = resource.cookie(new Cookie("iPlanetDirectoryPro", getAppSSOToken().getTokenID().toString())).get(
ClientResponse.class);
// OpenAM should return '200 OK' code
if (response.getStatus() != ClientResponse.Status.OK.getStatusCode()) {
// if status code is 404 - it means that token id was incorrect
if (ClientResponse.Status.NOT_FOUND.equals(response.getClientResponseStatus())) {
LOG.debug("Token with id [" + LoggingUtils.maskPartially(accessToken) + "] not found in the repository");
return false;
}
LOG.debug("En error occured when validate token with id [" + LoggingUtils.maskPartially(accessToken) + "], exception: HTTP: "
+ response.getStatus() + ", " + response.getEntity(String.class));
throw new InternalErrorException("Could not validate " + LoggingUtils.maskPartially(accessToken),InternalErrorException.ErrorType.OPENAM);
} else {
return true;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy