Skip to content

Commit 9fcb8e4

Browse files
committed
[#13859] fix(authz): expose inaccessible object associations
1 parent 7990fb1 commit 9fcb8e4

16 files changed

Lines changed: 544 additions & 48 deletions

File tree

‎clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/PolicyAuthorizationIT.java‎

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.google.common.collect.ImmutableSet;
2525
import com.google.common.collect.Maps;
2626
import java.io.IOException;
27+
import java.lang.reflect.Method;
2728
import java.util.ArrayList;
2829
import java.util.Arrays;
2930
import java.util.HashMap;
@@ -39,6 +40,9 @@
3940
import org.apache.gravitino.authorization.SecurableObject;
4041
import org.apache.gravitino.authorization.SecurableObjects;
4142
import org.apache.gravitino.client.GravitinoMetalake;
43+
import org.apache.gravitino.client.RESTClient;
44+
import org.apache.gravitino.dto.responses.MetadataObjectPolicyListResponse;
45+
import org.apache.gravitino.dto.responses.PolicyNameListResponse;
4246
import org.apache.gravitino.exceptions.ForbiddenException;
4347
import org.apache.gravitino.integration.test.container.ContainerSuite;
4448
import org.apache.gravitino.integration.test.container.HiveContainer;
@@ -321,6 +325,38 @@ public void testListPolicyForTable() {
321325
.supportsPolicies()
322326
.listPolicies();
323327
Assertions.assertArrayEquals(new String[] {"policy2"}, policies);
328+
329+
RESTClient restClient = getNormalUserRestClient();
330+
String path =
331+
"api/metalakes/"
332+
+ METALAKE
333+
+ "/objects/table/"
334+
+ CATALOG
335+
+ "."
336+
+ SCHEMA
337+
+ ".table1/policies";
338+
PolicyNameListResponse nameListResponse =
339+
restClient.get(
340+
path,
341+
PolicyNameListResponse.class,
342+
Map.of(),
343+
error -> {
344+
throw new AssertionError(error);
345+
});
346+
Assertions.assertEquals(0, nameListResponse.getNames().length);
347+
Assertions.assertTrue(nameListResponse.hasInaccessiblePolicies());
348+
349+
MetadataObjectPolicyListResponse listResponse =
350+
restClient.get(
351+
path,
352+
Map.of("details", "true"),
353+
MetadataObjectPolicyListResponse.class,
354+
Map.of(),
355+
error -> {
356+
throw new AssertionError(error);
357+
});
358+
Assertions.assertEquals(0, listResponse.getPolicies().length);
359+
Assertions.assertTrue(listResponse.hasInaccessiblePolicies());
324360
}
325361

326362
@Test
@@ -433,4 +469,15 @@ public void testDropPolicy() {
433469
gravitinoMetalake.deletePolicy("policy1");
434470
metalakeLoadByNormalUser.deletePolicy("policy2");
435471
}
472+
473+
private RESTClient getNormalUserRestClient() {
474+
try {
475+
Method restClientMethod =
476+
normalUserClient.getClass().getSuperclass().getDeclaredMethod("restClient");
477+
restClientMethod.setAccessible(true);
478+
return (RESTClient) restClientMethod.invoke(normalUserClient);
479+
} catch (ReflectiveOperationException e) {
480+
throw new RuntimeException("Failed to access the normal user's REST client", e);
481+
}
482+
}
436483
}

‎clients/client-java/src/test/java/org/apache/gravitino/client/integration/test/authorization/TagOperationsAuthorizationIT.java‎

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@
3939
import org.apache.gravitino.authorization.SecurableObject;
4040
import org.apache.gravitino.authorization.SecurableObjects;
4141
import org.apache.gravitino.client.GravitinoMetalake;
42+
import org.apache.gravitino.client.RESTClient;
4243
import org.apache.gravitino.dto.MetalakeDTO;
44+
import org.apache.gravitino.dto.responses.MetadataObjectTagListResponse;
45+
import org.apache.gravitino.dto.responses.TagNameListResponse;
4346
import org.apache.gravitino.exceptions.ForbiddenException;
4447
import org.apache.gravitino.integration.test.container.ContainerSuite;
4548
import org.apache.gravitino.integration.test.container.HiveContainer;
@@ -281,6 +284,32 @@ public void testListTagByMetadata() {
281284
String[] tagsLoadByNormalUser = tableSupportTagByNormalUser.listTags();
282285
Arrays.sort(tagsLoadByNormalUser);
283286
assertArrayEquals(new String[] {"tag2", "tag3"}, tagsLoadByNormalUser);
287+
288+
RESTClient restClient = getNormalUserRestClient();
289+
String path =
290+
"api/metalakes/" + METALAKE + "/objects/table/" + CATALOG + "." + SCHEMA + ".table1/tags";
291+
TagNameListResponse nameListResponse =
292+
restClient.get(
293+
path,
294+
TagNameListResponse.class,
295+
Map.of(),
296+
error -> {
297+
throw new AssertionError(error);
298+
});
299+
Assertions.assertEquals(2, nameListResponse.getNames().length);
300+
Assertions.assertTrue(nameListResponse.hasInaccessibleTags());
301+
302+
MetadataObjectTagListResponse listResponse =
303+
restClient.get(
304+
path,
305+
Map.of("details", "true"),
306+
MetadataObjectTagListResponse.class,
307+
Map.of(),
308+
error -> {
309+
throw new AssertionError(error);
310+
});
311+
Assertions.assertEquals(2, listResponse.getTags().length);
312+
Assertions.assertTrue(listResponse.hasInaccessibleTags());
284313
}
285314

286315
@Test
@@ -467,4 +496,15 @@ public void testDropTag() {
467496
private Column[] createColumns() {
468497
return new Column[] {Column.of("col1", Types.StringType.get())};
469498
}
499+
500+
private RESTClient getNormalUserRestClient() {
501+
try {
502+
Method restClientMethod =
503+
normalUserClient.getClass().getSuperclass().getDeclaredMethod("restClient");
504+
restClientMethod.setAccessible(true);
505+
return (RESTClient) restClientMethod.invoke(normalUserClient);
506+
} catch (ReflectiveOperationException e) {
507+
throw new RuntimeException("Failed to access the normal user's REST client", e);
508+
}
509+
}
470510
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.gravitino.dto.responses;
20+
21+
import com.fasterxml.jackson.annotation.JsonProperty;
22+
import lombok.EqualsAndHashCode;
23+
import lombok.ToString;
24+
import org.apache.gravitino.dto.policy.PolicyDTO;
25+
26+
/** Represents a response for policies associated with a metadata object. */
27+
@ToString
28+
@EqualsAndHashCode(callSuper = true)
29+
public class MetadataObjectPolicyListResponse extends PolicyListResponse {
30+
31+
@JsonProperty("hasInaccessiblePolicies")
32+
private final boolean hasInaccessiblePolicies;
33+
34+
/**
35+
* Creates a new MetadataObjectPolicyListResponse.
36+
*
37+
* @param policies The list of accessible policies.
38+
* @param hasInaccessiblePolicies Whether inaccessible policies were omitted from the response.
39+
*/
40+
public MetadataObjectPolicyListResponse(PolicyDTO[] policies, boolean hasInaccessiblePolicies) {
41+
super(policies);
42+
this.hasInaccessiblePolicies = hasInaccessiblePolicies;
43+
}
44+
45+
/** Constructor used by Jackson deserializer. */
46+
public MetadataObjectPolicyListResponse() {
47+
super();
48+
this.hasInaccessiblePolicies = false;
49+
}
50+
51+
/**
52+
* Returns whether inaccessible policies were omitted from the response.
53+
*
54+
* @return true if at least one inaccessible policy was omitted, false otherwise
55+
*/
56+
public boolean hasInaccessiblePolicies() {
57+
return hasInaccessiblePolicies;
58+
}
59+
}
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.gravitino.dto.responses;
20+
21+
import com.fasterxml.jackson.annotation.JsonProperty;
22+
import lombok.EqualsAndHashCode;
23+
import lombok.ToString;
24+
import org.apache.gravitino.dto.tag.TagDTO;
25+
26+
/** Represents a response for tags associated with a metadata object. */
27+
@ToString
28+
@EqualsAndHashCode(callSuper = true)
29+
public class MetadataObjectTagListResponse extends TagListResponse {
30+
31+
@JsonProperty("hasInaccessibleTags")
32+
private final boolean hasInaccessibleTags;
33+
34+
/**
35+
* Creates a new MetadataObjectTagListResponse.
36+
*
37+
* @param tags The list of accessible tags.
38+
* @param hasInaccessibleTags Whether inaccessible tags were omitted from the response.
39+
*/
40+
public MetadataObjectTagListResponse(TagDTO[] tags, boolean hasInaccessibleTags) {
41+
super(tags);
42+
this.hasInaccessibleTags = hasInaccessibleTags;
43+
}
44+
45+
/** Constructor used by Jackson deserializer. */
46+
public MetadataObjectTagListResponse() {
47+
super();
48+
this.hasInaccessibleTags = false;
49+
}
50+
51+
/**
52+
* Returns whether inaccessible tags were omitted from the response.
53+
*
54+
* @return true if at least one inaccessible tag was omitted, false otherwise
55+
*/
56+
public boolean hasInaccessibleTags() {
57+
return hasInaccessibleTags;
58+
}
59+
}

‎common/src/main/java/org/apache/gravitino/dto/responses/NameListResponse.java‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package org.apache.gravitino.dto.responses;
2020

21+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
2122
import com.fasterxml.jackson.annotation.JsonProperty;
2223
import com.google.common.base.Preconditions;
2324
import java.util.Arrays;
@@ -27,6 +28,7 @@
2728
import org.apache.commons.lang3.StringUtils;
2829

2930
/** Represents a response for a list of entity names. */
31+
@JsonIgnoreProperties(ignoreUnknown = true)
3032
@Getter
3133
@ToString
3234
@EqualsAndHashCode(callSuper = true)

‎common/src/main/java/org/apache/gravitino/dto/responses/PolicyListResponse.java‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package org.apache.gravitino.dto.responses;
2020

21+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
2122
import com.fasterxml.jackson.annotation.JsonProperty;
2223
import com.google.common.base.Preconditions;
2324
import java.util.Arrays;
@@ -27,6 +28,7 @@
2728
import org.apache.gravitino.dto.policy.PolicyDTO;
2829

2930
/** Represents a response for a list of policies. */
31+
@JsonIgnoreProperties(ignoreUnknown = true)
3032
@Getter
3133
@ToString
3234
@EqualsAndHashCode(callSuper = true)
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.gravitino.dto.responses;
20+
21+
import com.fasterxml.jackson.annotation.JsonProperty;
22+
import lombok.EqualsAndHashCode;
23+
import lombok.ToString;
24+
25+
/** Represents a response for a list of policy names. */
26+
@ToString
27+
@EqualsAndHashCode(callSuper = true)
28+
public class PolicyNameListResponse extends NameListResponse {
29+
30+
@JsonProperty("hasInaccessiblePolicies")
31+
private final boolean hasInaccessiblePolicies;
32+
33+
/**
34+
* Creates a new PolicyNameListResponse.
35+
*
36+
* @param names The list of accessible policy names.
37+
* @param hasInaccessiblePolicies Whether inaccessible policies were omitted from the response.
38+
*/
39+
public PolicyNameListResponse(String[] names, boolean hasInaccessiblePolicies) {
40+
super(names);
41+
this.hasInaccessiblePolicies = hasInaccessiblePolicies;
42+
}
43+
44+
/** Constructor used by Jackson deserializer. */
45+
public PolicyNameListResponse() {
46+
super();
47+
this.hasInaccessiblePolicies = false;
48+
}
49+
50+
/**
51+
* Returns whether inaccessible policies were omitted from the response.
52+
*
53+
* @return true if at least one inaccessible policy was omitted, false otherwise
54+
*/
55+
public boolean hasInaccessiblePolicies() {
56+
return hasInaccessiblePolicies;
57+
}
58+
}

‎common/src/main/java/org/apache/gravitino/dto/responses/TagListResponse.java‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package org.apache.gravitino.dto.responses;
2020

21+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
2122
import com.fasterxml.jackson.annotation.JsonProperty;
2223
import com.google.common.base.Preconditions;
2324
import java.util.Arrays;
@@ -27,6 +28,7 @@
2728
import org.apache.gravitino.dto.tag.TagDTO;
2829

2930
/** Represents a response for a list of tags. */
31+
@JsonIgnoreProperties(ignoreUnknown = true)
3032
@Getter
3133
@ToString
3234
@EqualsAndHashCode(callSuper = true)

0 commit comments

Comments
 (0)