Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id E80AF200C8E for ; Thu, 8 Jun 2017 13:33:56 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id E501D160BD5; Thu, 8 Jun 2017 11:33:56 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id E23FC160BCA for ; Thu, 8 Jun 2017 13:33:54 +0200 (CEST) Received: (qmail 85408 invoked by uid 500); 8 Jun 2017 11:33:54 -0000 Mailing-List: contact commits-help@ambari.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: ambari-dev@ambari.apache.org Delivered-To: mailing list commits@ambari.apache.org Received: (qmail 85399 invoked by uid 99); 8 Jun 2017 11:33:54 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 08 Jun 2017 11:33:54 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 0099EDFE5C; Thu, 8 Jun 2017 11:33:52 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: oleewere@apache.org To: commits@ambari.apache.org Message-Id: <8ef6c65a4e1c43199a17644653829592@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: ambari git commit: AMBARI-21196. Fix ambari-solr-plugin folder structure (oleewere) Date: Thu, 8 Jun 2017 11:33:52 +0000 (UTC) archived-at: Thu, 08 Jun 2017 11:33:57 -0000 Repository: ambari Updated Branches: refs/heads/trunk 2ff48a00b -> 3146a1970 AMBARI-21196. Fix ambari-solr-plugin folder structure (oleewere) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/3146a197 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/3146a197 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/3146a197 Branch: refs/heads/trunk Commit: 3146a1970f356427010a2275462a6ad93c9ce126 Parents: 2ff48a0 Author: oleewere Authored: Wed Jun 7 19:54:17 2017 +0200 Committer: oleewere Committed: Thu Jun 8 13:29:46 2017 +0200 ---------------------------------------------------------------------- .../InfraKerberosHostValidator.java | 54 -- .../InfraRuleBasedAuthorizationPlugin.java | 542 ------------------- .../InfraUserRolesLookupStrategy.java | 49 -- .../security/InfraKerberosHostValidator.java | 54 ++ .../InfraRuleBasedAuthorizationPlugin.java | 542 +++++++++++++++++++ .../security/InfraUserRolesLookupStrategy.java | 49 ++ 6 files changed, 645 insertions(+), 645 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/3146a197/ambari-infra/ambari-infra-solr-plugin/src/main/java/org.apache.ambari.infra.security/InfraKerberosHostValidator.java ---------------------------------------------------------------------- diff --git a/ambari-infra/ambari-infra-solr-plugin/src/main/java/org.apache.ambari.infra.security/InfraKerberosHostValidator.java b/ambari-infra/ambari-infra-solr-plugin/src/main/java/org.apache.ambari.infra.security/InfraKerberosHostValidator.java deleted file mode 100644 index 4a47a89..0000000 --- a/ambari-infra/ambari-infra-solr-plugin/src/main/java/org.apache.ambari.infra.security/InfraKerberosHostValidator.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.ambari.infra.security; - -import org.apache.commons.collections.CollectionUtils; -import org.apache.commons.collections.MapUtils; -import org.apache.hadoop.security.authentication.server.AuthenticationToken; -import org.apache.hadoop.security.authentication.util.KerberosName; - -import java.security.Principal; -import java.util.Map; -import java.util.Set; - -/** - * Validate that the user has the right access based on the hostname in the kerberos principal - */ -public class InfraKerberosHostValidator { - - public boolean validate(Principal principal, Map> userVsHosts, Map userVsHostRegex) { - if (principal instanceof AuthenticationToken) { - AuthenticationToken authenticationToken = (AuthenticationToken) principal; - KerberosName kerberosName = new KerberosName(authenticationToken.getName()); - String hostname = kerberosName.getHostName(); - String serviceUserName = kerberosName.getServiceName(); - if (MapUtils.isNotEmpty(userVsHostRegex)) { - String regex = userVsHostRegex.get(serviceUserName); - return hostname.matches(regex); - } - if (MapUtils.isNotEmpty(userVsHosts)) { - Set hosts = userVsHosts.get(serviceUserName); - if (CollectionUtils.isNotEmpty(hosts)) { - return hosts.contains(hostname); - } - } - } - return true; - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/3146a197/ambari-infra/ambari-infra-solr-plugin/src/main/java/org.apache.ambari.infra.security/InfraRuleBasedAuthorizationPlugin.java ---------------------------------------------------------------------- diff --git a/ambari-infra/ambari-infra-solr-plugin/src/main/java/org.apache.ambari.infra.security/InfraRuleBasedAuthorizationPlugin.java b/ambari-infra/ambari-infra-solr-plugin/src/main/java/org.apache.ambari.infra.security/InfraRuleBasedAuthorizationPlugin.java deleted file mode 100644 index 2f1a558..0000000 --- a/ambari-infra/ambari-infra-solr-plugin/src/main/java/org.apache.ambari.infra.security/InfraRuleBasedAuthorizationPlugin.java +++ /dev/null @@ -1,542 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.ambari.infra.security; - -import com.google.common.collect.ImmutableSet; -import java.io.IOException; -import java.lang.invoke.MethodHandles; -import java.security.Principal; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; -import org.apache.solr.common.SolrException; -import org.apache.solr.common.params.CollectionParams; -import org.apache.solr.common.util.Utils; -import org.apache.solr.security.AuthorizationContext; -import org.apache.solr.security.AuthorizationPlugin; -import org.apache.solr.security.AuthorizationResponse; -import org.apache.solr.security.ConfigEditablePlugin; -import org.apache.solr.util.CommandOperation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import static java.util.Collections.singleton; -import static org.apache.solr.common.params.CommonParams.NAME; -import static org.apache.solr.common.util.Utils.getDeepCopy; -import static org.apache.solr.handler.admin.SecurityConfHandler.getListValue; -import static org.apache.solr.handler.admin.SecurityConfHandler.getMapValue; - -/** - * Modified copy of solr.RuleBasedAuthorizationPlugin to handle role - permission mappings with KereberosPlugin - * Added 2 new JSON map: (precedence: user-host-regex > user-host) - * 1. "user-host": user host mappings (array) for hostname validation - * 2. "user-host-regex": user host regex mapping (string) for hostname validation - */ -public class InfraRuleBasedAuthorizationPlugin implements AuthorizationPlugin, ConfigEditablePlugin { - - private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); - - private final Map> usersVsRoles = new HashMap<>(); - private final Map mapping = new HashMap<>(); - private final List permissions = new ArrayList<>(); - private final Map> userVsHosts = new HashMap<>(); - private final Map userVsHostRegex = new HashMap<>(); - - private final InfraUserRolesLookupStrategy infraUserRolesLookupStrategy = new InfraUserRolesLookupStrategy(); - private final InfraKerberosHostValidator infraKerberosDomainValidator = new InfraKerberosHostValidator(); - - private static class WildCardSupportMap extends HashMap> { - final Set wildcardPrefixes = new HashSet<>(); - - @Override - public List put(String key, List value) { - if (key != null && key.endsWith("/*")) { - key = key.substring(0, key.length() - 2); - wildcardPrefixes.add(key); - } - return super.put(key, value); - } - - @Override - public List get(Object key) { - List result = super.get(key); - if (key == null || result != null) return result; - if (!wildcardPrefixes.isEmpty()) { - for (String s : wildcardPrefixes) { - if (key.toString().startsWith(s)) { - List l = super.get(s); - if (l != null) { - result = result == null ? new ArrayList() : new ArrayList(result); - result.addAll(l); - } - } - } - } - return result; - } - } - - @Override - public AuthorizationResponse authorize(AuthorizationContext context) { - List collectionRequests = context.getCollectionRequests(); - if (context.getRequestType() == AuthorizationContext.RequestType.ADMIN) { - MatchStatus flag = checkCollPerm(mapping.get(null), context); - return flag.rsp; - } - - for (AuthorizationContext.CollectionRequest collreq : collectionRequests) { - //check permissions for each collection - MatchStatus flag = checkCollPerm(mapping.get(collreq.collectionName), context); - if (flag != MatchStatus.NO_PERMISSIONS_FOUND) return flag.rsp; - } - //check wildcard (all=*) permissions. - MatchStatus flag = checkCollPerm(mapping.get("*"), context); - return flag.rsp; - } - - private MatchStatus checkCollPerm(Map> pathVsPerms, - AuthorizationContext context) { - if (pathVsPerms == null) return MatchStatus.NO_PERMISSIONS_FOUND; - - String path = context.getResource(); - MatchStatus flag = checkPathPerm(pathVsPerms.get(path), context); - if (flag != MatchStatus.NO_PERMISSIONS_FOUND) return flag; - return checkPathPerm(pathVsPerms.get(null), context); - } - - private MatchStatus checkPathPerm(List permissions, AuthorizationContext context) { - if (permissions == null || permissions.isEmpty()) return MatchStatus.NO_PERMISSIONS_FOUND; - Principal principal = context.getUserPrincipal(); - loopPermissions: - for (int i = 0; i < permissions.size(); i++) { - Permission permission = permissions.get(i); - if (permission.method != null && !permission.method.contains(context.getHttpMethod())) { - //this permissions HTTP method does not match this rule. try other rules - continue; - } - if(permission.predicate != null){ - if(!permission.predicate.test(context)) continue ; - } - - if (permission.params != null) { - for (Map.Entry e : permission.params.entrySet()) { - String paramVal = context.getParams().get(e.getKey()); - Object val = e.getValue(); - if (val instanceof List) { - if (!((List) val).contains(paramVal)) continue loopPermissions; - } else if (!Objects.equals(val, paramVal)) continue loopPermissions; - } - } - - if (permission.role == null) { - //no role is assigned permission.That means everybody is allowed to access - return MatchStatus.PERMITTED; - } - if (principal == null) { - log.info("request has come without principal. failed permission {} ",permission); - //this resource needs a principal but the request has come without - //any credential. - return MatchStatus.USER_REQUIRED; - } else if (permission.role.contains("*")) { - return MatchStatus.PERMITTED; - } - - for (String role : permission.role) { - Set userRoles = infraUserRolesLookupStrategy.getUserRolesFromPrincipal(usersVsRoles, principal); - boolean validHostname = infraKerberosDomainValidator.validate(principal, userVsHosts, userVsHostRegex); - if (!validHostname) { - log.warn("Hostname is not valid for principal {}", principal); - return MatchStatus.FORBIDDEN; - } - if (userRoles != null && userRoles.contains(role)) return MatchStatus.PERMITTED; - } - log.info("This resource is configured to have a permission {}, The principal {} does not have the right role ", permission, principal); - return MatchStatus.FORBIDDEN; - } - log.debug("No permissions configured for the resource {} . So allowed to access", context.getResource()); - return MatchStatus.NO_PERMISSIONS_FOUND; - } - - @Override - public void init(Map initInfo) { - mapping.put(null, new WildCardSupportMap()); - Map map = getMapValue(initInfo, "user-role"); - for (Object o : map.entrySet()) { - Map.Entry e = (Map.Entry) o; - String roleName = (String) e.getKey(); - usersVsRoles.put(roleName, readValueAsSet(map, roleName)); - } - List perms = getListValue(initInfo, "permissions"); - for (Map o : perms) { - Permission p; - try { - p = Permission.load(o); - } catch (Exception exp) { - log.error("Invalid permission ", exp); - continue; - } - permissions.add(p); - add2Mapping(p); - } - // adding user-host - Map userHostsMap = getMapValue(initInfo, "user-host"); - for (Object userHost : userHostsMap.entrySet()) { - Map.Entry e = (Map.Entry) userHost; - String roleName = (String) e.getKey(); - userVsHosts.put(roleName, readValueAsSet(userHostsMap, roleName)); - } - // adding user-host-regex - Map userHostRegexMap = getMapValue(initInfo, "user-host-regex"); - for (Map.Entry entry : userHostRegexMap.entrySet()) { - userVsHostRegex.put(entry.getKey(), entry.getValue().toString()); - } - - } - - //this is to do optimized lookup of permissions for a given collection/path - private void add2Mapping(Permission permission) { - for (String c : permission.collections) { - WildCardSupportMap m = mapping.get(c); - if (m == null) mapping.put(c, m = new WildCardSupportMap()); - for (String path : permission.path) { - List perms = m.get(path); - if (perms == null) m.put(path, perms = new ArrayList<>()); - perms.add(permission); - } - } - } - - /** - * read a key value as a set. if the value is a single string , - * return a singleton set - * - * @param m the map from which to lookup - * @param key the key with which to do lookup - */ - static Set readValueAsSet(Map m, String key) { - Set result = new HashSet<>(); - Object val = m.get(key); - if (val == null) { - if("collection".equals(key)){ - //for collection collection: null means a core admin/ collection admin request - // otherwise it means a request where collection name is ignored - return m.containsKey(key) ? singleton((String) null) : singleton("*"); - } - return null; - } - if (val instanceof Collection) { - Collection list = (Collection) val; - for (Object o : list) result.add(String.valueOf(o)); - } else if (val instanceof String) { - result.add((String) val); - } else { - throw new RuntimeException("Bad value for : " + key); - } - return result.isEmpty() ? null : Collections.unmodifiableSet(result); - } - - @Override - public void close() throws IOException { } - - static class Permission { - String name; - Set path, role, collections, method; - Map params; - Predicate predicate; - Map originalConfig; - - private Permission() { - } - - static Permission load(Map m) { - Permission p = new Permission(); - p.originalConfig = new LinkedHashMap<>(m); - String name = (String) m.get(NAME); - if (!m.containsKey("role")) throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "role not specified"); - p.role = readValueAsSet(m, "role"); - if (well_known_permissions.containsKey(name)) { - HashSet disAllowed = new HashSet<>(knownKeys); - disAllowed.remove("role");//these are the only - disAllowed.remove(NAME);//allowed keys for well-known permissions - for (String s : disAllowed) { - if (m.containsKey(s)) - throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, s + " is not a valid key for the permission : " + name); - } - p.predicate = (Predicate) ((Map) well_known_permissions.get(name)).get(Predicate.class.getName()); - m = well_known_permissions.get(name); - } - p.name = name; - p.path = readSetSmart(name, m, "path"); - p.collections = readSetSmart(name, m, "collection"); - p.method = readSetSmart(name, m, "method"); - p.params = (Map) m.get("params"); - return p; - } - - @Override - public String toString() { - return Utils.toJSONString(originalConfig); - } - - static final Set knownKeys = ImmutableSet.of("collection", "role", "params", "path", "method", NAME); - } - - enum MatchStatus { - USER_REQUIRED(AuthorizationResponse.PROMPT), - NO_PERMISSIONS_FOUND(AuthorizationResponse.OK), - PERMITTED(AuthorizationResponse.OK), - FORBIDDEN(AuthorizationResponse.FORBIDDEN); - - final AuthorizationResponse rsp; - - MatchStatus(AuthorizationResponse rsp) { - this.rsp = rsp; - } - } - - /** - * This checks for the defaults available other rules for the keys - */ - private static Set readSetSmart(String permissionName, Map m, String key) { - Set set = readValueAsSet(m, key); - if (set == null && well_known_permissions.containsKey(permissionName)) { - set = readValueAsSet((Map) well_known_permissions.get(permissionName), key); - } - if ("method".equals(key)) { - if (set != null) { - for (String s : set) if (!HTTP_METHODS.contains(s)) return null; - } - return set; - } - return set == null ? singleton((String)null) : set; - } - - @Override - public Map edit(Map latestConf, List commands) { - for (CommandOperation op : commands) { - OPERATION operation = null; - for (OPERATION o : OPERATION.values()) { - if (o.name.equals(op.name)) { - operation = o; - break; - } - } - if (operation == null) { - op.unknownOperation(); - return null; - } - latestConf = operation.edit(latestConf, op); - if (latestConf == null) return null; - - } - return latestConf; - } - - enum OPERATION { - SET_USER_ROLE("set-user-role") { - @Override - public Map edit(Map latestConf, CommandOperation op) { - Map roleMap = getMapValue(latestConf, "user-role"); - Map map = op.getDataMap(); - if (op.hasError()) return null; - for (Map.Entry e : map.entrySet()) { - if (e.getValue() == null) { - roleMap.remove(e.getKey()); - continue; - } - if (e.getValue() instanceof String || e.getValue() instanceof List) { - roleMap.put(e.getKey(), e.getValue()); - } else { - op.addError("Unexpected value "); - return null; - } - } - return latestConf; - } - }, - SET_PERMISSION("set-permission") { - @Override - public Map edit(Map latestConf, CommandOperation op) { - String name = op.getStr(NAME); - Map dataMap = op.getDataMap(); - if (op.hasError()) return null; - dataMap = getDeepCopy(dataMap, 3); - String before = (String) dataMap.remove("before"); - for (String key : dataMap.keySet()) { - if (!Permission.knownKeys.contains(key)) op.addError("Unknown key, " + key); - } - try { - Permission.load(dataMap); - } catch (Exception e) { - op.addError(e.getMessage()); - return null; - } - List permissions = getListValue(latestConf, "permissions"); - List permissionsCopy = new ArrayList<>(); - boolean added = false; - for (Map e : permissions) { - Object n = e.get(NAME); - if (n.equals(before) || n.equals(name)) { - added = true; - permissionsCopy.add(dataMap); - } - if (!n.equals(name)) permissionsCopy.add(e); - } - if (!added && before != null) { - op.addError("Invalid 'before' :" + before); - return null; - } - if (!added) permissionsCopy.add(dataMap); - latestConf.put("permissions", permissionsCopy); - return latestConf; - } - }, - UPDATE_PERMISSION("update-permission") { - @Override - public Map edit(Map latestConf, CommandOperation op) { - String name = op.getStr(NAME); - if (op.hasError()) return null; - for (Map permission : (List) getListValue(latestConf, "permissions")) { - if (name.equals(permission.get(NAME))) { - LinkedHashMap copy = new LinkedHashMap<>(permission); - copy.putAll(op.getDataMap()); - op.setCommandData(copy); - return SET_PERMISSION.edit(latestConf, op); - } - } - op.addError("No such permission " + name); - return null; - } - }, - DELETE_PERMISSION("delete-permission") { - @Override - public Map edit(Map latestConf, CommandOperation op) { - List names = op.getStrs(""); - if (names == null || names.isEmpty()) { - op.addError("Invalid command"); - return null; - } - names = new ArrayList<>(names); - List copy = new ArrayList<>(); - List p = getListValue(latestConf, "permissions"); - for (Map map : p) { - Object n = map.get(NAME); - if (names.contains(n)) { - names.remove(n); - continue; - } else { - copy.add(map); - } - } - if (!names.isEmpty()) { - op.addError("Unknown permission name(s) " + names); - return null; - } - latestConf.put("permissions", copy); - return latestConf; - } - }; - - public abstract Map edit(Map latestConf, CommandOperation op); - - public final String name; - - OPERATION(String s) { - this.name = s; - } - - public static OPERATION get(String name) { - for (OPERATION o : values()) if (o.name.equals(name)) return o; - return null; - } - } - - public static final Set HTTP_METHODS = ImmutableSet.of("GET", "POST", "DELETE", "PUT", "HEAD"); - - private static final Map> well_known_permissions = (Map) Utils.fromJSONString( - " { " + - " security-edit :{" + - " path:['/admin/authentication','/admin/authorization']," + - " collection:null," + - " method:POST }," + - " security-read :{" + - " path:['/admin/authentication','/admin/authorization']," + - " collection:null," + - " method:GET}," + - " schema-edit :{" + - " method:POST," + - " path:'/schema/*'}," + - " collection-admin-edit :{" + - " collection:null," + - " path:'/admin/collections'}," + - " collection-admin-read :{" + - " collection:null," + - " path:'/admin/collections'}," + - " schema-read :{" + - " method:GET," + - " path:'/schema/*'}," + - " config-read :{" + - " method:GET," + - " path:'/config/*'}," + - " update :{" + - " path:'/update/*'}," + - " read :{" + - " path:['/select', '/get','/browse','/tvrh','/terms','/clustering','/elevate', '/export','/spell','/clustering']}," + - " config-edit:{" + - " method:POST," + - " path:'/config/*'}," + - " all:{collection:['*', null]}" + - "}"); - - static { - ((Map) well_known_permissions.get("collection-admin-edit")).put(Predicate.class.getName(), getCollectionActionPredicate(true)); - ((Map) well_known_permissions.get("collection-admin-read")).put(Predicate.class.getName(), getCollectionActionPredicate(false)); - } - - private static Predicate getCollectionActionPredicate(final boolean isEdit) { - return new Predicate() { - @Override - public boolean test(AuthorizationContext context) { - String action = context.getParams().get("action"); - if (action == null) return false; - CollectionParams.CollectionAction collectionAction = CollectionParams.CollectionAction.get(action); - if (collectionAction == null) return false; - return isEdit ? collectionAction.isWrite : !collectionAction.isWrite; - } - }; - } - - - public static void main(String[] args) { - System.out.println(Utils.toJSONString(well_known_permissions)); - - } - - public interface Predicate { - - boolean test(T t); - } -} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/3146a197/ambari-infra/ambari-infra-solr-plugin/src/main/java/org.apache.ambari.infra.security/InfraUserRolesLookupStrategy.java ---------------------------------------------------------------------- diff --git a/ambari-infra/ambari-infra-solr-plugin/src/main/java/org.apache.ambari.infra.security/InfraUserRolesLookupStrategy.java b/ambari-infra/ambari-infra-solr-plugin/src/main/java/org.apache.ambari.infra.security/InfraUserRolesLookupStrategy.java deleted file mode 100644 index a54e4ad..0000000 --- a/ambari-infra/ambari-infra-solr-plugin/src/main/java/org.apache.ambari.infra.security/InfraUserRolesLookupStrategy.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF 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.apache.ambari.infra.security; - -import org.apache.commons.collections.CollectionUtils; -import org.apache.hadoop.security.authentication.server.AuthenticationToken; -import org.apache.hadoop.security.authentication.util.KerberosName; - -import java.security.Principal; -import java.util.Map; -import java.util.Set; - - -/** - * Strategy class to get roles with the principal name (in a specific format e.g.: 'name@DOMAIN') - * in case of KerberosPlugin is used for authentication - */ -public class InfraUserRolesLookupStrategy { - - public Set getUserRolesFromPrincipal(Map> usersVsRoles, Principal principal) { - if (principal instanceof AuthenticationToken) { - AuthenticationToken authenticationToken = (AuthenticationToken) principal; - KerberosName kerberosName = new KerberosName(authenticationToken.getName()); - Set rolesResult = usersVsRoles.get(String.format("%s@%s", kerberosName.getServiceName(), kerberosName.getRealm())); - if (CollectionUtils.isEmpty(rolesResult)) { - rolesResult = usersVsRoles.get(principal.getName()); - } - return rolesResult; - } else { - return usersVsRoles.get(principal.getName()); - } - } -} http://git-wip-us.apache.org/repos/asf/ambari/blob/3146a197/ambari-infra/ambari-infra-solr-plugin/src/main/java/org/apache/ambari/infra/security/InfraKerberosHostValidator.java ---------------------------------------------------------------------- diff --git a/ambari-infra/ambari-infra-solr-plugin/src/main/java/org/apache/ambari/infra/security/InfraKerberosHostValidator.java b/ambari-infra/ambari-infra-solr-plugin/src/main/java/org/apache/ambari/infra/security/InfraKerberosHostValidator.java new file mode 100644 index 0000000..4a47a89 --- /dev/null +++ b/ambari-infra/ambari-infra-solr-plugin/src/main/java/org/apache/ambari/infra/security/InfraKerberosHostValidator.java @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.ambari.infra.security; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.commons.collections.MapUtils; +import org.apache.hadoop.security.authentication.server.AuthenticationToken; +import org.apache.hadoop.security.authentication.util.KerberosName; + +import java.security.Principal; +import java.util.Map; +import java.util.Set; + +/** + * Validate that the user has the right access based on the hostname in the kerberos principal + */ +public class InfraKerberosHostValidator { + + public boolean validate(Principal principal, Map> userVsHosts, Map userVsHostRegex) { + if (principal instanceof AuthenticationToken) { + AuthenticationToken authenticationToken = (AuthenticationToken) principal; + KerberosName kerberosName = new KerberosName(authenticationToken.getName()); + String hostname = kerberosName.getHostName(); + String serviceUserName = kerberosName.getServiceName(); + if (MapUtils.isNotEmpty(userVsHostRegex)) { + String regex = userVsHostRegex.get(serviceUserName); + return hostname.matches(regex); + } + if (MapUtils.isNotEmpty(userVsHosts)) { + Set hosts = userVsHosts.get(serviceUserName); + if (CollectionUtils.isNotEmpty(hosts)) { + return hosts.contains(hostname); + } + } + } + return true; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/3146a197/ambari-infra/ambari-infra-solr-plugin/src/main/java/org/apache/ambari/infra/security/InfraRuleBasedAuthorizationPlugin.java ---------------------------------------------------------------------- diff --git a/ambari-infra/ambari-infra-solr-plugin/src/main/java/org/apache/ambari/infra/security/InfraRuleBasedAuthorizationPlugin.java b/ambari-infra/ambari-infra-solr-plugin/src/main/java/org/apache/ambari/infra/security/InfraRuleBasedAuthorizationPlugin.java new file mode 100644 index 0000000..2f1a558 --- /dev/null +++ b/ambari-infra/ambari-infra-solr-plugin/src/main/java/org/apache/ambari/infra/security/InfraRuleBasedAuthorizationPlugin.java @@ -0,0 +1,542 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.ambari.infra.security; + +import com.google.common.collect.ImmutableSet; +import java.io.IOException; +import java.lang.invoke.MethodHandles; +import java.security.Principal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import org.apache.solr.common.SolrException; +import org.apache.solr.common.params.CollectionParams; +import org.apache.solr.common.util.Utils; +import org.apache.solr.security.AuthorizationContext; +import org.apache.solr.security.AuthorizationPlugin; +import org.apache.solr.security.AuthorizationResponse; +import org.apache.solr.security.ConfigEditablePlugin; +import org.apache.solr.util.CommandOperation; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import static java.util.Collections.singleton; +import static org.apache.solr.common.params.CommonParams.NAME; +import static org.apache.solr.common.util.Utils.getDeepCopy; +import static org.apache.solr.handler.admin.SecurityConfHandler.getListValue; +import static org.apache.solr.handler.admin.SecurityConfHandler.getMapValue; + +/** + * Modified copy of solr.RuleBasedAuthorizationPlugin to handle role - permission mappings with KereberosPlugin + * Added 2 new JSON map: (precedence: user-host-regex > user-host) + * 1. "user-host": user host mappings (array) for hostname validation + * 2. "user-host-regex": user host regex mapping (string) for hostname validation + */ +public class InfraRuleBasedAuthorizationPlugin implements AuthorizationPlugin, ConfigEditablePlugin { + + private static final Logger log = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + private final Map> usersVsRoles = new HashMap<>(); + private final Map mapping = new HashMap<>(); + private final List permissions = new ArrayList<>(); + private final Map> userVsHosts = new HashMap<>(); + private final Map userVsHostRegex = new HashMap<>(); + + private final InfraUserRolesLookupStrategy infraUserRolesLookupStrategy = new InfraUserRolesLookupStrategy(); + private final InfraKerberosHostValidator infraKerberosDomainValidator = new InfraKerberosHostValidator(); + + private static class WildCardSupportMap extends HashMap> { + final Set wildcardPrefixes = new HashSet<>(); + + @Override + public List put(String key, List value) { + if (key != null && key.endsWith("/*")) { + key = key.substring(0, key.length() - 2); + wildcardPrefixes.add(key); + } + return super.put(key, value); + } + + @Override + public List get(Object key) { + List result = super.get(key); + if (key == null || result != null) return result; + if (!wildcardPrefixes.isEmpty()) { + for (String s : wildcardPrefixes) { + if (key.toString().startsWith(s)) { + List l = super.get(s); + if (l != null) { + result = result == null ? new ArrayList() : new ArrayList(result); + result.addAll(l); + } + } + } + } + return result; + } + } + + @Override + public AuthorizationResponse authorize(AuthorizationContext context) { + List collectionRequests = context.getCollectionRequests(); + if (context.getRequestType() == AuthorizationContext.RequestType.ADMIN) { + MatchStatus flag = checkCollPerm(mapping.get(null), context); + return flag.rsp; + } + + for (AuthorizationContext.CollectionRequest collreq : collectionRequests) { + //check permissions for each collection + MatchStatus flag = checkCollPerm(mapping.get(collreq.collectionName), context); + if (flag != MatchStatus.NO_PERMISSIONS_FOUND) return flag.rsp; + } + //check wildcard (all=*) permissions. + MatchStatus flag = checkCollPerm(mapping.get("*"), context); + return flag.rsp; + } + + private MatchStatus checkCollPerm(Map> pathVsPerms, + AuthorizationContext context) { + if (pathVsPerms == null) return MatchStatus.NO_PERMISSIONS_FOUND; + + String path = context.getResource(); + MatchStatus flag = checkPathPerm(pathVsPerms.get(path), context); + if (flag != MatchStatus.NO_PERMISSIONS_FOUND) return flag; + return checkPathPerm(pathVsPerms.get(null), context); + } + + private MatchStatus checkPathPerm(List permissions, AuthorizationContext context) { + if (permissions == null || permissions.isEmpty()) return MatchStatus.NO_PERMISSIONS_FOUND; + Principal principal = context.getUserPrincipal(); + loopPermissions: + for (int i = 0; i < permissions.size(); i++) { + Permission permission = permissions.get(i); + if (permission.method != null && !permission.method.contains(context.getHttpMethod())) { + //this permissions HTTP method does not match this rule. try other rules + continue; + } + if(permission.predicate != null){ + if(!permission.predicate.test(context)) continue ; + } + + if (permission.params != null) { + for (Map.Entry e : permission.params.entrySet()) { + String paramVal = context.getParams().get(e.getKey()); + Object val = e.getValue(); + if (val instanceof List) { + if (!((List) val).contains(paramVal)) continue loopPermissions; + } else if (!Objects.equals(val, paramVal)) continue loopPermissions; + } + } + + if (permission.role == null) { + //no role is assigned permission.That means everybody is allowed to access + return MatchStatus.PERMITTED; + } + if (principal == null) { + log.info("request has come without principal. failed permission {} ",permission); + //this resource needs a principal but the request has come without + //any credential. + return MatchStatus.USER_REQUIRED; + } else if (permission.role.contains("*")) { + return MatchStatus.PERMITTED; + } + + for (String role : permission.role) { + Set userRoles = infraUserRolesLookupStrategy.getUserRolesFromPrincipal(usersVsRoles, principal); + boolean validHostname = infraKerberosDomainValidator.validate(principal, userVsHosts, userVsHostRegex); + if (!validHostname) { + log.warn("Hostname is not valid for principal {}", principal); + return MatchStatus.FORBIDDEN; + } + if (userRoles != null && userRoles.contains(role)) return MatchStatus.PERMITTED; + } + log.info("This resource is configured to have a permission {}, The principal {} does not have the right role ", permission, principal); + return MatchStatus.FORBIDDEN; + } + log.debug("No permissions configured for the resource {} . So allowed to access", context.getResource()); + return MatchStatus.NO_PERMISSIONS_FOUND; + } + + @Override + public void init(Map initInfo) { + mapping.put(null, new WildCardSupportMap()); + Map map = getMapValue(initInfo, "user-role"); + for (Object o : map.entrySet()) { + Map.Entry e = (Map.Entry) o; + String roleName = (String) e.getKey(); + usersVsRoles.put(roleName, readValueAsSet(map, roleName)); + } + List perms = getListValue(initInfo, "permissions"); + for (Map o : perms) { + Permission p; + try { + p = Permission.load(o); + } catch (Exception exp) { + log.error("Invalid permission ", exp); + continue; + } + permissions.add(p); + add2Mapping(p); + } + // adding user-host + Map userHostsMap = getMapValue(initInfo, "user-host"); + for (Object userHost : userHostsMap.entrySet()) { + Map.Entry e = (Map.Entry) userHost; + String roleName = (String) e.getKey(); + userVsHosts.put(roleName, readValueAsSet(userHostsMap, roleName)); + } + // adding user-host-regex + Map userHostRegexMap = getMapValue(initInfo, "user-host-regex"); + for (Map.Entry entry : userHostRegexMap.entrySet()) { + userVsHostRegex.put(entry.getKey(), entry.getValue().toString()); + } + + } + + //this is to do optimized lookup of permissions for a given collection/path + private void add2Mapping(Permission permission) { + for (String c : permission.collections) { + WildCardSupportMap m = mapping.get(c); + if (m == null) mapping.put(c, m = new WildCardSupportMap()); + for (String path : permission.path) { + List perms = m.get(path); + if (perms == null) m.put(path, perms = new ArrayList<>()); + perms.add(permission); + } + } + } + + /** + * read a key value as a set. if the value is a single string , + * return a singleton set + * + * @param m the map from which to lookup + * @param key the key with which to do lookup + */ + static Set readValueAsSet(Map m, String key) { + Set result = new HashSet<>(); + Object val = m.get(key); + if (val == null) { + if("collection".equals(key)){ + //for collection collection: null means a core admin/ collection admin request + // otherwise it means a request where collection name is ignored + return m.containsKey(key) ? singleton((String) null) : singleton("*"); + } + return null; + } + if (val instanceof Collection) { + Collection list = (Collection) val; + for (Object o : list) result.add(String.valueOf(o)); + } else if (val instanceof String) { + result.add((String) val); + } else { + throw new RuntimeException("Bad value for : " + key); + } + return result.isEmpty() ? null : Collections.unmodifiableSet(result); + } + + @Override + public void close() throws IOException { } + + static class Permission { + String name; + Set path, role, collections, method; + Map params; + Predicate predicate; + Map originalConfig; + + private Permission() { + } + + static Permission load(Map m) { + Permission p = new Permission(); + p.originalConfig = new LinkedHashMap<>(m); + String name = (String) m.get(NAME); + if (!m.containsKey("role")) throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "role not specified"); + p.role = readValueAsSet(m, "role"); + if (well_known_permissions.containsKey(name)) { + HashSet disAllowed = new HashSet<>(knownKeys); + disAllowed.remove("role");//these are the only + disAllowed.remove(NAME);//allowed keys for well-known permissions + for (String s : disAllowed) { + if (m.containsKey(s)) + throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, s + " is not a valid key for the permission : " + name); + } + p.predicate = (Predicate) ((Map) well_known_permissions.get(name)).get(Predicate.class.getName()); + m = well_known_permissions.get(name); + } + p.name = name; + p.path = readSetSmart(name, m, "path"); + p.collections = readSetSmart(name, m, "collection"); + p.method = readSetSmart(name, m, "method"); + p.params = (Map) m.get("params"); + return p; + } + + @Override + public String toString() { + return Utils.toJSONString(originalConfig); + } + + static final Set knownKeys = ImmutableSet.of("collection", "role", "params", "path", "method", NAME); + } + + enum MatchStatus { + USER_REQUIRED(AuthorizationResponse.PROMPT), + NO_PERMISSIONS_FOUND(AuthorizationResponse.OK), + PERMITTED(AuthorizationResponse.OK), + FORBIDDEN(AuthorizationResponse.FORBIDDEN); + + final AuthorizationResponse rsp; + + MatchStatus(AuthorizationResponse rsp) { + this.rsp = rsp; + } + } + + /** + * This checks for the defaults available other rules for the keys + */ + private static Set readSetSmart(String permissionName, Map m, String key) { + Set set = readValueAsSet(m, key); + if (set == null && well_known_permissions.containsKey(permissionName)) { + set = readValueAsSet((Map) well_known_permissions.get(permissionName), key); + } + if ("method".equals(key)) { + if (set != null) { + for (String s : set) if (!HTTP_METHODS.contains(s)) return null; + } + return set; + } + return set == null ? singleton((String)null) : set; + } + + @Override + public Map edit(Map latestConf, List commands) { + for (CommandOperation op : commands) { + OPERATION operation = null; + for (OPERATION o : OPERATION.values()) { + if (o.name.equals(op.name)) { + operation = o; + break; + } + } + if (operation == null) { + op.unknownOperation(); + return null; + } + latestConf = operation.edit(latestConf, op); + if (latestConf == null) return null; + + } + return latestConf; + } + + enum OPERATION { + SET_USER_ROLE("set-user-role") { + @Override + public Map edit(Map latestConf, CommandOperation op) { + Map roleMap = getMapValue(latestConf, "user-role"); + Map map = op.getDataMap(); + if (op.hasError()) return null; + for (Map.Entry e : map.entrySet()) { + if (e.getValue() == null) { + roleMap.remove(e.getKey()); + continue; + } + if (e.getValue() instanceof String || e.getValue() instanceof List) { + roleMap.put(e.getKey(), e.getValue()); + } else { + op.addError("Unexpected value "); + return null; + } + } + return latestConf; + } + }, + SET_PERMISSION("set-permission") { + @Override + public Map edit(Map latestConf, CommandOperation op) { + String name = op.getStr(NAME); + Map dataMap = op.getDataMap(); + if (op.hasError()) return null; + dataMap = getDeepCopy(dataMap, 3); + String before = (String) dataMap.remove("before"); + for (String key : dataMap.keySet()) { + if (!Permission.knownKeys.contains(key)) op.addError("Unknown key, " + key); + } + try { + Permission.load(dataMap); + } catch (Exception e) { + op.addError(e.getMessage()); + return null; + } + List permissions = getListValue(latestConf, "permissions"); + List permissionsCopy = new ArrayList<>(); + boolean added = false; + for (Map e : permissions) { + Object n = e.get(NAME); + if (n.equals(before) || n.equals(name)) { + added = true; + permissionsCopy.add(dataMap); + } + if (!n.equals(name)) permissionsCopy.add(e); + } + if (!added && before != null) { + op.addError("Invalid 'before' :" + before); + return null; + } + if (!added) permissionsCopy.add(dataMap); + latestConf.put("permissions", permissionsCopy); + return latestConf; + } + }, + UPDATE_PERMISSION("update-permission") { + @Override + public Map edit(Map latestConf, CommandOperation op) { + String name = op.getStr(NAME); + if (op.hasError()) return null; + for (Map permission : (List) getListValue(latestConf, "permissions")) { + if (name.equals(permission.get(NAME))) { + LinkedHashMap copy = new LinkedHashMap<>(permission); + copy.putAll(op.getDataMap()); + op.setCommandData(copy); + return SET_PERMISSION.edit(latestConf, op); + } + } + op.addError("No such permission " + name); + return null; + } + }, + DELETE_PERMISSION("delete-permission") { + @Override + public Map edit(Map latestConf, CommandOperation op) { + List names = op.getStrs(""); + if (names == null || names.isEmpty()) { + op.addError("Invalid command"); + return null; + } + names = new ArrayList<>(names); + List copy = new ArrayList<>(); + List p = getListValue(latestConf, "permissions"); + for (Map map : p) { + Object n = map.get(NAME); + if (names.contains(n)) { + names.remove(n); + continue; + } else { + copy.add(map); + } + } + if (!names.isEmpty()) { + op.addError("Unknown permission name(s) " + names); + return null; + } + latestConf.put("permissions", copy); + return latestConf; + } + }; + + public abstract Map edit(Map latestConf, CommandOperation op); + + public final String name; + + OPERATION(String s) { + this.name = s; + } + + public static OPERATION get(String name) { + for (OPERATION o : values()) if (o.name.equals(name)) return o; + return null; + } + } + + public static final Set HTTP_METHODS = ImmutableSet.of("GET", "POST", "DELETE", "PUT", "HEAD"); + + private static final Map> well_known_permissions = (Map) Utils.fromJSONString( + " { " + + " security-edit :{" + + " path:['/admin/authentication','/admin/authorization']," + + " collection:null," + + " method:POST }," + + " security-read :{" + + " path:['/admin/authentication','/admin/authorization']," + + " collection:null," + + " method:GET}," + + " schema-edit :{" + + " method:POST," + + " path:'/schema/*'}," + + " collection-admin-edit :{" + + " collection:null," + + " path:'/admin/collections'}," + + " collection-admin-read :{" + + " collection:null," + + " path:'/admin/collections'}," + + " schema-read :{" + + " method:GET," + + " path:'/schema/*'}," + + " config-read :{" + + " method:GET," + + " path:'/config/*'}," + + " update :{" + + " path:'/update/*'}," + + " read :{" + + " path:['/select', '/get','/browse','/tvrh','/terms','/clustering','/elevate', '/export','/spell','/clustering']}," + + " config-edit:{" + + " method:POST," + + " path:'/config/*'}," + + " all:{collection:['*', null]}" + + "}"); + + static { + ((Map) well_known_permissions.get("collection-admin-edit")).put(Predicate.class.getName(), getCollectionActionPredicate(true)); + ((Map) well_known_permissions.get("collection-admin-read")).put(Predicate.class.getName(), getCollectionActionPredicate(false)); + } + + private static Predicate getCollectionActionPredicate(final boolean isEdit) { + return new Predicate() { + @Override + public boolean test(AuthorizationContext context) { + String action = context.getParams().get("action"); + if (action == null) return false; + CollectionParams.CollectionAction collectionAction = CollectionParams.CollectionAction.get(action); + if (collectionAction == null) return false; + return isEdit ? collectionAction.isWrite : !collectionAction.isWrite; + } + }; + } + + + public static void main(String[] args) { + System.out.println(Utils.toJSONString(well_known_permissions)); + + } + + public interface Predicate { + + boolean test(T t); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/3146a197/ambari-infra/ambari-infra-solr-plugin/src/main/java/org/apache/ambari/infra/security/InfraUserRolesLookupStrategy.java ---------------------------------------------------------------------- diff --git a/ambari-infra/ambari-infra-solr-plugin/src/main/java/org/apache/ambari/infra/security/InfraUserRolesLookupStrategy.java b/ambari-infra/ambari-infra-solr-plugin/src/main/java/org/apache/ambari/infra/security/InfraUserRolesLookupStrategy.java new file mode 100644 index 0000000..a54e4ad --- /dev/null +++ b/ambari-infra/ambari-infra-solr-plugin/src/main/java/org/apache/ambari/infra/security/InfraUserRolesLookupStrategy.java @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF 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.apache.ambari.infra.security; + +import org.apache.commons.collections.CollectionUtils; +import org.apache.hadoop.security.authentication.server.AuthenticationToken; +import org.apache.hadoop.security.authentication.util.KerberosName; + +import java.security.Principal; +import java.util.Map; +import java.util.Set; + + +/** + * Strategy class to get roles with the principal name (in a specific format e.g.: 'name@DOMAIN') + * in case of KerberosPlugin is used for authentication + */ +public class InfraUserRolesLookupStrategy { + + public Set getUserRolesFromPrincipal(Map> usersVsRoles, Principal principal) { + if (principal instanceof AuthenticationToken) { + AuthenticationToken authenticationToken = (AuthenticationToken) principal; + KerberosName kerberosName = new KerberosName(authenticationToken.getName()); + Set rolesResult = usersVsRoles.get(String.format("%s@%s", kerberosName.getServiceName(), kerberosName.getRealm())); + if (CollectionUtils.isEmpty(rolesResult)) { + rolesResult = usersVsRoles.get(principal.getName()); + } + return rolesResult; + } else { + return usersVsRoles.get(principal.getName()); + } + } +}