fmorg-git commented on code in PR #11134:
URL: https://github.com/apache/ozone/pull/11134#discussion_r3920638149
##########
hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/security/S3AssumeRoleRequest.java:
##########
@@ -274,13 +298,134 @@ String getSessionPolicy(OzoneManager ozoneManager,
String originalAccessKeyId, S
final Set<OzoneGrant> grants = Strings.isNullOrEmpty(awsIamPolicy) ?
null :
- IamSessionPolicyResolver.resolve(awsIamPolicy, volumeName,
IamSessionPolicyResolver.AuthorizerType.RANGER);
+ resolveGrantsAgainstBucketLinks(
+ IamSessionPolicyResolver.resolve(awsIamPolicy, volumeName,
IamSessionPolicyResolver.AuthorizerType.RANGER),
+ (linkVolume, linkBucket) ->
ozoneManager.resolveBucketLink(Pair.of(linkVolume, linkBucket), true, false));
return ozoneManager.getAccessAuthorizer().generateAssumeRoleSessionPolicy(
new org.apache.hadoop.ozone.security.acl.AssumeRoleRequest(
hostName, remoteIp, ugi, targetRoleName, grants));
}
+ /**
+ * Rewrites the resolved session-policy grants so that any bucket, key, or
prefix resource that names a
+ * bucket link is anchored to the link's source volume and bucket - the
resource paths the OM authorizes
+ * against once the link is resolved at request time. READ on each link
bucket in the chain (and, when the
+ * chain crosses volumes, READ on each distinct volume except the requested
one) is retained so OM can follow
+ * every hop at request time, which keeps the generated token as small as
possible.
+ * <p>
+ * The link target is resolved when the token is generated, so the token
grants access to whatever the link
+ * points to at that moment. If the link is later re-pointed, the token no
longer grants access to the new
+ * target.
+ *
+ * @param grants the grants produced by {@link
IamSessionPolicyResolver}, possibly {@code null}
+ * @param linkResolver resolves a (volume, bucket) pair to its link target
+ * @return the link-aware grants, or the input unchanged when there is
nothing to resolve
+ */
+ @VisibleForTesting
+ static Set<OzoneGrant> resolveGrantsAgainstBucketLinks(Set<OzoneGrant>
grants,
+ BucketLinkResolver linkResolver) throws IOException {
+ if (grants == null || grants.isEmpty()) {
+ return grants;
+ }
+
+ final Map<Pair<String, String>, ResolvedBucket> resolutionCache = new
HashMap<>();
+ final Set<IOzoneObj> linkFollowObjects = new LinkedHashSet<>();
+ final Set<OzoneGrant> resolvedGrants = new LinkedHashSet<>();
+
+ for (OzoneGrant grant : grants) {
+ final Set<IOzoneObj> resolvedObjects = new LinkedHashSet<>();
+ for (IOzoneObj object : grant.getObjects()) {
+ resolvedObjects.add(
+ resolveObjectAgainstBucketLink((OzoneObj) object, linkResolver,
resolutionCache, linkFollowObjects));
+ }
+ resolvedGrants.add(new OzoneGrant(resolvedObjects,
grant.getPermissions(), grant.getS3Actions()));
+ }
+
+ // Retain only the READ required to follow each link hop at request time.
+ if (!linkFollowObjects.isEmpty()) {
+ resolvedGrants.add(new OzoneGrant(linkFollowObjects,
EnumSet.of(ACLType.READ)));
+ }
+
+ return resolvedGrants;
+ }
+
+ /**
+ * Resolves a single grant object against its bucket link. Bucket, key, and
prefix objects that name a
+ * link bucket are rewritten to the link's source volume and bucket, and the
READ needed to follow each hop
+ * in the link chain is collected in {@code linkFollowObjects}. All other
objects (volume resources and
+ * wildcard buckets) are returned unchanged.
+ */
+ private static IOzoneObj resolveObjectAgainstBucketLink(OzoneObj object,
BucketLinkResolver linkResolver,
+ Map<Pair<String, String>, ResolvedBucket> resolutionCache,
Set<IOzoneObj> linkFollowObjects)
+ throws IOException {
+ final OzoneObj.ResourceType resourceType = object.getResourceType();
+ if (resourceType != OzoneObj.ResourceType.BUCKET
+ && resourceType != OzoneObj.ResourceType.KEY
+ && resourceType != OzoneObj.ResourceType.PREFIX) {
+ return object;
+ }
+
+ final String volumeName = object.getVolumeName();
+ final String bucketName = object.getBucketName();
+ // Wildcard or unspecified names cannot correspond to a concrete link
bucket.
+ if (StringUtils.isBlank(volumeName) || StringUtils.isBlank(bucketName) ||
hasWildcard(volumeName) ||
+ hasWildcard(bucketName)) {
+ return object;
+ }
+
+ final Pair<String, String> requested = Pair.of(volumeName, bucketName);
+ ResolvedBucket resolved = resolutionCache.get(requested);
+ if (resolved == null) {
+ resolved = linkResolver.resolve(volumeName, bucketName);
+ resolutionCache.put(requested, resolved);
+ }
Review Comment:
this doesn't appear to be a valid issue today
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]