This is an automated email from the ASF dual-hosted git repository.
madhan pushed a commit to branch ranger-2.8
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/ranger-2.8 by this push:
new b104e9449 RANGER-5447: update local policy source implementations to
support loading from serviceName.json (#802)
b104e9449 is described below
commit b104e944951c92a1331331088f2acbb2ed00497a
Author: Madhan Neethiraj <[email protected]>
AuthorDate: Mon Jan 19 23:33:36 2026 -0800
RANGER-5447: update local policy source implementations to support loading
from serviceName.json (#802)
(cherry picked from commit 57dbe01ca0f93a6f30f28e1152cc63d3dd4c2355)
---
.../admin/client/EmbeddedResourcePolicySource.java | 125 +++++-----
.../admin/client/LocalFolderPolicySource.java | 96 ++++----
.../ranger/admin/client/RangerPolicySource.java | 88 +++++++
.../client/TestEmbeddedResourcePolicySource.java | 91 +++++++
.../admin/client/TestLocalFolderPolicySource.java | 91 +++++++
.../src/test/resources/admin.client/dev_s3.json | 7 +
.../test/resources/admin.client/dev_s3_roles.json | 5 +
.../test/resources/admin.client/dev_s3_tag.json | 9 +
.../resources/admin.client/dev_s3_userstore.json | 6 +
.../admin.client/hiveServer2_dev_hive.json | 7 +
.../admin.client/hiveServer2_dev_hive_roles.json | 5 +
.../admin.client/hiveServer2_dev_hive_tag.json | 9 +
.../hiveServer2_dev_hive_userstore.json | 6 +
.../{hive_dev_hive.json => dev_hive.json} | 0
.../{hive_dev_hive_tag.json => dev_hive_tag.json} | 0
.../resources/test_hive/hive_dev_hive_gds.json | 112 ---------
.../src/test/resources/test_hive/tests_authz.json | 263 ---------------------
.../test_hive/tests_resource_permissions.json | 57 -----
.../test_s3/{s3_dev_s3.json => dev_s3.json} | 0
.../{s3_dev_s3_roles.json => dev_s3_roles.json} | 0
.../{s3_dev_s3_tag.json => dev_s3_tag.json} | 0
.../src/test/resources/test_s3/s3_dev_s3_gds.json | 90 -------
.../src/test/resources/test_s3/tests_authz.json | 222 -----------------
.../test_s3/tests_resource_permissions.json | 30 ---
24 files changed, 441 insertions(+), 878 deletions(-)
diff --git
a/agents-common/src/main/java/org/apache/ranger/admin/client/EmbeddedResourcePolicySource.java
b/agents-common/src/main/java/org/apache/ranger/admin/client/EmbeddedResourcePolicySource.java
index 395700abb..5b1b46c01 100644
---
a/agents-common/src/main/java/org/apache/ranger/admin/client/EmbeddedResourcePolicySource.java
+++
b/agents-common/src/main/java/org/apache/ranger/admin/client/EmbeddedResourcePolicySource.java
@@ -19,6 +19,7 @@
package org.apache.ranger.admin.client;
+import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.ranger.plugin.util.RangerRoles;
import org.apache.ranger.plugin.util.RangerUserStore;
@@ -30,122 +31,120 @@
import java.io.InputStream;
import java.io.InputStreamReader;
-// this implementation loads policies, roles, tags, userstore and gds info
from embedded resources at following paths:
-// {resource-path}/{appId}_{serviceName}.json -> policies
-// {resource-path}/{appId}_{serviceName}_roles.json -> roles
-// {resource-path}/{appId}_{serviceName}_tag.json -> tags
-// {resource-path}/{appId}_{serviceName}_userstore.json -> userstore
-// {resource-path}/{appId}_{serviceName}_gds.json -> gds info
-public class EmbeddedResourcePolicySource extends AbstractRangerAdminClient {
+// this implementation loads policies, roles, tags and userstore from embedded
resources at following paths:
+// policies: {resource-path}/{serviceName}.json or
{resource-path}/{appId}_{serviceName}.json
+// roles: {resource-path}/{serviceName}_roles.json or
{resource-path}/{appId}_{serviceName}_roles.json
+// tags: {resource-path}/{serviceName}_tag.json or
{resource-path}/{appId}_{serviceName}_tag.json
+// userstore: {resource-path}/{serviceName}_userstore.json or
{resource-path}/{appId}_{serviceName}_userstore.json
+public class EmbeddedResourcePolicySource extends RangerPolicySource {
private static final Logger LOG =
LoggerFactory.getLogger(EmbeddedResourcePolicySource.class);
+ private String prefix;
+ private String prefixWithAppId;
+
private ServicePolicies policies;
private RangerRoles roles;
private ServiceTags tags;
private RangerUserStore userStore;
- private String policiesPath;
- private String rolesPath;
- private String tagsPath;
- private String userStorePath;
-
@Override
public void init(String serviceName, String appId, String
configPropertyPrefix, Configuration config) {
super.init(serviceName, appId, configPropertyPrefix, config);
- String directory = config.get(configPropertyPrefix +
".policy.source.embedded_resource.path");
- String pathPrefix = (directory == null ? "" : directory) + "/" + appId
+ "_" + serviceName;
+ String directory = config.get(configPropertyPrefix +
".policy.source.embedded_resource.path");
- if (!pathPrefix.startsWith("/")) {
- pathPrefix = "/" + pathPrefix;
+ if (StringUtils.isBlank(directory)) {
+ directory = "/";
+ } else if (!directory.endsWith("/")) {
+ directory += "/";
}
- this.policiesPath = pathPrefix + ".json";
- this.rolesPath = pathPrefix + "_roles.json";
- this.tagsPath = pathPrefix + "_tag.json";
- this.userStorePath = pathPrefix + "_userstore.json";
+ prefix = directory + serviceName;
+ prefixWithAppId = StringUtils.isBlank(appId) ? null : (directory +
appId + "_" + serviceName);
}
@Override
- public ServicePolicies getServicePoliciesIfUpdated(long lastKnownVersion,
long lastActivationTimeInMillis) {
+ public ServicePolicies getServicePoliciesIfUpdated(long lastKnownVersion,
long lastActivationTimeInMillis) throws Exception {
loadPolicies();
return (lastKnownVersion == -1 || policies == null ||
policies.getPolicyVersion() == null ||
!policies.getPolicyVersion().equals(lastKnownVersion)) ? policies : null;
}
@Override
- public RangerRoles getRolesIfUpdated(long lastKnownVersion, long
lastActivationTimeInMills) {
+ public RangerRoles getRolesIfUpdated(long lastKnownVersion, long
lastActivationTimeInMills) throws Exception {
loadRoles();
return (lastKnownVersion == -1 || roles == null ||
roles.getRoleVersion() == null ||
!roles.getRoleVersion().equals(lastKnownVersion)) ? roles : null; }
@Override
- public ServiceTags getServiceTagsIfUpdated(long lastKnownVersion, long
lastActivationTimeInMillis) {
+ public ServiceTags getServiceTagsIfUpdated(long lastKnownVersion, long
lastActivationTimeInMillis) throws Exception {
loadTags();
return (lastKnownVersion == -1 || tags == null || tags.getTagVersion()
== null || !tags.getTagVersion().equals(lastKnownVersion)) ? tags : null;
}
@Override
- public RangerUserStore getUserStoreIfUpdated(long lastKnownVersion, long
lastActivationTimeInMillis) {
+ public RangerUserStore getUserStoreIfUpdated(long lastKnownVersion, long
lastActivationTimeInMillis) throws Exception {
loadUserStore();
return (lastKnownVersion == -1 || userStore == null ||
userStore.getUserStoreVersion() == null ||
!userStore.getUserStoreVersion().equals(lastKnownVersion)) ? userStore : null;
}
- private void loadPolicies() {
+ private void loadPolicies() throws Exception {
if (policies == null) {
- try {
- InputStream input =
getClass().getResourceAsStream(policiesPath);
-
- if (input != null) {
- policies = gson.fromJson(new InputStreamReader(input),
ServicePolicies.class);
- }
- } catch (Throwable t) {
- LOG.error("loadPolicies(): failed to load policies from {}",
policiesPath, t);
- }
+ InputStream input = getResourceStream(SUFFIX_POLICIES_FILE);
+
+ policies = gson.fromJson(new InputStreamReader(input),
ServicePolicies.class);
}
}
- private void loadRoles() {
+ private void loadRoles() throws Exception {
if (roles == null) {
- try {
- InputStream input = getClass().getResourceAsStream(rolesPath);
-
- if (input != null) {
- roles = gson.fromJson(new InputStreamReader(input),
RangerRoles.class);
- }
- } catch (Throwable t) {
- LOG.error("loadRoles(): failed to load roles from {}",
rolesPath, t);
- }
+ InputStream input = getResourceStream(SUFFIX_ROLES_FILE);
+
+ roles = gson.fromJson(new InputStreamReader(input),
RangerRoles.class);
}
}
- private void loadUserStore() {
+ private void loadUserStore() throws Exception {
if (userStore == null) {
- try {
- InputStream input =
getClass().getResourceAsStream(userStorePath);
-
- if (input != null) {
- userStore = gson.fromJson(new InputStreamReader(input),
RangerUserStore.class);
- }
- } catch (Throwable t) {
- LOG.error("loadUserStore(): failed to load userstore from {}",
userStorePath, t);
- }
+ InputStream input = getResourceStream(SUFFIX_USERSTORE_FILE);
+
+ userStore = gson.fromJson(new InputStreamReader(input),
RangerUserStore.class);
}
}
- private void loadTags() {
+ private void loadTags() throws Exception {
if (tags == null) {
- try {
- InputStream input = getClass().getResourceAsStream(tagsPath);
-
- if (input != null) {
- tags = gson.fromJson(new InputStreamReader(input),
ServiceTags.class);
- }
- } catch (Throwable t) {
- LOG.error("loadTags(): failed to load tags from {}", tagsPath,
t);
+ InputStream input = getResourceStream(SUFFIX_TAG_FILE);
+
+ tags = gson.fromJson(new InputStreamReader(input),
ServiceTags.class);
+ }
+ }
+
+ private InputStream getResourceStream(String suffix) throws Exception {
+ if (StringUtils.isBlank(prefix)) {
+ throw new Exception(EmbeddedResourcePolicySource.class.getName() +
": not initialized");
+ }
+
+ try {
+ InputStream src = getClass().getResourceAsStream(prefix + suffix);
+
+ if (src == null && StringUtils.isNotBlank(prefixWithAppId)) {
+ src = getClass().getResourceAsStream(prefixWithAppId + suffix);
}
+
+ if (src == null) {
+ LOG.error("{}{}: resource not found", prefix, suffix);
+
+ throw new Exception(prefix + suffix + ": resource not found");
+ }
+
+ return src;
+ } catch (Exception excp) {
+ LOG.error("{}{}: resource not found", prefix, suffix, excp);
+
+ throw new Exception(prefix + suffix + ": resource not found",
excp);
}
}
}
diff --git
a/agents-common/src/main/java/org/apache/ranger/admin/client/LocalFolderPolicySource.java
b/agents-common/src/main/java/org/apache/ranger/admin/client/LocalFolderPolicySource.java
index dec07a821..3de249230 100644
---
a/agents-common/src/main/java/org/apache/ranger/admin/client/LocalFolderPolicySource.java
+++
b/agents-common/src/main/java/org/apache/ranger/admin/client/LocalFolderPolicySource.java
@@ -19,47 +19,53 @@
package org.apache.ranger.admin.client;
+import org.apache.commons.lang3.StringUtils;
import org.apache.hadoop.conf.Configuration;
import org.apache.ranger.plugin.util.RangerRoles;
import org.apache.ranger.plugin.util.RangerUserStore;
import org.apache.ranger.plugin.util.ServicePolicies;
import org.apache.ranger.plugin.util.ServiceTags;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import java.io.File;
import java.io.FileReader;
-// this implementation loads policies, roles, tags, userstore and gds info
from the given local filesystem paths:
-// {path}/{appId}_{serviceName}.json -> policies
-// {path}/{appId}_{serviceName}_roles.json -> roles
-// {path}/{appId}_{serviceName}_tag.json -> tags
-// {path}/{appId}_{serviceName}_userstore.json -> userstore
-// {path}/{appId}_{serviceName}_gds.json -> gds info
-public class LocalFolderPolicySource extends AbstractRangerAdminClient {
+// this implementation loads policies, roles, tags and userstore from the
given local filesystem paths:
+// policies: {path}/{serviceName}.json or
{path}/{appId}_{serviceName}.json
+// roles: {path}/{serviceName}_roles.json or
{path}/{appId}_{serviceName}_roles.json
+// tags: {path}/{serviceName}_tag.json or
{path}/{appId}_{serviceName}_tag.json
+// userstore: {path}/{serviceName}_userstore.json or
{path}/{appId}_{serviceName}_userstore.json
+public class LocalFolderPolicySource extends RangerPolicySource {
+ private static final Logger LOG =
LoggerFactory.getLogger(LocalFolderPolicySource.class);
+
+ private String prefix;
+ private String prefixWithAppId;
+
private ServicePolicies policies;
private RangerRoles roles;
private RangerUserStore userStore;
private ServiceTags tags;
- private String policiesPath;
- private String rolesPath;
- private String userStorePath;
- private String tagsPath;
- private long lastPoliciesFileModifiedTime = -1;
- private long lastRolesFileModifiedTime = -1;
- private long lastUserStoreFileModifiedTime = -1;
- private long lastTagsFileModifiedTime = -1;
+ private long lastPoliciesFileModifiedTime = -1;
+ private long lastRolesFileModifiedTime = -1;
+ private long lastUserStoreFileModifiedTime = -1;
+ private long lastTagsFileModifiedTime = -1;
@Override
public void init(String serviceName, String appId, String
configPropertyPrefix, Configuration config) {
super.init(serviceName, appId, configPropertyPrefix, config);
- String directory = config.get(configPropertyPrefix +
".policy.source.local_folder.path");
- String pathPrefix = (directory == null ? "" : directory) +
File.separator + appId + "_" + serviceName;
+ String directory = config.get(configPropertyPrefix +
".policy.source.local_folder.path");
+
+ if (StringUtils.isBlank(directory)) {
+ directory = "";
+ } else if (!directory.endsWith(File.separator)) {
+ directory += File.separator;
+ }
- this.policiesPath = pathPrefix + ".json";
- this.rolesPath = pathPrefix + "_roles.json";
- this.userStorePath = pathPrefix + "_userstore.json";
- this.tagsPath = pathPrefix + "_tag.json";
+ prefix = directory + serviceName;
+ prefixWithAppId = StringUtils.isBlank(appId) ? null : (directory +
appId + "_" + serviceName);
}
@Override
@@ -91,11 +97,7 @@ public RangerUserStore getUserStoreIfUpdated(long
lastKnownVersion, long lastAct
}
private void loadPolicies() throws Exception {
- File srcFile = new File(policiesPath);
-
- if (!srcFile.exists() || !srcFile.canRead()) {
- throw new Exception(policiesPath + ": policies file not found or
not readable");
- }
+ File srcFile = getSourceFile(SUFFIX_POLICIES_FILE);
if (policies == null || srcFile.lastModified() !=
lastPoliciesFileModifiedTime) {
try (FileReader reader = new FileReader(srcFile)) {
@@ -107,11 +109,7 @@ private void loadPolicies() throws Exception {
}
private void loadRoles() throws Exception {
- File srcFile = new File(rolesPath);
-
- if (!srcFile.exists() || !srcFile.canRead()) {
- throw new Exception(rolesPath + ": roles file not found or not
readable");
- }
+ File srcFile = getSourceFile(SUFFIX_ROLES_FILE);
if (roles == null || srcFile.lastModified() !=
lastRolesFileModifiedTime) {
try (FileReader reader = new FileReader(srcFile)) {
@@ -123,11 +121,7 @@ private void loadRoles() throws Exception {
}
private void loadTags() throws Exception {
- File srcFile = new File(tagsPath);
-
- if (!srcFile.exists() || !srcFile.canRead()) {
- throw new Exception(tagsPath + ": tags file not found or not
readable");
- }
+ File srcFile = getSourceFile(SUFFIX_TAG_FILE);
if (tags == null || srcFile.lastModified() !=
lastTagsFileModifiedTime) {
try (FileReader reader = new FileReader(srcFile)) {
@@ -139,11 +133,7 @@ private void loadTags() throws Exception {
}
private void loadUserStore() throws Exception {
- File srcFile = new File(userStorePath);
-
- if (!srcFile.exists() || !srcFile.canRead()) {
- throw new Exception(userStorePath + ": userStore file not found or
not readable");
- }
+ File srcFile = getSourceFile(SUFFIX_USERSTORE_FILE);
if (userStore == null || srcFile.lastModified() !=
lastUserStoreFileModifiedTime) {
try (FileReader reader = new FileReader(srcFile)) {
@@ -153,4 +143,28 @@ private void loadUserStore() throws Exception {
}
}
}
+
+ private File getSourceFile(String suffix) throws Exception {
+ if (StringUtils.isBlank(prefix)) {
+ throw new Exception(LocalFolderPolicySource.class.getName() + ":
not initialized");
+ }
+
+ File src = new File(prefix + suffix);
+ boolean isReadable = src.exists() && src.canRead();
+
+ if (!isReadable) {
+ if (StringUtils.isNotBlank(prefixWithAppId)) {
+ src = new File(prefixWithAppId + suffix);
+ isReadable = src.exists() && src.canRead();
+ }
+ }
+
+ if (!isReadable) {
+ LOG.error("{}{}: file not found or not readable", prefix, suffix);
+
+ throw new Exception(prefix + suffix + ": file not found or not
readable");
+ }
+
+ return src;
+ }
}
diff --git
a/agents-common/src/main/java/org/apache/ranger/admin/client/RangerPolicySource.java
b/agents-common/src/main/java/org/apache/ranger/admin/client/RangerPolicySource.java
new file mode 100644
index 000000000..24f417d6f
--- /dev/null
+++
b/agents-common/src/main/java/org/apache/ranger/admin/client/RangerPolicySource.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.admin.client;
+
+import org.apache.commons.lang3.NotImplementedException;
+import org.apache.ranger.plugin.model.RangerRole;
+import org.apache.ranger.plugin.util.GrantRevokeRequest;
+import org.apache.ranger.plugin.util.GrantRevokeRoleRequest;
+
+import java.util.List;
+
+// Implementations of this abstract class should implement methods that supply
+// following details used by policy engine: policies, tags, roles, userstore,
gds
+// Other methods in RangerAdminClient throw NotImplementedException
+public abstract class RangerPolicySource extends AbstractRangerAdminClient {
+ public static final String SUFFIX_POLICIES_FILE = ".json";
+ public static final String SUFFIX_ROLES_FILE = "_roles.json";
+ public static final String SUFFIX_USERSTORE_FILE = "_userstore.json";
+ public static final String SUFFIX_TAG_FILE = "_tag.json";
+ public static final String SUFFIX_GDS_FILE = "_gds.json";
+
+ @Override
+ public RangerRole createRole(RangerRole request) throws Exception {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public void dropRole(String execUser, String roleName) throws Exception {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public List<String> getAllRoles(String execUser) throws Exception {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public List<String> getUserRoles(String execUser) throws Exception {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public RangerRole getRole(String execUser, String roleName) throws
Exception {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public void grantRole(GrantRevokeRoleRequest request) throws Exception {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public void revokeRole(GrantRevokeRoleRequest request) throws Exception {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public void grantAccess(GrantRevokeRequest request) throws Exception {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public void revokeAccess(GrantRevokeRequest request) throws Exception {
+ throw new NotImplementedException();
+ }
+
+ @Override
+ public List<String> getTagTypes(String tagTypePattern) throws Exception {
+ throw new NotImplementedException();
+ }
+}
diff --git
a/agents-common/src/test/java/org/apache/ranger/admin/client/TestEmbeddedResourcePolicySource.java
b/agents-common/src/test/java/org/apache/ranger/admin/client/TestEmbeddedResourcePolicySource.java
new file mode 100644
index 000000000..6f1101f8c
--- /dev/null
+++
b/agents-common/src/test/java/org/apache/ranger/admin/client/TestEmbeddedResourcePolicySource.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.admin.client;
+
+import org.apache.hadoop.conf.Configuration;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class TestEmbeddedResourcePolicySource {
+ @Test
+ public void testLoadWithServiceNamePrefix() throws Exception {
+ RangerPolicySource source = getPolicySource("s3", "dev_s3", null);
+
+ assertNotNull(source.getServicePoliciesIfUpdated(-1, -1), "failed to
load policies for service=dev_s3, appId=null");
+ assertNotNull(source.getServiceTagsIfUpdated(-1, -1), "failed to load
tags for service=dev_s3, appId=null");
+ assertNotNull(source.getRolesIfUpdated(-1, -1), "failed to load roles
for service=dev_s3, appId=null");
+ assertNotNull(source.getUserStoreIfUpdated(-1, -1), "failed to load
userStore for service=dev_s3, appId=null");
+ }
+
+ @Test
+ public void testLoadWithServiceNamePrefixIgnoreAppId() throws Exception {
+ RangerPolicySource source = getPolicySource("s3", "dev_s3", "s3proxy");
+
+ assertNotNull(source.getServicePoliciesIfUpdated(-1, -1), "failed to
load policies for service=dev_s3, appId=s3proxy");
+ assertNotNull(source.getServiceTagsIfUpdated(-1, -1), "failed to load
tags for service=dev_s3, appId=s3proxy");
+ assertNotNull(source.getRolesIfUpdated(-1, -1), "failed to load roles
for service=dev_s3, appId=s3proxy");
+ assertNotNull(source.getUserStoreIfUpdated(-1, -1), "failed to load
userStore for service=dev_s3, appId=s3proxy");
+ }
+
+ @Test
+ public void testLoadWithAppIdServiceNamePrefix() throws Exception {
+ RangerPolicySource source = getPolicySource("hive", "dev_hive",
"hiveServer2");
+
+ assertNotNull(source.getServicePoliciesIfUpdated(-1, -1), "failed to
load policies for service=dev_hive, appId=hiveServer2");
+ assertNotNull(source.getServiceTagsIfUpdated(-1, -1), "failed to load
tags for service=dev_hive, appId=hiveServer2");
+ assertNotNull(source.getRolesIfUpdated(-1, -1), "failed to load roles
for service=dev_hive, appId=hiveServer2");
+ assertNotNull(source.getUserStoreIfUpdated(-1, -1), "failed to load
userStore for service=dev_hive, appId=hiveServer2");
+ }
+
+ @Test
+ public void testLoadFailureWithNonExistingServiceName() throws Exception {
+ RangerPolicySource source = getPolicySource("s3", "test_s3", null);
+
+ assertThrows(Exception.class, () ->
source.getServicePoliciesIfUpdated(-1, -1), "expected to not find policies for
service=test_s3, appId=null");
+ assertThrows(Exception.class, () -> source.getServiceTagsIfUpdated(-1,
-1), "expected to not find tags for service=test_s3, appId=null");
+ assertThrows(Exception.class, () -> source.getRolesIfUpdated(-1, -1),
"expected to not find roles for service=test_s3, appId=null");
+ assertThrows(Exception.class, () -> source.getUserStoreIfUpdated(-1,
-1), "expected to not find userStore for service=test_s3, appId=null");
+ }
+
+ @Test
+ public void testLoadFailureWithNonExistingServiceNameAndAppId() throws
Exception {
+ RangerPolicySource source = getPolicySource("hive", "test_hive",
"trino");
+
+ assertThrows(Exception.class, () ->
source.getServicePoliciesIfUpdated(-1, -1), "expected to not find policies for
service=test_hive, appId=trino");
+ assertThrows(Exception.class, () -> source.getServiceTagsIfUpdated(-1,
-1), "expected to not find tags for service=test_hive, appId=trino");
+ assertThrows(Exception.class, () -> source.getRolesIfUpdated(-1, -1),
"expected to not find roles for service=test_hive, appId=trino");
+ assertThrows(Exception.class, () -> source.getUserStoreIfUpdated(-1,
-1), "expected to not find userStore for service=test_hive, appId=trino");
+ }
+
+ private RangerPolicySource getPolicySource(String serviceType, String
serviceName, String appId) {
+ String propPrefix = "ranger.plugin." + serviceType;
+ Configuration conf = new Configuration();
+
+ conf.set(propPrefix + ".policy.source.embedded_resource.path",
"/admin.client");
+
+ EmbeddedResourcePolicySource source = new
EmbeddedResourcePolicySource();
+
+ source.init(serviceName, appId, propPrefix, conf);
+
+ return source;
+ }
+}
diff --git
a/agents-common/src/test/java/org/apache/ranger/admin/client/TestLocalFolderPolicySource.java
b/agents-common/src/test/java/org/apache/ranger/admin/client/TestLocalFolderPolicySource.java
new file mode 100644
index 000000000..11bfa9e26
--- /dev/null
+++
b/agents-common/src/test/java/org/apache/ranger/admin/client/TestLocalFolderPolicySource.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.ranger.admin.client;
+
+import org.apache.hadoop.conf.Configuration;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+public class TestLocalFolderPolicySource {
+ @Test
+ public void testLoadWithServiceNamePrefix() throws Exception {
+ RangerPolicySource source = getPolicySource("s3", "dev_s3", null);
+
+ assertNotNull(source.getServicePoliciesIfUpdated(-1, -1), "failed to
load policies for service=dev_s3, appId=null");
+ assertNotNull(source.getServiceTagsIfUpdated(-1, -1), "failed to load
tags for service=dev_s3, appId=null");
+ assertNotNull(source.getRolesIfUpdated(-1, -1), "failed to load roles
for service=dev_s3, appId=null");
+ assertNotNull(source.getUserStoreIfUpdated(-1, -1), "failed to load
userStore for service=dev_s3, appId=null");
+ }
+
+ @Test
+ public void testLoadWithServiceNamePrefixIgnoreAppId() throws Exception {
+ RangerPolicySource source = getPolicySource("s3", "dev_s3", "s3proxy");
+
+ assertNotNull(source.getServicePoliciesIfUpdated(-1, -1), "failed to
load policies for service=dev_s3, appId=s3proxy");
+ assertNotNull(source.getServiceTagsIfUpdated(-1, -1), "failed to load
tags for service=dev_s3, appId=s3proxy");
+ assertNotNull(source.getRolesIfUpdated(-1, -1), "failed to load roles
for service=dev_s3, appId=s3proxy");
+ assertNotNull(source.getUserStoreIfUpdated(-1, -1), "failed to load
userStore for service=dev_s3, appId=s3proxy");
+ }
+
+ @Test
+ public void testLoadWithAppIdServiceNamePrefix() throws Exception {
+ RangerPolicySource source = getPolicySource("hive", "dev_hive",
"hiveServer2");
+
+ assertNotNull(source.getServicePoliciesIfUpdated(-1, -1), "failed to
load policies for service=dev_hive, appId=hiveServer2");
+ assertNotNull(source.getServiceTagsIfUpdated(-1, -1), "failed to load
tags for service=dev_hive, appId=hiveServer2");
+ assertNotNull(source.getRolesIfUpdated(-1, -1), "failed to load roles
for service=dev_hive, appId=hiveServer2");
+ assertNotNull(source.getUserStoreIfUpdated(-1, -1), "failed to load
userStore for service=dev_hive, appId=hiveServer2");
+ }
+
+ @Test
+ public void testLoadFailureWithNonExistingServiceName() throws Exception {
+ RangerPolicySource source = getPolicySource("s3", "test_s3", null);
+
+ assertThrows(Exception.class, () ->
source.getServicePoliciesIfUpdated(-1, -1), "expected to not find policies for
service=test_s3, appId=null");
+ assertThrows(Exception.class, () -> source.getServiceTagsIfUpdated(-1,
-1), "expected to not find tags for service=test_s3, appId=null");
+ assertThrows(Exception.class, () -> source.getRolesIfUpdated(-1, -1),
"expected to not find roles for service=test_s3, appId=null");
+ assertThrows(Exception.class, () -> source.getUserStoreIfUpdated(-1,
-1), "expected to not find userStore for service=test_s3, appId=null");
+ }
+
+ @Test
+ public void testLoadFailureWithNonExistingServiceNameAndAppId() throws
Exception {
+ RangerPolicySource source = getPolicySource("hive", "test_hive",
"trino");
+
+ assertThrows(Exception.class, () ->
source.getServicePoliciesIfUpdated(-1, -1), "expected to not find policies for
service=test_hive, appId=trino");
+ assertThrows(Exception.class, () -> source.getServiceTagsIfUpdated(-1,
-1), "expected to not find tags for service=test_hive, appId=trino");
+ assertThrows(Exception.class, () -> source.getRolesIfUpdated(-1, -1),
"expected to not find roles for service=test_hive, appId=trino");
+ assertThrows(Exception.class, () -> source.getUserStoreIfUpdated(-1,
-1), "expected to not find userStore for service=test_hive, appId=trino");
+ }
+
+ private RangerPolicySource getPolicySource(String serviceType, String
serviceName, String appId) {
+ String propPrefix = "ranger.plugin." + serviceType;
+ Configuration conf = new Configuration();
+
+ conf.set(propPrefix + ".policy.source.local_folder.path",
"src/test/resources/admin.client");
+
+ LocalFolderPolicySource source = new LocalFolderPolicySource();
+
+ source.init(serviceName, appId, propPrefix, conf);
+
+ return source;
+ }
+}
diff --git a/agents-common/src/test/resources/admin.client/dev_s3.json
b/agents-common/src/test/resources/admin.client/dev_s3.json
new file mode 100644
index 000000000..55b1640ee
--- /dev/null
+++ b/agents-common/src/test/resources/admin.client/dev_s3.json
@@ -0,0 +1,7 @@
+{
+ "serviceName": "dev_s3",
+ "policyVersion": 1,
+ "serviceDef": { },
+ "policies": [ ],
+ "tagPolicies": { }
+}
\ No newline at end of file
diff --git a/agents-common/src/test/resources/admin.client/dev_s3_roles.json
b/agents-common/src/test/resources/admin.client/dev_s3_roles.json
new file mode 100644
index 000000000..f7009de72
--- /dev/null
+++ b/agents-common/src/test/resources/admin.client/dev_s3_roles.json
@@ -0,0 +1,5 @@
+{
+ "serviceName": "dev_s3",
+ "roleVersion": 6,
+ "rangerRoles": []
+}
diff --git a/agents-common/src/test/resources/admin.client/dev_s3_tag.json
b/agents-common/src/test/resources/admin.client/dev_s3_tag.json
new file mode 100644
index 000000000..aad6df795
--- /dev/null
+++ b/agents-common/src/test/resources/admin.client/dev_s3_tag.json
@@ -0,0 +1,9 @@
+{
+ "serviceName": "dev_s3",
+ "tagVersion": 2,
+ "op": "add_or_update",
+ "tagDefinitions": { },
+ "tags": { },
+ "serviceResources": [ ],
+ "resourceToTagIds": { }
+}
\ No newline at end of file
diff --git
a/agents-common/src/test/resources/admin.client/dev_s3_userstore.json
b/agents-common/src/test/resources/admin.client/dev_s3_userstore.json
new file mode 100644
index 000000000..c307ee74f
--- /dev/null
+++ b/agents-common/src/test/resources/admin.client/dev_s3_userstore.json
@@ -0,0 +1,6 @@
+{
+ "userStoreVersion": 2,
+ "userAttrMapping": { },
+ "groupAttrMapping": { },
+ "userGroupMapping": { }
+}
\ No newline at end of file
diff --git
a/agents-common/src/test/resources/admin.client/hiveServer2_dev_hive.json
b/agents-common/src/test/resources/admin.client/hiveServer2_dev_hive.json
new file mode 100644
index 000000000..9dc482426
--- /dev/null
+++ b/agents-common/src/test/resources/admin.client/hiveServer2_dev_hive.json
@@ -0,0 +1,7 @@
+{
+ "serviceName": "dev_hive",
+ "policyVersion": 1,
+ "serviceDef": { },
+ "policies": [ ],
+ "tagPolicies": { }
+}
\ No newline at end of file
diff --git
a/agents-common/src/test/resources/admin.client/hiveServer2_dev_hive_roles.json
b/agents-common/src/test/resources/admin.client/hiveServer2_dev_hive_roles.json
new file mode 100644
index 000000000..0cb430e87
--- /dev/null
+++
b/agents-common/src/test/resources/admin.client/hiveServer2_dev_hive_roles.json
@@ -0,0 +1,5 @@
+{
+ "serviceName": "dev_hive",
+ "roleVersion": 6,
+ "rangerRoles": []
+}
diff --git
a/agents-common/src/test/resources/admin.client/hiveServer2_dev_hive_tag.json
b/agents-common/src/test/resources/admin.client/hiveServer2_dev_hive_tag.json
new file mode 100644
index 000000000..3bb7c60e5
--- /dev/null
+++
b/agents-common/src/test/resources/admin.client/hiveServer2_dev_hive_tag.json
@@ -0,0 +1,9 @@
+{
+ "serviceName": "dev_hive",
+ "tagVersion": 2,
+ "op": "add_or_update",
+ "tagDefinitions": { },
+ "tags": { },
+ "serviceResources": [ ],
+ "resourceToTagIds": { }
+}
\ No newline at end of file
diff --git
a/agents-common/src/test/resources/admin.client/hiveServer2_dev_hive_userstore.json
b/agents-common/src/test/resources/admin.client/hiveServer2_dev_hive_userstore.json
new file mode 100644
index 000000000..c307ee74f
--- /dev/null
+++
b/agents-common/src/test/resources/admin.client/hiveServer2_dev_hive_userstore.json
@@ -0,0 +1,6 @@
+{
+ "userStoreVersion": 2,
+ "userAttrMapping": { },
+ "groupAttrMapping": { },
+ "userGroupMapping": { }
+}
\ No newline at end of file
diff --git a/authz-embedded/src/test/resources/test_hive/hive_dev_hive.json
b/authz-embedded/src/test/resources/test_hive/dev_hive.json
similarity index 100%
rename from authz-embedded/src/test/resources/test_hive/hive_dev_hive.json
rename to authz-embedded/src/test/resources/test_hive/dev_hive.json
diff --git a/authz-embedded/src/test/resources/test_hive/hive_dev_hive_tag.json
b/authz-embedded/src/test/resources/test_hive/dev_hive_tag.json
similarity index 100%
rename from authz-embedded/src/test/resources/test_hive/hive_dev_hive_tag.json
rename to authz-embedded/src/test/resources/test_hive/dev_hive_tag.json
diff --git a/authz-embedded/src/test/resources/test_hive/hive_dev_hive_gds.json
b/authz-embedded/src/test/resources/test_hive/hive_dev_hive_gds.json
deleted file mode 100644
index 93807ed20..000000000
--- a/authz-embedded/src/test/resources/test_hive/hive_dev_hive_gds.json
+++ /dev/null
@@ -1,112 +0,0 @@
-{
- "serviceName": "dev_hive", "gdsVersion": 19,
- "datasets": [
- {
- "id": 1, "name": "ds1",
- "policies": [
- {
- "id": 41, "name": "DATASET: ds1", "version": 1,
- "resources": { "dataset-id": { "values": [ "1" ] } },
- "policyItems": [
- { "accesses": [ { "type": "_READ" } ], "users": [ "ds1-r-user" ] }
- ]
- }
- ]
- },
- {
- "id": 2, "name": "ds2",
- "policies": [
- {
- "id": 42, "name": "DATASET: ds2", "version": 1,
- "resources": { "dataset-id": { "values": [ "2" ] } },
- "policyItems": [
- { "accesses": [ { "type": "_READ" } ], "users": [ "ds2-r-user" ] }
- ]
- }
- ]
- },
- {
- "id": 3, "name": "ds3",
- "policies": [
- {
- "id": 43, "name": "DATASET: ds3", "version": 1,
- "resources": { "dataset-id": { "values": [ "3" ] } },
- "policyItems": [
- { "accesses": [ { "type": "_READ" } ], "users": [ "ds3-r-user" ] }
- ]
- }
- ]
- }
- ],
- "dataShares": [
- { "id": 1, "name": "hive-ds1", "defaultAccessTypes": [ "select" ] },
- { "id": 2, "name": "hive-ds2", "defaultAccessTypes": [ "select" ] },
- { "id": 3, "name": "hive-ds3", "defaultAccessTypes": [ "select" ] }
- ],
- "dshids": [
- { "dataShareId": 1, "datasetId": 1, "status": "ACTIVE" },
- { "dataShareId": 2, "datasetId": 2, "status": "ACTIVE" },
- { "dataShareId": 3, "datasetId": 3, "status": "ACTIVE" }
- ],
- "resources": [
- {
- "id": 1, "name": "mydb.tbl_ds1", "dataShareId": 1,
- "resource": { "database": { "values": [ "mydb" ] }, "table": { "values":
[ "tbl_ds1" ] } }
- },
- {
- "id": 2, "name": "mydb.tbl_ds2", "dataShareId": 2,
- "resource": { "database": { "values": [ "mydb" ] }, "table": { "values":
[ "tbl_ds2" ] } }
- },
- {
- "id": 3, "name": "mydb.tbl_ds3", "dataShareId": 3,
- "resource": { "database": { "values": [ "mydb" ] }, "table": { "values":
[ "tbl_ds3" ] } }, "subResource": { "values": [ "col1", "col2", "col3" ] },
"subResourceType": "column",
- "rowFilter": { "filterExpr": "year = current_year()" },
- "subResourceMasks": [
- { "values": [ "col1" ], "maskInfo": { "dataMaskType": "MASK_HASH" } }
- ]
- }
- ],
- "gdsServiceDef": {
- "id": 207, "name": "gds", "label": "GDS", "description": "GDS Service
Definition", "displayName": "Governed Data Sharing", "implClass":
"org.apache.ranger.services.gds.RangerServiceGds", "version": 1,
- "resources": [
- {
- "itemId": 1, "name": "dataset-id", "label": "Dataset ID",
"description": "Dataset ID", "level": 1, "type": "string",
- "excludesSupported": false, "isValidLeaf": true, "lookupSupported":
false, "mandatory": true, "recursiveSupported": false,
- "matcher":
"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
"matcherOptions": { "ignoreCase": "false", "wildCard": "false" },
- "uiHint": "{ \"singleValue\": true }"
- },
- {
- "itemId": 2, "name": "project-id", "label": "Project ID",
"description": "Project ID", "level": 1, "type": "string",
- "excludesSupported": false, "isValidLeaf": true, "lookupSupported":
false, "mandatory": true, "recursiveSupported": false,
- "matcher":
"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
"matcherOptions": { "ignoreCase": "false", "wildCard": "false" },
- "uiHint": "{ \"singleValue\": true }"
- }
- ],
- "accessTypes": [
- { "itemId": 1, "name": "_CREATE", "label": "_CREATE" },
- { "itemId": 2, "name": "_READ", "label": "_READ" },
- { "itemId": 3, "name": "_UPDATE", "label": "_UPDATE" },
- { "itemId": 4, "name": "_DELETE", "label": "_DELETE" },
- { "itemId": 5, "name": "_MANAGE", "label": "_MANAGE" },
- { "itemId": 6, "name": "_ALL", "label": "_ALL" }
- ],
- "markerAccessTypes": [
- { "itemId": 7, "name": "_CREATE", "label": "_CREATE" },
- { "itemId": 8, "name": "_READ", "label": "_READ" },
- { "itemId": 9, "name": "_UPDATE", "label": "_UPDATE" },
- { "itemId": 10, "name": "_DELETE", "label": "_DELETE" },
- { "itemId": 11, "name": "_MANAGE", "label": "_MANAGE" },
- { "itemId": 12, "name": "_ALL", "label": "_ALL" }
- ],
- "policyConditions": [
- {
- "itemId": 1, "name": "expression", "label": "Enter boolean
expression", "description": "Boolean expression",
- "evaluator":
"org.apache.ranger.plugin.conditionevaluator.RangerScriptConditionEvaluator",
"evaluatorOptions": { "engineName": "JavaScript", "ui.isMultiline": "true" }
- },
- {
- "itemId": 2, "name": "validitySchedule", "label": "Validity
schedule", "description": "Validity schedule",
- "evaluator":
"org.apache.ranger.plugin.conditionevaluator.RangerValidityScheduleConditionEvaluator"
- }
- ]
- }
-}
diff --git a/authz-embedded/src/test/resources/test_hive/tests_authz.json
b/authz-embedded/src/test/resources/test_hive/tests_authz.json
index 1d25ef073..765ffe080 100644
--- a/authz-embedded/src/test/resources/test_hive/tests_authz.json
+++ b/authz-embedded/src/test/resources/test_hive/tests_authz.json
@@ -562,268 +562,5 @@
"update": { "permission": "update", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
}
}
- },
-
-
- {
- "comment": "tests for tbl mydb/tbl_ds1"
- },
- {
- "request": {
- "requestId": "ds1-r-user select mydb/tbl_ds1",
- "user": { "name": "ds1-r-user" },
- "access": { "resource": { "name": "table:mydb/tbl_ds1" }, "action":
"select", "permissions": [ "select" ] },
- "context": { "serviceName": "dev_hive" }
- },
- "result": {
- "requestId": "ds1-r-user select mydb/tbl_ds1",
- "decision": "ALLOW",
- "permissions": {
- "select": { "permission": "select", "access": { "decision": "ALLOW",
"policy": { "id": 41, "version": 1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "ds1-r-user update mydb/tbl_ds1",
- "user": { "name": "ds1-r-user" },
- "access": { "resource": { "name": "table:mydb/tbl_ds1" }, "action":
"update", "permissions": [ "update" ] },
- "context": { "serviceName": "dev_hive" }
- },
- "result": {
- "requestId": "ds1-r-user update mydb/tbl_ds1",
- "decision": "DENY",
- "permissions": {
- "update": { "permission": "update", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "ds1-r-user select,update mydb/tbl_ds1",
- "user": { "name": "ds1-r-user" },
- "access": { "resource": { "name": "table:mydb/tbl_ds1" }, "action":
"update", "permissions": [ "select", "update" ] },
- "context": { "serviceName": "dev_hive" }
- },
- "result": {
- "requestId": "ds1-r-user select,update mydb/tbl_ds1",
- "decision": "DENY",
- "permissions": {
- "select": { "permission": "select", "access": { "decision": "ALLOW",
"policy": { "id": 41, "version": 1 } } },
- "update": { "permission": "update", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "ds2-r-user select mydb/tbl_ds1",
- "user": { "name": "ds2-r-user" },
- "access": { "resource": { "name": "table:mydb/tbl_ds1" }, "action":
"select", "permissions": [ "select" ] },
- "context": { "serviceName": "dev_hive" }
- },
- "result": {
- "requestId": "ds2-r-user select mydb/tbl_ds1",
- "decision": "DENY",
- "permissions": {
- "select": { "permission": "select", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "ds2-r-user update mydb/tbl_ds1",
- "user": { "name": "ds2-r-user" },
- "access": { "resource": { "name": "table:mydb/tbl_ds1" }, "action":
"update", "permissions": [ "update" ] },
- "context": { "serviceName": "dev_hive" }
- },
- "result": {
- "requestId": "ds2-r-user update mydb/tbl_ds1",
- "decision": "DENY",
- "permissions": {
- "update": { "permission": "update", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "all-tbl-r-user select mydb/tbl_ds1",
- "user": { "name": "all-tbl-r-user" },
- "access": { "resource": { "name": "table:mydb/tbl_ds1" }, "action":
"select", "permissions": [ "select" ] },
- "context": { "serviceName": "dev_hive" }
- },
- "result": {
- "requestId": "all-tbl-r-user select mydb/tbl_ds1",
- "decision": "ALLOW",
- "permissions": {
- "select": { "permission": "select", "access": { "decision": "ALLOW",
"policy": { "id": 3, "version": 2 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "all-tbl-r-user update mydb/tbl_ds1",
- "user": { "name": "all-tbl-r-user" },
- "access": { "resource": { "name": "table:mydb/tbl_ds1" }, "action":
"update", "permissions": [ "update" ] },
- "context": { "serviceName": "dev_hive" }
- },
- "result": {
- "requestId": "all-tbl-r-user update mydb/tbl_ds1",
- "decision": "DENY",
- "permissions": {
- "update": { "permission": "update", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
-
-
- {
- "comment": "tests for tbl mydb/tbl_ds2"
- },
- {
- "request": {
- "requestId": "ds2-r-user select mydb/tbl_ds2",
- "user": { "name": "ds2-r-user" },
- "access": { "resource": { "name": "table:mydb/tbl_ds2" }, "action":
"select", "permissions": [ "select" ] },
- "context": { "serviceName": "dev_hive" }
- },
- "result": {
- "requestId": "ds2-r-user select mydb/tbl_ds2",
- "decision": "ALLOW",
- "permissions": {
- "select": { "permission": "select", "access": { "decision": "ALLOW",
"policy": { "id": 42, "version": 1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "ds2-r-user update mydb/tbl_ds2",
- "user": { "name": "ds2-r-user" },
- "access": { "resource": { "name": "table:mydb/tbl_ds2" }, "action":
"update", "permissions": [ "update" ] },
- "context": { "serviceName": "dev_hive" }
- },
- "result": {
- "requestId": "ds2-r-user update mydb/tbl_ds2",
- "decision": "DENY",
- "permissions": {
- "update": { "permission": "update", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "ds2-r-user select,update mydb/tbl_ds2",
- "user": { "name": "ds2-r-user" },
- "access": { "resource": { "name": "table:mydb/tbl_ds2" }, "action":
"update", "permissions": [ "select", "update" ] },
- "context": { "serviceName": "dev_hive" }
- },
- "result": {
- "requestId": "ds2-r-user select,update mydb/tbl_ds2",
- "decision": "DENY",
- "permissions": {
- "select": { "permission": "select", "access": { "decision": "ALLOW",
"policy": { "id": 42, "version": 1 } } },
- "update": { "permission": "update", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "ds1-r-user select mydb/tbl_ds2",
- "user": { "name": "ds1-r-user" },
- "access": { "resource": { "name": "table:mydb/tbl_ds2" }, "action":
"select", "permissions": [ "select" ] },
- "context": { "serviceName": "dev_hive" }
- },
- "result": {
- "requestId": "ds1-r-user select mydb/tbl_ds2",
- "decision": "DENY",
- "permissions": {
- "select": { "permission": "select", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "ds1-r-user update mydb/tbl_ds2",
- "user": { "name": "ds1-r-user" },
- "access": { "resource": { "name": "table:mydb/tbl_ds2" }, "action":
"update", "permissions": [ "update" ] },
- "context": { "serviceName": "dev_hive" }
- },
- "result": {
- "requestId": "ds1-r-user update mydb/tbl_ds2",
- "decision": "DENY",
- "permissions": {
- "update": { "permission": "update", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "all-tbl-r-user select mydb/tbl_ds2",
- "user": { "name": "all-tbl-r-user" },
- "access": { "resource": { "name": "table:mydb/tbl_ds2" }, "action":
"select", "permissions": [ "select" ] },
- "context": { "serviceName": "dev_hive" }
- },
- "result": {
- "requestId": "all-tbl-r-user select mydb/tbl_ds2",
- "decision": "ALLOW",
- "permissions": {
- "select": { "permission": "select", "access": { "decision": "ALLOW",
"policy": { "id": 3, "version": 2 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "all-tbl-r-user update mydb/tbl_ds2",
- "user": { "name": "all-tbl-r-user" },
- "access": { "resource": { "name": "table:mydb/tbl_ds2" }, "action":
"update", "permissions": [ "update" ] },
- "context": { "serviceName": "dev_hive" }
- },
- "result": {
- "requestId": "all-tbl-r-user update mydb/tbl_ds2",
- "decision": "DENY",
- "permissions": {
- "update": { "permission": "update", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
-
- {
- "comment": "tests for tbl mydb/tbl_ds3"
- },
- {
- "request": {
- "requestId": "ds3-r-user select mydb/tbl_ds3",
- "user": { "name": "ds3-r-user" },
- "access": { "resource": { "name": "table:mydb/tbl_ds3" }, "action":
"select", "permissions": [ "select" ] },
- "context": { "serviceName": "dev_hive" }
- },
- "result": {
- "requestId": "ds3-r-user select mydb/tbl_ds3",
- "decision": "DENY",
- "permissions": {
- "select": { "permission": "select", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "ds3-r-user select mydb/tbl_ds3 col1,col2,col3",
- "user": { "name": "ds3-r-user" },
- "access": { "resource": { "name": "table:mydb/tbl_ds3",
"subResources": [ "column:col1", "column:col2", "column:col3" ] }, "action":
"select", "permissions": [ "select" ] },
- "context": { "serviceName": "dev_hive" }
- },
- "result": {
- "requestId": "ds3-r-user select mydb/tbl_ds3 col1,col2,col3",
- "decision": "ALLOW",
- "permissions": {
- "select": {
- "permission": "select", "access": { "decision": "ALLOW", "policy": {
"id": 43, "version": 1 } }, "rowFilter": { "filterExpr": "year =
current_year()", "policy": { "id": 43, "version": 1 } },
- "subResources": {
- "column:col1": { "permission": "select", "access": { "decision":
"ALLOW", "policy": { "id": 43, "version": 1 } }, "dataMask": { "maskType":
"MASK_HASH", "policy": { "id": 43, "version": 1 } } },
- "column:col2": { "permission": "select", "access": { "decision":
"ALLOW", "policy": { "id": 43, "version": 1 } } },
- "column:col3": { "permission": "select", "access": { "decision":
"ALLOW", "policy": { "id": 43, "version": 1 } } }
- }
- }
- }
- }
}
]
diff --git
a/authz-embedded/src/test/resources/test_hive/tests_resource_permissions.json
b/authz-embedded/src/test/resources/test_hive/tests_resource_permissions.json
index 0fee56e66..d481c5212 100644
---
a/authz-embedded/src/test/resources/test_hive/tests_resource_permissions.json
+++
b/authz-embedded/src/test/resources/test_hive/tests_resource_permissions.json
@@ -80,62 +80,5 @@
}
}
}
- },
- {
- "resource": { "name": "table:mydb/tbl_ds1" },
- "context": { "serviceName": "dev_hive" },
- "permissions": {
- "resource": { "name": "table:mydb/tbl_ds1" },
- "users": {
- "all-tbl-r-user": {
- "select": { "permission": "select", "access": { "decision":
"ALLOW", "policy": { "id": 3, "version": 2 } } }
- },
- "ds1-r-user": {
- "select": { "permission": "select", "access": { "decision":
"ALLOW", "policy": { "id": 41, "version": 1 } } }
- }
- }
- }
- },
- {
- "resource": { "name": "table:mydb/tbl_ds2" },
- "context": { "serviceName": "dev_hive" },
- "permissions": {
- "resource": { "name": "table:mydb/tbl_ds2" },
- "users": {
- "all-tbl-r-user": {
- "select": { "permission": "select", "access": { "decision":
"ALLOW", "policy": { "id": 3, "version": 2 } } }
- },
- "ds2-r-user": {
- "select": { "permission": "select", "access": { "decision":
"ALLOW", "policy": { "id": 42, "version": 1 } } }
- }
- }
- }
- },
- {
- "resource": { "name": "table:mydb/tbl_ds3" },
- "context": { "serviceName": "dev_hive" },
- "permissions": {
- "resource": { "name": "table:mydb/tbl_ds3" },
- "users": {
- "all-tbl-r-user": {
- "select": { "permission": "select", "access": { "decision":
"ALLOW", "policy": { "id": 3, "version": 2 } } }
- }
- }
- }
- },
- {
- "resource": { "name": "column:mydb/tbl_ds3/col1" },
- "context": { "serviceName": "dev_hive" },
- "permissions": {
- "resource": { "name": "column:mydb/tbl_ds3/col1" },
- "users": {
- "all-tbl-r-user": {
- "select": { "permission": "select", "access": { "decision":
"ALLOW", "policy": { "id": 3, "version": 2 } } }
- },
- "ds3-r-user": {
- "select": { "permission": "select", "access": { "decision":
"ALLOW", "policy": { "id": 43, "version": 1 } }, "dataMask": null }
- }
- }
- }
}
]
diff --git a/authz-embedded/src/test/resources/test_s3/s3_dev_s3.json
b/authz-embedded/src/test/resources/test_s3/dev_s3.json
similarity index 100%
rename from authz-embedded/src/test/resources/test_s3/s3_dev_s3.json
rename to authz-embedded/src/test/resources/test_s3/dev_s3.json
diff --git a/authz-embedded/src/test/resources/test_s3/s3_dev_s3_roles.json
b/authz-embedded/src/test/resources/test_s3/dev_s3_roles.json
similarity index 100%
rename from authz-embedded/src/test/resources/test_s3/s3_dev_s3_roles.json
rename to authz-embedded/src/test/resources/test_s3/dev_s3_roles.json
diff --git a/authz-embedded/src/test/resources/test_s3/s3_dev_s3_tag.json
b/authz-embedded/src/test/resources/test_s3/dev_s3_tag.json
similarity index 100%
rename from authz-embedded/src/test/resources/test_s3/s3_dev_s3_tag.json
rename to authz-embedded/src/test/resources/test_s3/dev_s3_tag.json
diff --git a/authz-embedded/src/test/resources/test_s3/s3_dev_s3_gds.json
b/authz-embedded/src/test/resources/test_s3/s3_dev_s3_gds.json
deleted file mode 100644
index 3a474e8b8..000000000
--- a/authz-embedded/src/test/resources/test_s3/s3_dev_s3_gds.json
+++ /dev/null
@@ -1,90 +0,0 @@
-{
- "serviceName": "dev_s3", "gdsVersion": 19,
- "datasets": [
- {
- "id": 1, "name": "ds1",
- "policies": [
- {
- "id": 41, "name": "DATASET: ds1", "version": 1,
- "resources": { "dataset-id": { "values": [ "1" ] } },
- "policyItems": [
- { "accesses": [ { "type": "_READ" } ], "users": [ "ds1-r-user" ] }
- ]
- }
- ]
- },
- {
- "id": 2, "name": "ds2",
- "policies": [
- {
- "id": 42, "name": "DATASET: ds2", "version": 1,
- "resources": { "dataset-id": { "values": [ "2" ] } },
- "policyItems": [
- { "accesses": [ { "type": "_READ" } ], "users": [ "ds2-r-user" ] }
- ]
- }
- ]
- }
- ],
- "dataShares": [
- { "id": 1, "name": "s3-ds1", "defaultAccessTypes": [ "read" ] },
- { "id": 2, "name": "s3-ds2", "defaultAccessTypes": [ "read" ] }
- ],
- "dshids": [
- { "dataShareId": 1, "datasetId": 1, "status": "ACTIVE" },
- { "dataShareId": 2, "datasetId": 2, "status": "ACTIVE" }
- ],
- "resources": [
- {
- "id": 1, "name": "mybucket/data/ds1", "dataShareId": 1,
- "resource": { "bucket": { "values": [ "mybucket" ] }, "path": {
"values": [ "data/ds1" ], "isRecursive": true } }
- },
- {
- "id": 2, "name": "mybucket/data/ds2", "dataShareId": 2,
- "resource": { "bucket": { "values": [ "mybucket" ] }, "path": {
"values": [ "data/ds2" ], "isRecursive": true } }
- }
- ],
- "gdsServiceDef": {
- "id": 207, "name": "gds", "label": "GDS", "description": "GDS Service
Definition", "displayName": "Governed Data Sharing", "implClass":
"org.apache.ranger.services.gds.RangerServiceGds", "version": 1,
- "resources": [
- {
- "itemId": 1, "name": "dataset-id", "label": "Dataset ID",
"description": "Dataset ID", "level": 1, "type": "string",
- "excludesSupported": false, "isValidLeaf": true, "lookupSupported":
false, "mandatory": true, "recursiveSupported": false,
- "matcher":
"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
"matcherOptions": { "ignoreCase": "false", "wildCard": "false" },
- "uiHint": "{ \"singleValue\": true }"
- },
- {
- "itemId": 2, "name": "project-id", "label": "Project ID",
"description": "Project ID", "level": 1, "type": "string",
- "excludesSupported": false, "isValidLeaf": true, "lookupSupported":
false, "mandatory": true, "recursiveSupported": false,
- "matcher":
"org.apache.ranger.plugin.resourcematcher.RangerDefaultResourceMatcher",
"matcherOptions": { "ignoreCase": "false", "wildCard": "false" },
- "uiHint": "{ \"singleValue\": true }"
- }
- ],
- "accessTypes": [
- { "itemId": 1, "name": "_CREATE", "label": "_CREATE" },
- { "itemId": 2, "name": "_READ", "label": "_READ" },
- { "itemId": 3, "name": "_UPDATE", "label": "_UPDATE" },
- { "itemId": 4, "name": "_DELETE", "label": "_DELETE" },
- { "itemId": 5, "name": "_MANAGE", "label": "_MANAGE" },
- { "itemId": 6, "name": "_ALL", "label": "_ALL" }
- ],
- "markerAccessTypes": [
- { "itemId": 7, "name": "_CREATE", "label": "_CREATE" },
- { "itemId": 8, "name": "_READ", "label": "_READ" },
- { "itemId": 9, "name": "_UPDATE", "label": "_UPDATE" },
- { "itemId": 10, "name": "_DELETE", "label": "_DELETE" },
- { "itemId": 11, "name": "_MANAGE", "label": "_MANAGE" },
- { "itemId": 12, "name": "_ALL", "label": "_ALL" }
- ],
- "policyConditions": [
- {
- "itemId": 1, "name": "expression", "label": "Enter boolean
expression", "description": "Boolean expression",
- "evaluator":
"org.apache.ranger.plugin.conditionevaluator.RangerScriptConditionEvaluator",
"evaluatorOptions": { "engineName": "JavaScript", "ui.isMultiline": "true" }
- },
- {
- "itemId": 2, "name": "validitySchedule", "label": "Validity
schedule", "description": "Validity schedule",
- "evaluator":
"org.apache.ranger.plugin.conditionevaluator.RangerValidityScheduleConditionEvaluator"
- }
- ]
- }
-}
diff --git a/authz-embedded/src/test/resources/test_s3/tests_authz.json
b/authz-embedded/src/test/resources/test_s3/tests_authz.json
index aa9da7d63..42d48e2f6 100644
--- a/authz-embedded/src/test/resources/test_s3/tests_authz.json
+++ b/authz-embedded/src/test/resources/test_s3/tests_authz.json
@@ -562,227 +562,5 @@
"write": { "permission": "write", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
}
}
- },
-
-
- {
- "comment": "tests for path mybucket/data/ds1/file.orc"
- },
- {
- "request": {
- "requestId": "ds1-r-user read mybucket/data/ds1/file.orc",
- "user": { "name": "ds1-r-user" },
- "access": { "resource": { "name": "path:mybucket/data/ds1/file.orc"
}, "action": "read", "permissions": [ "read" ] },
- "context": { "serviceName": "dev_s3" }
- },
- "result": {
- "requestId": "ds1-r-user read mybucket/data/ds1/file.orc",
- "decision": "ALLOW",
- "permissions": {
- "read": { "permission": "read", "access": { "decision": "ALLOW",
"policy": { "id": 41, "version": 1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "ds1-r-user write mybucket/data/ds1/file.orc",
- "user": { "name": "ds1-r-user" },
- "access": { "resource": { "name": "path:mybucket/data/ds1/file.orc"
}, "action": "write", "permissions": [ "write" ] },
- "context": { "serviceName": "dev_s3" }
- },
- "result": {
- "requestId": "ds1-r-user write mybucket/data/ds1/file.orc",
- "decision": "DENY",
- "permissions": {
- "write": { "permission": "write", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "ds1-r-user read,write mybucket/data/ds1/file.orc",
- "user": { "name": "ds1-r-user" },
- "access": { "resource": { "name": "path:mybucket/data/ds1/file.orc"
}, "action": "update", "permissions": [ "read", "write" ] },
- "context": { "serviceName": "dev_s3" }
- },
- "result": {
- "requestId": "ds1-r-user read,write mybucket/data/ds1/file.orc",
- "decision": "DENY",
- "permissions": {
- "read": { "permission": "read", "access": { "decision": "ALLOW",
"policy": { "id": 41, "version": 1 } } },
- "write": { "permission": "write", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "ds2-r-user read mybucket/data/ds1/file.orc",
- "user": { "name": "ds2-r-user" },
- "access": { "resource": { "name": "path:mybucket/data/ds1/file.orc"
}, "action": "read", "permissions": [ "read" ] },
- "context": { "serviceName": "dev_s3" }
- },
- "result": {
- "requestId": "ds2-r-user read mybucket/data/ds1/file.orc",
- "decision": "DENY",
- "permissions": {
- "read": { "permission": "read", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "ds2-r-user write mybucket/data/ds1/file.orc",
- "user": { "name": "ds2-r-user" },
- "access": { "resource": { "name": "path:mybucket/data/ds1/file.orc"
}, "action": "write", "permissions": [ "write" ] },
- "context": { "serviceName": "dev_s3" }
- },
- "result": {
- "requestId": "ds2-r-user write mybucket/data/ds1/file.orc",
- "decision": "DENY",
- "permissions": {
- "write": { "permission": "write", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "all-path-r-user read mybucket/data/ds1/file.orc",
- "user": { "name": "all-path-r-user" },
- "access": { "resource": { "name": "path:mybucket/data/ds1/file.orc"
}, "action": "read", "permissions": [ "read" ] },
- "context": { "serviceName": "dev_s3" }
- },
- "result": {
- "requestId": "all-path-r-user read mybucket/data/ds1/file.orc",
- "decision": "ALLOW",
- "permissions": {
- "read": { "permission": "read", "access": { "decision": "ALLOW",
"policy": { "id": 3, "version": 2 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "all-path-r-user write mybucket/data/ds1/file.orc",
- "user": { "name": "all-path-r-user" },
- "access": { "resource": { "name": "path:mybucket/data/ds1/file.orc"
}, "action": "write", "permissions": [ "write" ] },
- "context": { "serviceName": "dev_s3" }
- },
- "result": {
- "requestId": "all-path-r-user write mybucket/data/ds1/file.orc",
- "decision": "DENY",
- "permissions": {
- "write": { "permission": "write", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
-
-
- {
- "comment": "tests for path mybucket/data/ds2/file.orc"
- },
- {
- "request": {
- "requestId": "ds2-r-user read mybucket/data/ds2/file.orc",
- "user": { "name": "ds2-r-user" },
- "access": { "resource": { "name": "path:mybucket/data/ds2/file.orc"
}, "action": "read", "permissions": [ "read" ] },
- "context": { "serviceName": "dev_s3" }
- },
- "result": {
- "requestId": "ds2-r-user read mybucket/data/ds2/file.orc",
- "decision": "ALLOW",
- "permissions": {
- "read": { "permission": "read", "access": { "decision": "ALLOW",
"policy": { "id": 42, "version": 1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "ds2-r-user write mybucket/data/ds2/file.orc",
- "user": { "name": "ds2-r-user" },
- "access": { "resource": { "name": "path:mybucket/data/ds2/file.orc"
}, "action": "write", "permissions": [ "write" ] },
- "context": { "serviceName": "dev_s3" }
- },
- "result": {
- "requestId": "ds2-r-user write mybucket/data/ds2/file.orc",
- "decision": "DENY",
- "permissions": {
- "write": { "permission": "write", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "ds2-r-user read,write mybucket/data/ds2/file.orc",
- "user": { "name": "ds2-r-user" },
- "access": { "resource": { "name": "path:mybucket/data/ds2/file.orc"
}, "action": "update", "permissions": [ "read", "write" ] },
- "context": { "serviceName": "dev_s3" }
- },
- "result": {
- "requestId": "ds2-r-user read,write mybucket/data/ds2/file.orc",
- "decision": "DENY",
- "permissions": {
- "read": { "permission": "read", "access": { "decision": "ALLOW",
"policy": { "id": 42, "version": 1 } } },
- "write": { "permission": "write", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "ds1-r-user read mybucket/data/ds2/file.orc",
- "user": { "name": "ds1-r-user" },
- "access": { "resource": { "name": "path:mybucket/data/ds2/file.orc"
}, "action": "read", "permissions": [ "read" ] },
- "context": { "serviceName": "dev_s3" }
- },
- "result": {
- "requestId": "ds1-r-user read mybucket/data/ds2/file.orc",
- "decision": "DENY",
- "permissions": {
- "read": { "permission": "read", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "ds1-r-user write mybucket/data/ds2/file.orc",
- "user": { "name": "ds1-r-user" },
- "access": { "resource": { "name": "path:mybucket/data/ds2/file.orc"
}, "action": "write", "permissions": [ "write" ] },
- "context": { "serviceName": "dev_s3" }
- },
- "result": {
- "requestId": "ds1-r-user write mybucket/data/ds2/file.orc",
- "decision": "DENY",
- "permissions": {
- "write": { "permission": "write", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "all-path-r-user read mybucket/data/ds2/file.orc",
- "user": { "name": "all-path-r-user" },
- "access": { "resource": { "name": "path:mybucket/data/ds2/file.orc"
}, "action": "read", "permissions": [ "read" ] },
- "context": { "serviceName": "dev_s3" }
- },
- "result": {
- "requestId": "all-path-r-user read mybucket/data/ds2/file.orc",
- "decision": "ALLOW",
- "permissions": {
- "read": { "permission": "read", "access": { "decision": "ALLOW",
"policy": { "id": 3, "version": 2 } } }
- }
- }
- },
- {
- "request": {
- "requestId": "all-path-r-user write mybucket/data/ds2/file.orc",
- "user": { "name": "all-path-r-user" },
- "access": { "resource": { "name": "path:mybucket/data/ds2/file.orc"
}, "action": "write", "permissions": [ "write" ] },
- "context": { "serviceName": "dev_s3" }
- },
- "result": {
- "requestId": "all-path-r-user write mybucket/data/ds2/file.orc",
- "decision": "DENY",
- "permissions": {
- "write": { "permission": "write", "access": { "decision": "DENY",
"policy": { "id": -1 } } }
- }
- }
}
]
\ No newline at end of file
diff --git
a/authz-embedded/src/test/resources/test_s3/tests_resource_permissions.json
b/authz-embedded/src/test/resources/test_s3/tests_resource_permissions.json
index a4b458644..4e0c77cf7 100644
--- a/authz-embedded/src/test/resources/test_s3/tests_resource_permissions.json
+++ b/authz-embedded/src/test/resources/test_s3/tests_resource_permissions.json
@@ -80,35 +80,5 @@
}
}
}
- },
- {
- "resource": { "name": "path:mybucket/data/ds1/file.orc" },
- "context": { "serviceName": "dev_s3" },
- "permissions": {
- "resource": { "name": "path:mybucket/data/ds1/file.orc" },
- "users": {
- "all-path-r-user": {
- "read": { "permission": "read", "access": { "decision": "ALLOW",
"policy": { "id": 3, "version": 2 } } }
- },
- "ds1-r-user": {
- "read": { "permission": "read", "access": { "decision": "ALLOW",
"policy": { "id": 41, "version": 1 } } }
- }
- }
- }
- },
- {
- "resource": { "name": "path:mybucket/data/ds2/file.orc" },
- "context": { "serviceName": "dev_s3" },
- "permissions": {
- "resource": { "name": "path:mybucket/data/ds2/file.orc" },
- "users": {
- "all-path-r-user": {
- "read": { "permission": "read", "access": { "decision": "ALLOW",
"policy": { "id": 3, "version": 2 } } }
- },
- "ds2-r-user": {
- "read": { "permission": "read", "access": { "decision": "ALLOW",
"policy": { "id": 42, "version": 1 } } }
- }
- }
- }
}
]
\ No newline at end of file