Skip to content

Commit 0b10b48

Browse files
fmorg-gitFabian Morgan
authored andcommitted
HDDS-13848. [STS] Artifacts for Ranger to authorize STS token (#9214)
(cherry picked from commit 281a5b3)
1 parent 51deb3c commit 0b10b48

File tree

8 files changed

+337
-8
lines changed

8 files changed

+337
-8
lines changed

hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/OzoneConsts.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ public final class OzoneConsts {
6565
public static final String OZONE_ACL_CREATE = "c";
6666
public static final String OZONE_ACL_READ_ACL = "x";
6767
public static final String OZONE_ACL_WRITE_ACL = "y";
68+
public static final String OZONE_ACL_ASSUME_ROLE = "m";
6869

6970
public static final String OZONE_DATE_FORMAT =
7071
"EEE, dd MMM yyyy HH:mm:ss zzz";
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.hadoop.ozone.security.acl;
19+
20+
import java.net.InetAddress;
21+
import java.util.Objects;
22+
import java.util.Set;
23+
import net.jcip.annotations.Immutable;
24+
import org.apache.hadoop.security.UserGroupInformation;
25+
26+
/**
27+
* Represents an S3 AssumeRole request that needs to be authorized by an IAccessAuthorizer.
28+
* The grants parameter can be null if the access must not be limited beyond the role.
29+
* Note that if the grants parameter is the empty set, this means the access should
30+
* be the intersection of the role and the empty set, meaning no access will be granted.
31+
*/
32+
@Immutable
33+
public class AssumeRoleRequest {
34+
private final String host;
35+
private final InetAddress ip;
36+
private final UserGroupInformation clientUgi;
37+
private final String targetRoleName;
38+
private final Set<OzoneGrant> grants;
39+
40+
public AssumeRoleRequest(String host, InetAddress ip, UserGroupInformation clientUgi, String targetRoleName,
41+
Set<OzoneGrant> grants) {
42+
43+
this.host = host;
44+
this.ip = ip;
45+
this.clientUgi = clientUgi;
46+
this.targetRoleName = targetRoleName;
47+
this.grants = grants;
48+
}
49+
50+
public String getHost() {
51+
return host;
52+
}
53+
54+
public InetAddress getIp() {
55+
return ip;
56+
}
57+
58+
public UserGroupInformation getClientUgi() {
59+
return clientUgi;
60+
}
61+
62+
public String getTargetRoleName() {
63+
return targetRoleName;
64+
}
65+
66+
public Set<OzoneGrant> getGrants() {
67+
return grants;
68+
}
69+
70+
@Override
71+
public boolean equals(Object o) {
72+
if (this == o) {
73+
return true;
74+
} else if (o == null || getClass() != o.getClass()) {
75+
return false;
76+
}
77+
78+
final AssumeRoleRequest that = (AssumeRoleRequest) o;
79+
return Objects.equals(host, that.host) && Objects.equals(ip, that.ip) &&
80+
Objects.equals(clientUgi, that.clientUgi) && Objects.equals(targetRoleName, that.targetRoleName) &&
81+
Objects.equals(grants, that.grants);
82+
}
83+
84+
@Override
85+
public int hashCode() {
86+
return Objects.hash(host, ip, clientUgi, targetRoleName, grants);
87+
}
88+
89+
/**
90+
* Encapsulates the IOzoneObj and associated permissions.
91+
*/
92+
@Immutable
93+
public static class OzoneGrant {
94+
private final Set<IOzoneObj> objects;
95+
private final Set<IAccessAuthorizer.ACLType> permissions;
96+
97+
public OzoneGrant(Set<IOzoneObj> objects, Set<IAccessAuthorizer.ACLType> permissions) {
98+
this.objects = objects;
99+
this.permissions = permissions;
100+
}
101+
102+
public Set<IOzoneObj> getObjects() {
103+
return objects;
104+
}
105+
106+
public Set<IAccessAuthorizer.ACLType> getPermissions() {
107+
return permissions;
108+
}
109+
110+
@Override
111+
public boolean equals(Object o) {
112+
if (this == o) {
113+
return true;
114+
} else if (o == null || getClass() != o.getClass()) {
115+
return false;
116+
}
117+
118+
final OzoneGrant that = (OzoneGrant) o;
119+
return Objects.equals(objects, that.objects) && Objects.equals(permissions, that.permissions);
120+
}
121+
122+
@Override
123+
public int hashCode() {
124+
return Objects.hash(objects, permissions);
125+
}
126+
}
127+
}

hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/acl/IAccessAuthorizer.java

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
package org.apache.hadoop.ozone.security.acl;
1919

20+
import static org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes.NOT_SUPPORTED_OPERATION;
21+
2022
import java.util.Arrays;
2123
import java.util.BitSet;
2224
import java.util.Collections;
@@ -48,6 +50,25 @@ public interface IAccessAuthorizer {
4850
boolean checkAccess(IOzoneObj ozoneObject, RequestContext context)
4951
throws OMException;
5052

53+
/**
54+
* Attempts to authorize an STS AssumeRole request. If authorized, returns a String
55+
* representation of the authorized session policy. This return value must be supplied on the subsequent
56+
* {@link IAccessAuthorizer#checkAccess(IOzoneObj, RequestContext)} call, using the
57+
* {@link RequestContext.Builder#setSessionPolicy(String)} parameter, and the authorizer will
58+
* use the Role permissions and the session policy permissions to determine if
59+
* the attempted action should be allowed for the given STS token.
60+
* <p>
61+
* The user making this call must have the {@link ACLType#ASSUME_ROLE} permission.
62+
*
63+
* @param assumeRoleRequest the AssumeRole request containing role and optional limited scope policy grants
64+
* @return a String representing the permissions granted according to the authorizer.
65+
* @throws OMException if the caller is not authorized, either for the role and/or policy or for the
66+
* {@link ACLType#ASSUME_ROLE} permission
67+
*/
68+
default String generateAssumeRoleSessionPolicy(AssumeRoleRequest assumeRoleRequest) throws OMException {
69+
throw new OMException("The generateAssumeRoleSessionPolicy call is not supported", NOT_SUPPORTED_OPERATION);
70+
}
71+
5172
/**
5273
* @return true for Ozone-native authorizer
5374
*/
@@ -67,7 +88,9 @@ enum ACLType {
6788
READ_ACL,
6889
WRITE_ACL,
6990
ALL,
70-
NONE;
91+
NONE,
92+
ASSUME_ROLE; // ability to create STS tokens
93+
7194
private static int length = ACLType.values().length;
7295
static {
7396
if (length > 16) {
@@ -121,6 +144,8 @@ public static ACLType getACLRight(String type) {
121144
return ACLType.ALL;
122145
case OzoneConsts.OZONE_ACL_NONE:
123146
return ACLType.NONE;
147+
case OzoneConsts.OZONE_ACL_ASSUME_ROLE:
148+
return ACLType.ASSUME_ROLE;
124149
default:
125150
throw new IllegalArgumentException("[" + type + "] ACL right is not " +
126151
"recognized");
@@ -161,6 +186,8 @@ public static String getAclString(ACLType acl) {
161186
return OzoneConsts.OZONE_ACL_ALL;
162187
case NONE:
163188
return OzoneConsts.OZONE_ACL_NONE;
189+
case ASSUME_ROLE:
190+
return OzoneConsts.OZONE_ACL_ASSUME_ROLE;
164191
default:
165192
throw new IllegalArgumentException("ACL right is not recognized");
166193
}

hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/acl/OzoneObj.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import com.google.common.base.Preconditions;
2323
import java.util.LinkedHashMap;
2424
import java.util.Map;
25+
import java.util.Objects;
2526
import org.apache.hadoop.ozone.OzoneConsts;
2627
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
2728
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos.OzoneObj.ObjectType;
@@ -146,4 +147,20 @@ public Map<String, String> toAuditMap() {
146147
return auditMap;
147148
}
148149

150+
@Override
151+
public boolean equals(Object o) {
152+
if (this == o) {
153+
return true;
154+
} else if (o == null || getClass() != o.getClass()) {
155+
return false;
156+
}
157+
158+
final OzoneObj that = (OzoneObj) o;
159+
return resType == that.resType && storeType == that.storeType;
160+
}
161+
162+
@Override
163+
public int hashCode() {
164+
return Objects.hash(resType, storeType);
165+
}
149166
}

hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/acl/OzoneObjInfo.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import static org.apache.hadoop.ozone.OzoneConsts.OZONE_URI_DELIMITER;
2121

22+
import java.util.Objects;
2223
import org.apache.commons.lang3.StringUtils;
2324
import org.apache.hadoop.ozone.om.helpers.OmKeyArgs;
2425
import org.apache.hadoop.ozone.protocol.proto.OzoneManagerProtocolProtos;
@@ -237,4 +238,22 @@ public OzoneObjInfo build() {
237238
name, ozonePrefixPath);
238239
}
239240
}
241+
242+
@Override
243+
public boolean equals(Object o) {
244+
if (this == o) {
245+
return true;
246+
} else if (!super.equals(o)) {
247+
return false;
248+
}
249+
250+
final OzoneObjInfo that = (OzoneObjInfo) o;
251+
return Objects.equals(volumeName, that.volumeName) && Objects.equals(bucketName, that.bucketName) &&
252+
Objects.equals(name, that.name) && Objects.equals(ozonePrefixPath, that.ozonePrefixPath);
253+
}
254+
255+
@Override
256+
public int hashCode() {
257+
return Objects.hash(super.hashCode(), volumeName, bucketName, name, ozonePrefixPath);
258+
}
240259
}

hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/security/acl/RequestContext.java

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,20 +43,36 @@ public class RequestContext {
4343
*/
4444
private final boolean recursiveAccessCheck;
4545

46+
/**
47+
* Represents optional session policy JSON for Ranger to use when authorizing
48+
* an STS token. This value would have come as a result of a previous
49+
* {@link IAccessAuthorizer#generateAssumeRoleSessionPolicy(AssumeRoleRequest)} call.
50+
* The sessionPolicy includes the roleName.
51+
*/
52+
private final String sessionPolicy;
53+
4654
@SuppressWarnings("parameternumber")
4755
public RequestContext(String host, InetAddress ip,
4856
UserGroupInformation clientUgi, String serviceId,
4957
ACLIdentityType aclType, ACLType aclRights,
5058
String ownerName) {
5159
this(host, ip, clientUgi, serviceId, aclType, aclRights, ownerName,
52-
false);
60+
false, null);
5361
}
5462

5563
@SuppressWarnings("parameternumber")
5664
public RequestContext(String host, InetAddress ip,
5765
UserGroupInformation clientUgi, String serviceId,
5866
ACLIdentityType aclType, ACLType aclRights,
5967
String ownerName, boolean recursiveAccessCheck) {
68+
this(host, ip, clientUgi, serviceId, aclType, aclRights, ownerName,
69+
recursiveAccessCheck, null);
70+
}
71+
72+
@SuppressWarnings("parameternumber")
73+
public RequestContext(String host, InetAddress ip, UserGroupInformation clientUgi, String serviceId,
74+
ACLIdentityType aclType, ACLType aclRights, String ownerName, boolean recursiveAccessCheck,
75+
String sessionPolicy) {
6076
this.host = host;
6177
this.ip = ip;
6278
this.clientUgi = clientUgi;
@@ -65,6 +81,7 @@ public RequestContext(String host, InetAddress ip,
6581
this.aclRights = aclRights;
6682
this.ownerName = ownerName;
6783
this.recursiveAccessCheck = recursiveAccessCheck;
84+
this.sessionPolicy = sessionPolicy;
6885
}
6986

7087
/**
@@ -85,6 +102,7 @@ public static class Builder {
85102
private String ownerName;
86103

87104
private boolean recursiveAccessCheck;
105+
private String sessionPolicy;
88106

89107
public Builder setHost(String bHost) {
90108
this.host = bHost;
@@ -130,9 +148,14 @@ public Builder setRecursiveAccessCheck(boolean recursiveAccessCheckFlag) {
130148
return this;
131149
}
132150

151+
public Builder setSessionPolicy(String sessionPolicy) {
152+
this.sessionPolicy = sessionPolicy;
153+
return this;
154+
}
155+
133156
public RequestContext build() {
134157
return new RequestContext(host, ip, clientUgi, serviceId, aclType,
135-
aclRights, ownerName, recursiveAccessCheck);
158+
aclRights, ownerName, recursiveAccessCheck, sessionPolicy);
136159
}
137160
}
138161

@@ -144,21 +167,26 @@ public static RequestContext.Builder getBuilder(
144167
UserGroupInformation ugi, InetAddress remoteAddress, String hostName,
145168
ACLType aclType, String ownerName) {
146169
return getBuilder(ugi, remoteAddress, hostName, aclType, ownerName,
147-
false);
170+
false);
148171
}
149172

150173
public static RequestContext.Builder getBuilder(
151174
UserGroupInformation ugi, InetAddress remoteAddress, String hostName,
152175
ACLType aclType, String ownerName, boolean recursiveAccessCheck) {
153-
RequestContext.Builder contextBuilder = RequestContext.newBuilder()
176+
return getBuilder(ugi, remoteAddress, hostName, aclType, ownerName, recursiveAccessCheck, null);
177+
}
178+
179+
public static RequestContext.Builder getBuilder(UserGroupInformation ugi, InetAddress remoteAddress, String hostName,
180+
ACLType aclType, String ownerName, boolean recursiveAccessCheck, String sessionPolicy) {
181+
return RequestContext.newBuilder()
154182
.setClientUgi(ugi)
155183
.setIp(remoteAddress)
156184
.setHost(hostName)
157185
.setAclType(ACLIdentityType.USER)
158186
.setAclRights(aclType)
159187
.setOwnerName(ownerName)
160-
.setRecursiveAccessCheck(recursiveAccessCheck);
161-
return contextBuilder;
188+
.setRecursiveAccessCheck(recursiveAccessCheck)
189+
.setSessionPolicy(sessionPolicy);
162190
}
163191

164192
public static RequestContext.Builder getBuilder(UserGroupInformation ugi,
@@ -206,4 +234,8 @@ public String getOwnerName() {
206234
public boolean isRecursiveAccessCheck() {
207235
return recursiveAccessCheck;
208236
}
237+
238+
public String getSessionPolicy() {
239+
return sessionPolicy;
240+
}
209241
}

0 commit comments

Comments
 (0)