2020
2121package org .apache .ranger .authorization .ozone .authorizer ;
2222
23+ import org .apache .commons .lang3 .StringUtils ;
24+ import org .apache .hadoop .ozone .om .exceptions .OMException ;
25+ import org .apache .hadoop .ozone .security .acl .AssumeRoleRequest ;
26+ import org .apache .hadoop .ozone .security .acl .AssumeRoleRequest .OzoneGrant ;
2327import org .apache .hadoop .ozone .security .acl .IAccessAuthorizer ;
2428import org .apache .hadoop .ozone .security .acl .IOzoneObj ;
2529import org .apache .hadoop .ozone .security .acl .OzoneObj ;
2630import org .apache .hadoop .ozone .security .acl .RequestContext ;
2731import org .apache .hadoop .security .UserGroupInformation ;
2832import org .apache .hadoop .thirdparty .com .google .common .collect .Sets ;
2933import org .apache .ranger .audit .provider .MiscUtil ;
34+ import org .apache .ranger .authz .util .RangerResourceNameParser ;
3035import org .apache .ranger .plugin .audit .RangerDefaultAuditHandler ;
36+ import org .apache .ranger .plugin .model .RangerInlinePolicy ;
37+ import org .apache .ranger .plugin .model .RangerPrincipal ;
3138import org .apache .ranger .plugin .policyengine .RangerAccessRequestImpl ;
3239import org .apache .ranger .plugin .policyengine .RangerAccessResourceImpl ;
3340import org .apache .ranger .plugin .policyengine .RangerAccessResult ;
3441import org .apache .ranger .plugin .service .RangerBasePlugin ;
42+ import org .apache .ranger .plugin .util .JsonUtilsV2 ;
3543import org .apache .ranger .plugin .util .RangerPerfTracer ;
3644import org .slf4j .Logger ;
3745import org .slf4j .LoggerFactory ;
3846
47+ import java .util .Collections ;
3948import java .util .Date ;
49+ import java .util .HashMap ;
50+ import java .util .List ;
51+ import java .util .Map ;
52+ import java .util .Objects ;
53+ import java .util .Set ;
54+ import java .util .stream .Collectors ;
4055
4156public class RangerOzoneAuthorizer implements IAccessAuthorizer {
42- public static final String ACCESS_TYPE_READ = "read" ;
43- public static final String ACCESS_TYPE_WRITE = "write" ;
44- public static final String ACCESS_TYPE_CREATE = "create" ;
45- public static final String ACCESS_TYPE_LIST = "list" ;
46- public static final String ACCESS_TYPE_DELETE = "delete" ;
47- public static final String ACCESS_TYPE_READ_ACL = "read_acl" ;
48- public static final String ACCESS_TYPE_WRITE_ACL = "write_acl" ;
57+ public static final String ACCESS_TYPE_READ = "read" ;
58+ public static final String ACCESS_TYPE_WRITE = "write" ;
59+ public static final String ACCESS_TYPE_CREATE = "create" ;
60+ public static final String ACCESS_TYPE_LIST = "list" ;
61+ public static final String ACCESS_TYPE_DELETE = "delete" ;
62+ public static final String ACCESS_TYPE_READ_ACL = "read_acl" ;
63+ public static final String ACCESS_TYPE_WRITE_ACL = "write_acl" ;
64+ public static final String ACCESS_TYPE_ASSUME_ROLE = "assume_role" ;
65+ public static final String ACCESS_TYPE_ALL = "all" ;
4966
50-
51- public static final String KEY_RESOURCE_VOLUME = "volume" ;
67+ public static final String KEY_RESOURCE_VOLUME = "volume" ;
5268 public static final String KEY_RESOURCE_BUCKET = "bucket" ;
53- public static final String KEY_RESOURCE_KEY = "key" ;
69+ public static final String KEY_RESOURCE_KEY = "key" ;
70+ public static final String KEY_RESOURCE_ROLE = "role" ;
71+
72+ private static final String S3_VOLUME_NAME = "s3Vol" ;
5473
5574 private static final Logger PERF_OZONEAUTH_REQUEST_LOG = RangerPerfTracer .getPerfLogger ("ozoneauth.request" );
5675
@@ -78,6 +97,10 @@ public RangerOzoneAuthorizer() {
7897 }
7998 }
8099
100+ RangerOzoneAuthorizer (RangerBasePlugin plugin ) {
101+ rangerPlugin = plugin ;
102+ }
103+
81104 @ Override
82105 public boolean checkAccess (IOzoneObj ozoneObject , RequestContext context ) {
83106 boolean returnValue = false ;
@@ -149,11 +172,7 @@ public boolean checkAccess(IOzoneObj ozoneObject, RequestContext context) {
149172 if (ozoneObj .getResourceType () == OzoneObj .ResourceType .VOLUME ) {
150173 rangerResource .setValue (KEY_RESOURCE_VOLUME , ozoneObj .getVolumeName ());
151174 } else if (ozoneObj .getResourceType () == OzoneObj .ResourceType .BUCKET || ozoneObj .getResourceType () == OzoneObj .ResourceType .KEY ) {
152- if (ozoneObj .getStoreType () == OzoneObj .StoreType .S3 ) {
153- rangerResource .setValue (KEY_RESOURCE_VOLUME , "s3Vol" );
154- } else {
155- rangerResource .setValue (KEY_RESOURCE_VOLUME , ozoneObj .getVolumeName ());
156- }
175+ rangerResource .setValue (KEY_RESOURCE_VOLUME , ozoneObj .getStoreType () == OzoneObj .StoreType .S3 ? S3_VOLUME_NAME : ozoneObj .getVolumeName ());
157176 rangerResource .setValue (KEY_RESOURCE_BUCKET , ozoneObj .getBucketName ());
158177 if (ozoneObj .getResourceType () == OzoneObj .ResourceType .KEY ) {
159178 rangerResource .setValue (KEY_RESOURCE_KEY , ozoneObj .getKeyName ());
@@ -166,6 +185,10 @@ public boolean checkAccess(IOzoneObj ozoneObject, RequestContext context) {
166185 }
167186
168187 try {
188+ if (StringUtils .isNotBlank (context .getSessionPolicy ())) {
189+ rangerRequest .setInlinePolicy (JsonUtilsV2 .jsonToObj (context .getSessionPolicy (), RangerInlinePolicy .class ));
190+ }
191+
169192 RangerAccessResult result = plugin
170193 .isAccessAllowed (rangerRequest );
171194 if (result == null ) {
@@ -186,6 +209,61 @@ public boolean checkAccess(IOzoneObj ozoneObject, RequestContext context) {
186209 return returnValue ;
187210 }
188211
212+ @ Override
213+ public String generateAssumeRoleSessionPolicy (AssumeRoleRequest assumeRoleRequest ) throws OMException {
214+ LOG .debug ("==> RangerOzoneAuthorizer.generateAssumeRoleSessionPolicy(assumeRoleRequest={})" , assumeRoleRequest );
215+
216+ if (assumeRoleRequest == null ) {
217+ throw new OMException ("invalid request: null" , OMException .ResultCodes .INVALID_REQUEST );
218+ } else if (assumeRoleRequest .getClientUgi () == null ) {
219+ throw new OMException ("invalid request: request.clientUgi null" , OMException .ResultCodes .INVALID_REQUEST );
220+ } else if (assumeRoleRequest .getTargetRoleName () == null ) {
221+ throw new OMException ("invalid request: request.targetRoleName null" , OMException .ResultCodes .INVALID_REQUEST );
222+ }
223+
224+ RangerBasePlugin plugin = rangerPlugin ;
225+
226+ if (plugin == null ) {
227+ throw new OMException ("Ranger authorizer not initialized" , OMException .ResultCodes .INTERNAL_ERROR );
228+ }
229+
230+ UserGroupInformation ugi = assumeRoleRequest .getClientUgi ();
231+ RangerAccessResourceImpl resource = new RangerAccessResourceImpl (Collections .singletonMap (KEY_RESOURCE_ROLE , assumeRoleRequest .getTargetRoleName ()));
232+ RangerAccessRequestImpl request = new RangerAccessRequestImpl (resource , ACCESS_TYPE_ASSUME_ROLE , ugi .getShortUserName (), Sets .newHashSet (ugi .getGroupNames ()), null );
233+
234+ try {
235+ RangerAccessResult result = plugin .isAccessAllowed (request );
236+
237+ if (result != null && result .getIsAccessDetermined () && result .getIsAllowed ()) {
238+ final Set <OzoneGrant > ozoneGrants = assumeRoleRequest .getGrants ();
239+ final List <RangerInlinePolicy .Grant > inlineGrants ;
240+
241+ if (ozoneGrants == null ) { // allow all permissions
242+ inlineGrants = null ;
243+ } else if (ozoneGrants .isEmpty ()) { // don't allow any permission
244+ inlineGrants = Collections .singletonList (new RangerInlinePolicy .Grant ());
245+ } else { // allow explicitly specified permissions
246+ inlineGrants = ozoneGrants .stream ().map (g -> toRangerGrant (g , plugin )).collect (Collectors .toList ());
247+ }
248+
249+ RangerInlinePolicy inlinePolicy = new RangerInlinePolicy (RangerPrincipal .PREFIX_ROLE + assumeRoleRequest .getTargetRoleName (), RangerInlinePolicy .Mode .INLINE , inlineGrants , ugi .getShortUserName ());
250+ String ret = JsonUtilsV2 .objToJson (inlinePolicy );
251+
252+ LOG .debug ("<== RangerOzoneAuthorizer.generateAssumeRoleSessionPolicy(assumeRoleRequest={}): ret={}" , assumeRoleRequest , ret );
253+
254+ return ret ;
255+ } else {
256+ throw new OMException ("Permission denied" , OMException .ResultCodes .ACCESS_DENIED );
257+ }
258+ } catch (OMException excp ) {
259+ throw excp ;
260+ } catch (Throwable t ) {
261+ LOG .error ("isAccessAllowed() failed. request = {}" , request , t );
262+
263+ throw new OMException ("Ranger authorizer failed" , t , OMException .ResultCodes .INTERNAL_ERROR );
264+ }
265+ }
266+
189267 private String mapToRangerAccessType (ACLType operation ) {
190268 String rangerAccessType = null ;
191269 switch (operation ) {
@@ -213,5 +291,84 @@ private String mapToRangerAccessType(ACLType operation) {
213291 }
214292 return rangerAccessType ;
215293 }
294+
295+ private static RangerInlinePolicy .Grant toRangerGrant (OzoneGrant ozoneGrant , RangerBasePlugin plugin ) {
296+ RangerInlinePolicy .Grant ret = new RangerInlinePolicy .Grant ();
297+
298+ if (ozoneGrant .getObjects () != null ) {
299+ ret .setResources (ozoneGrant .getObjects ().stream ().map (o -> toRrn (o , plugin )).filter (Objects ::nonNull ).collect (Collectors .toSet ()));
300+ }
301+
302+ if (ozoneGrant .getPermissions () != null ) {
303+ ret .setPermissions (ozoneGrant .getPermissions ().stream ().map (RangerOzoneAuthorizer ::toRangerPermission ).filter (Objects ::nonNull ).collect (Collectors .toSet ()));
304+ }
305+
306+ LOG .debug ("toRangerGrant(ozoneGrant={}): ret={}" , ozoneGrant , ret );
307+
308+ return ret ;
309+ }
310+
311+ private static String toRrn (IOzoneObj obj , RangerBasePlugin plugin ) {
312+ OzoneObj ozoneObj = (OzoneObj ) obj ;
313+ Map <String , String > resource = new HashMap <>();
314+ String resType = null ;
315+
316+ switch (ozoneObj .getResourceType ()) {
317+ case VOLUME :
318+ resType = KEY_RESOURCE_VOLUME ;
319+
320+ resource .put (KEY_RESOURCE_VOLUME , ozoneObj .getVolumeName ());
321+ break ;
322+
323+ case BUCKET :
324+ resType = KEY_RESOURCE_BUCKET ;
325+
326+ resource .put (KEY_RESOURCE_VOLUME , ozoneObj .getStoreType () == OzoneObj .StoreType .S3 ? S3_VOLUME_NAME : ozoneObj .getVolumeName ());
327+ resource .put (KEY_RESOURCE_BUCKET , ozoneObj .getBucketName ());
328+ break ;
329+
330+ case KEY :
331+ resType = KEY_RESOURCE_KEY ;
332+
333+ resource .put (KEY_RESOURCE_VOLUME , ozoneObj .getStoreType () == OzoneObj .StoreType .S3 ? S3_VOLUME_NAME : ozoneObj .getVolumeName ());
334+ resource .put (KEY_RESOURCE_BUCKET , ozoneObj .getBucketName ());
335+ resource .put (KEY_RESOURCE_KEY , ozoneObj .getKeyName ());
336+ break ;
337+ }
338+
339+ RangerResourceNameParser rrnParser = resType != null ? plugin .getServiceDefHelper ().getRrnParser (resType ) : null ;
340+ String ret = rrnParser != null ? (resType + RangerResourceNameParser .RRN_RESOURCE_TYPE_SEP + rrnParser .toResourceName (resource )) : null ;
341+
342+ LOG .debug ("toRrn(ozoneObj={}): ret={}" , ozoneObj , ret );
343+
344+ return ret ;
345+ }
346+
347+
348+ private static String toRangerPermission (ACLType acl ) {
349+ switch (acl ) {
350+ case READ :
351+ return ACCESS_TYPE_READ ;
352+ case WRITE :
353+ return ACCESS_TYPE_WRITE ;
354+ case CREATE :
355+ return ACCESS_TYPE_CREATE ;
356+ case LIST :
357+ return ACCESS_TYPE_LIST ;
358+ case DELETE :
359+ return ACCESS_TYPE_DELETE ;
360+ case READ_ACL :
361+ return ACCESS_TYPE_READ_ACL ;
362+ case WRITE_ACL :
363+ return ACCESS_TYPE_WRITE_ACL ;
364+ case ALL :
365+ return ACCESS_TYPE_ALL ;
366+ case NONE :
367+ case ASSUME_ROLE : // ASSUME_ROLE is not supported in session policy
368+ return null ;
369+ }
370+
371+ return null ;
372+ }
216373}
217374
0 commit comments