package org.dcache.gplazma.plugins; import com.google.common.collect.Lists; import org.globus.gsi.gssapi.jaas.GlobusPrincipal; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.IOException; import java.security.Principal; import java.util.List; import java.util.Properties; import java.util.Set; import java.util.concurrent.TimeUnit; import org.dcache.auth.FQAN; import org.dcache.auth.FQANPrincipal; import org.dcache.auth.GroupNamePrincipal; import org.dcache.gplazma.AuthenticationException; import org.dcache.gplazma.util.NameRolePair; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.Iterables.filter; import static org.dcache.gplazma.util.Preconditions.checkAuthentication; /** * Plugin that uses a vorolemap file for mapping FQANPrincipal and * GlobusPrincipal to GroupNamePrincipal. */ public class VoRoleMapPlugin implements GPlazmaMappingPlugin { private static final Logger _log = LoggerFactory.getLogger(VoRoleMapPlugin.class); private static final long REFRESH_PERIOD = TimeUnit.SECONDS.toMillis(10); private static final String VOROLEMAP = "gplazma.vorolemap.file"; private final SourceBackedPredicateMap<NameRolePair,String> _map; public VoRoleMapPlugin(Properties properties) throws IOException { String path = properties.getProperty(VOROLEMAP); checkArgument(path != null, "Undefined property: " + VOROLEMAP); _map = new SourceBackedPredicateMap<>(new FileLineSource(path, REFRESH_PERIOD), new VOMapLineParser()); } /** * package visible constructor for testing purposes * @param map map of dnfqans to usernames */ VoRoleMapPlugin(SourceBackedPredicateMap<NameRolePair,String> map) { _map = map; } private boolean containsPrimaryGroupName(Set<Principal> principals) { for (GroupNamePrincipal p: filter(principals, GroupNamePrincipal.class)) { if (p.isPrimaryGroup()) { return true; } } return false; } private boolean addMappingFor(GlobusPrincipal globusPrincipal, FQANPrincipal fqanPrincipal, FQAN fqan, boolean isPrimary, Set<Principal> principals) { String dn = globusPrincipal.getName(); List<String> names = _map.getValuesForPredicatesMatching(new NameRolePair(dn, fqan.toString())); if (names.isEmpty()) { return false; } String name = names.get(0); principals.add(new GroupNamePrincipal(name, isPrimary)); _log.info("VOMS authorization successful for user with DN: {} and FQAN: {} for user name: {}.", dn, fqanPrincipal, name); return true; } @Override public void map(Set<Principal> principals) throws AuthenticationException { List<FQANPrincipal> fqanPrincipals = Lists.newArrayList(filter(principals, FQANPrincipal.class)); List<GlobusPrincipal> globusPrincipals = Lists.newArrayList(filter(principals, GlobusPrincipal.class)); boolean hasPrimary = containsPrimaryGroupName(principals); boolean authorized = false; for (FQANPrincipal fqanPrincipal: fqanPrincipals) { boolean found = false; boolean isPrimary = fqanPrincipal.isPrimaryGroup() && !hasPrimary; FQAN fqan = fqanPrincipal.getFqan(); do { for (GlobusPrincipal globusPrincipal: globusPrincipals) { if (addMappingFor(globusPrincipal, fqanPrincipal, fqan, isPrimary, principals)) { authorized = true; found = true; hasPrimary |= isPrimary; } } fqan = fqan.getParent(); } while (isPrimary && !found && fqan != null); } checkAuthentication(authorized, "no record"); } }