44import com .fasterxml .jackson .core .JsonProcessingException ;
55import com .fasterxml .jackson .databind .DeserializationFeature ;
66import com .fasterxml .jackson .databind .ObjectMapper ;
7+ import java .io .IOException ;
78import java .net .URI ;
89import java .net .http .HttpClient ;
910import java .net .http .HttpRequest ;
1011import java .net .http .HttpResponse ;
11- import java .util .HashMap ;
1212import java .util .List ;
13- import java .util .Map ;
1413import java .util .Objects ;
15-
16- import com .fasterxml .jackson .databind .type .TypeFactory ;
1714import org .apache .hadoop .conf .Configuration ;
1815import org .apache .hadoop .security .GroupMappingServiceProvider ;
16+ import org .apache .hadoop .security .UserGroupInformation ;
1917import org .slf4j .Logger ;
2018import org .slf4j .LoggerFactory ;
2119
2220public class StackableGroupMapper implements GroupMappingServiceProvider {
2321
24- private static final Logger LOG = LoggerFactory .getLogger (StackableGroupMapper .class );
25-
2622 public static final String OPA_MAPPING_URL_PROP = "hadoop.security.group.mapping.opa.policy.url" ;
27- // response base field: see https://www.openpolicyagent.org/docs/latest/rest-api/#response-message
28- private static final String OPA_RESULT_FIELD = "result" ;
29-
23+ private static final Logger LOG = LoggerFactory .getLogger (StackableGroupMapper .class );
3024 private final HttpClient httpClient = HttpClient .newHttpClient ();
3125 private final ObjectMapper json ;
3226 private URI opaUri ;
@@ -59,21 +53,36 @@ public StackableGroupMapper() {
5953 .setSerializationInclusion (JsonInclude .Include .NON_NULL );
6054 }
6155
62- private static class OpaQueryResult {
63- public List <String > result ;
64- }
65-
6656 /**
67- * Returns list of groups for a user.
57+ * Returns list of groups for a user. Internally Hadoop will pass the short name to this function,
58+ * but this prevents us from effectively separating users with the same names but with different
59+ * kerberos principals. For this reason the user name is extracted from the UserGroupInformation
60+ * instead (giving us the full name), defaulting to the original name if this is not possible.
6861 *
69- * @param user get groups for this user
62+ * @param user get groups from the associated user group information for this user
7063 * @return list of groups for a given user
7164 */
7265 @ Override
7366 public List <String > getGroups (String user ) {
7467 LOG .info ("Calling StackableGroupMapper.getGroups for user \" {}\" " , user );
7568
76- OpaGroupsQuery query = new OpaGroupsQuery (new OpaGroupsQuery .OpaGroupsQueryInput (user ));
69+ String workingUser = user ;
70+ try {
71+ UserGroupInformation currentUser = UserGroupInformation .getCurrentUser ();
72+ LOG .debug (
73+ "Current user [{}] with user-name [{}] and short-name [{}]" ,
74+ currentUser ,
75+ currentUser .getUserName (),
76+ currentUser .getShortUserName ());
77+ workingUser = currentUser .getUserName ();
78+ } catch (IOException e ) {
79+ LOG .warn (
80+ "Unable to extract name from UserGroupInformation, defaulting to \" {}\" : {}" ,
81+ user ,
82+ e .getMessage ());
83+ }
84+
85+ OpaGroupsQuery query = new OpaGroupsQuery (new OpaGroupsQuery .OpaGroupsQueryInput (workingUser ));
7786
7887 String body ;
7988 try {
@@ -115,7 +124,7 @@ public List<String> getGroups(String user) {
115124 }
116125 List <String > groups = result .result ;
117126
118- LOG .debug ("Groups for \" {}\" : {}" , user , groups );
127+ LOG .debug ("Groups for \" {}\" : {}" , workingUser , groups );
119128
120129 return groups ;
121130 }
@@ -139,4 +148,8 @@ public void cacheGroupsAdd(List<String> groups) {
139148 "ignoring cacheGroupsAdd for groups [{}]: caching should be provided by the policy provider" ,
140149 groups );
141150 }
151+
152+ private static class OpaQueryResult {
153+ public List <String > result ;
154+ }
142155}
0 commit comments