/*
* Copyright (c) Members of the EGEE Collaboration. 2006-2010.
* See http://www.eu-egee.org/partners/ for details on the copyright holders.
*
* 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.glite.authz.pep.obligation.dfpmap;
import java.util.Collections;
import java.util.List;
import javax.security.auth.x500.X500Principal;
import org.glite.authz.common.fqan.FQAN;
import org.glite.authz.pep.obligation.ObligationProcessingException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/** Maps a subject to a POSIX account based on the subject's DN, primary FQAN, and secondary FQANs. */
public class AccountMapper {
/** Class logger. */
private final Logger log = LoggerFactory.getLogger(AccountMapper.class);
/** Strategy used to map a subject to a pool account indicator. */
private final AccountIndicatorMappingStrategy accountIndicatorMappingStrategy;
/** Strategy used to map a subject to a set of group names. */
private final GroupNameMappingStrategy groupNameMappingStrategy;
/** Manager used to track and access pool accounts. */
private final PoolAccountManager poolAccountManager;
/**
* Whether the failure to map a primary group name cause the {@link #mapToAccount(X500Principal, FQAN, List)} method
* to fail or not. Default: {@value}
*/
private boolean noPrimaryGroupNameIsError = false;
/**
* Constructor.
*
* @param aimStrategy strategy used to map a subject to a pool account indicator
* @param gnmStrategy strategy used to map a subject to a set of group names
* @param pam manager used to track and access pool accounts
*/
public AccountMapper(AccountIndicatorMappingStrategy aimStrategy, GroupNameMappingStrategy gnmStrategy,
PoolAccountManager pam) {
if (aimStrategy == null) {
throw new IllegalArgumentException("Account indiciator mapping strategy may not be null");
}
accountIndicatorMappingStrategy = aimStrategy;
if (gnmStrategy == null) {
throw new IllegalArgumentException("Group name mapping strategy may not be null");
}
groupNameMappingStrategy = gnmStrategy;
if (pam == null) {
throw new IllegalArgumentException("Pool account manager may not be null");
}
poolAccountManager = pam;
}
/**
* Constructor.
*
* @param aimStrategy strategy used to map a subject to a pool account indicator
* @param gnmStrategy strategy used to map a subject to a set of group names
* @param pam manager used to track and access pool accounts
* @param noPrimaryGroupNameIsError whether the failure to map a primary group name cause an error or not
*/
public AccountMapper(AccountIndicatorMappingStrategy aimStrategy, GroupNameMappingStrategy gnmStrategy,
PoolAccountManager pam, boolean noPrimaryGroupNameIsError) {
this(aimStrategy, gnmStrategy, pam);
this.noPrimaryGroupNameIsError = noPrimaryGroupNameIsError;
}
/**
* Maps a subject to a POSIX account.
*
* @param subjectDN subject's DN
* @param primaryFQAN subject's primary FQAN, may be null
* @param secondaryFQANs subject's secondary FQANs, may be null
*
* @return account to which the subject is mapped
*
* @throws ObligationProcessingException thrown is there is a problem mapping the subject to an account
*/
public PosixAccount mapToAccount(X500Principal subjectDN, FQAN primaryFQAN, List<FQAN> secondaryFQANs)
throws ObligationProcessingException {
if (subjectDN==null) {
String error= "Can not map without Subject DN";
log.error(error);
throw new ObligationProcessingException(error);
}
return mapToAccountByDNFQAN(subjectDN, primaryFQAN, secondaryFQANs);
}
/**
* Maps a subject, identified by a DN and set of FQANs, to an account.
*
* @param subjectDN DN of the subject
* @param primaryFQAN subject's primary FQAN
* @param secondaryFQANs subject's secondary FQAN
*
* @return account to which the subject is mapped
*
* @throws ObligationProcessingException thrown if there is a problem mapping the user to an account
*/
private PosixAccount mapToAccountByDNFQAN(X500Principal subjectDN, FQAN primaryFQAN, List<FQAN> secondaryFQANs)
throws ObligationProcessingException {
log.debug("Mapping subject {} with primary FQAN {} and secondary FQANs {} to a POSIX account", new Object[] {
subjectDN, primaryFQAN, secondaryFQANs });
String accountIndicator = accountIndicatorMappingStrategy.mapToAccountIndicator(subjectDN, primaryFQAN,
secondaryFQANs);
if (accountIndicator == null) {
String error = "Failed to map subject DN " + subjectDN + ", primary FQAN " + primaryFQAN
+ ", secondary FQANs " + secondaryFQANs + " to an account indicator";
log.error(error);
throw new ObligationProcessingException(error);
}
boolean indicatorIsPoolAccountPrefix = false;
if (poolAccountManager.isPoolAccountPrefix(accountIndicator)) {
indicatorIsPoolAccountPrefix = true;
accountIndicator = poolAccountManager.getPoolAccountPrefix(accountIndicator);
}
log.debug("Subject {} mapped to account indiciator {}", subjectDN.getName(), accountIndicator);
String primaryGroupName = null;
List<String> secondaryGroupNames = null;
List<String> groupNames = groupNameMappingStrategy.mapToGroupNames(subjectDN, primaryFQAN, secondaryFQANs);
if (groupNames != null && !groupNames.isEmpty()) {
primaryGroupName = groupNames.get(0);
if (groupNames.size() > 1) {
secondaryGroupNames = groupNames.subList(1, groupNames.size());
} else {
secondaryGroupNames = Collections.emptyList();
}
}
// if noPrimaryGroupNameIsError throw an error
if (primaryGroupName == null && noPrimaryGroupNameIsError) {
String error = "Failed to map subject DN " + subjectDN.getName() + ", primary FQAN " + primaryFQAN
+ ", secondary FQANs " + secondaryFQANs + " to a POSIX primary group";
log.error(error);
throw new ObligationProcessingException(error);
}
log.debug("Subject {} mapped to POSIX group {} and secondary groups {}", new Object[] { subjectDN.getName(),
primaryGroupName, secondaryGroupNames, });
String loginName;
if (indicatorIsPoolAccountPrefix) {
loginName = poolAccountManager.mapToAccount(accountIndicator, subjectDN, primaryGroupName,
secondaryGroupNames);
} else {
loginName = accountIndicator;
}
if (loginName == null) {
String error = "Failed to map subject DN " + subjectDN.getName() + ", primary FQAN " + primaryFQAN
+ ", secondary FQANs " + secondaryFQANs + " to a POSIX login name";
log.error(error);
throw new ObligationProcessingException(error);
}
log.debug("Subject {} mapped to POSIX login name {}", subjectDN.getName(), loginName);
return new PosixAccount(loginName, primaryGroupName, secondaryGroupNames);
}
}