This is an automated email from the ASF dual-hosted git repository.
madhan pushed a commit to branch ranger-2.7
in repository https://gitbox.apache.org/repos/asf/ranger.git
The following commit(s) were added to refs/heads/ranger-2.7 by this push:
new cd82fe269 RANGER-5216: added unit tests for Atlas authorizer (#581)
cd82fe269 is described below
commit cd82fe269d9787962aa377112098ce21c14fb421
Author: Madhan Neethiraj <[email protected]>
AuthorDate: Thu May 29 09:34:47 2025 -0700
RANGER-5216: added unit tests for Atlas authorizer (#581)
(cherry picked from commit 109dc779e46090f8f4869a24b213b3ebd8751fe2)
---
plugin-atlas/pom.xml | 12 +
.../atlas/authorizer/RangerAtlasAuthorizer.java | 19 +-
.../authorizer/TestRangerAtlasAuthorizer.java | 522 +++++++++++++++++++++
.../atlas/testutil/RangerAdminClientImpl.java | 45 ++
.../test/resources/atlas-application.properties | 18 +
.../src/test/resources/atlas-policies.json | 181 +++++++
plugin-atlas/src/test/resources/logback.xml | 22 +
.../src/test/resources/ranger-atlas-security.xml | 37 ++
pom.xml | 1 +
9 files changed, 847 insertions(+), 10 deletions(-)
diff --git a/plugin-atlas/pom.xml b/plugin-atlas/pom.xml
index ca99bbfcf..0aa45164a 100644
--- a/plugin-atlas/pom.xml
+++ b/plugin-atlas/pom.xml
@@ -89,5 +89,17 @@
<artifactId>ranger-plugins-common</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <version>${assertj.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-api</artifactId>
+ <version>${junit.jupiter.version}</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git
a/plugin-atlas/src/main/java/org/apache/ranger/authorization/atlas/authorizer/RangerAtlasAuthorizer.java
b/plugin-atlas/src/main/java/org/apache/ranger/authorization/atlas/authorizer/RangerAtlasAuthorizer.java
index 4570442ab..daa974fe8 100644
---
a/plugin-atlas/src/main/java/org/apache/ranger/authorization/atlas/authorizer/RangerAtlasAuthorizer.java
+++
b/plugin-atlas/src/main/java/org/apache/ranger/authorization/atlas/authorizer/RangerAtlasAuthorizer.java
@@ -21,7 +21,6 @@
import org.apache.atlas.authorize.AtlasAdminAccessRequest;
-import org.apache.atlas.authorize.AtlasAuthorizationException;
import org.apache.atlas.authorize.AtlasEntityAccessRequest;
import org.apache.atlas.authorize.AtlasSearchResultScrubRequest;
import org.apache.atlas.authorize.AtlasRelationshipAccessRequest;
@@ -101,7 +100,7 @@ public void cleanUp() {
}
@Override
- public boolean isAccessAllowed(AtlasAdminAccessRequest request) throws
AtlasAuthorizationException {
+ public boolean isAccessAllowed(AtlasAdminAccessRequest request) {
if (LOG.isDebugEnabled()) {
LOG.debug("==> isAccessAllowed(" + request + ")");
}
@@ -138,7 +137,7 @@ public boolean isAccessAllowed(AtlasAdminAccessRequest
request) throws AtlasAuth
}
@Override
- public boolean isAccessAllowed(AtlasEntityAccessRequest request) throws
AtlasAuthorizationException {
+ public boolean isAccessAllowed(AtlasEntityAccessRequest request) {
if (LOG.isDebugEnabled()) {
LOG.debug("==> isAccessAllowed(" + request + ")");
}
@@ -170,7 +169,7 @@ public boolean isAccessAllowed(AtlasEntityAccessRequest
request) throws AtlasAut
}
@Override
- public boolean isAccessAllowed(AtlasTypeAccessRequest request) throws
AtlasAuthorizationException {
+ public boolean isAccessAllowed(AtlasTypeAccessRequest request) {
if (LOG.isDebugEnabled()) {
LOG.debug("==> isAccessAllowed(" + request + ")");
}
@@ -220,7 +219,7 @@ public boolean isAccessAllowed(AtlasTypeAccessRequest
request) throws AtlasAutho
- public boolean isAccessAllowed(AtlasRelationshipAccessRequest request)
throws AtlasAuthorizationException {
+ public boolean isAccessAllowed(AtlasRelationshipAccessRequest request) {
if (LOG.isDebugEnabled()) {
LOG.debug("==> isAccessAllowed(" + request + ")");
}
@@ -293,7 +292,7 @@ public boolean
isAccessAllowed(AtlasRelationshipAccessRequest request) throws At
@Override
- public void scrubSearchResults(AtlasSearchResultScrubRequest request)
throws AtlasAuthorizationException {
+ public void scrubSearchResults(AtlasSearchResultScrubRequest request) {
if (LOG.isDebugEnabled()) {
LOG.debug("==> scrubSearchResults(" + request + ")");
}
@@ -336,7 +335,7 @@ public void
scrubSearchResults(AtlasSearchResultScrubRequest request) throws Atl
}
@Override
- public void filterTypesDef(AtlasTypesDefFilterRequest request) throws
AtlasAuthorizationException {
+ public void filterTypesDef(AtlasTypesDefFilterRequest request) {
AtlasTypesDef typesDef = request.getTypesDef();
@@ -349,7 +348,7 @@ public void filterTypesDef(AtlasTypesDefFilterRequest
request) throws AtlasAutho
}
- private void filterTypes(AtlasAccessRequest request, List<? extends
AtlasBaseTypeDef> typeDefs)throws AtlasAuthorizationException {
+ private void filterTypes(AtlasAccessRequest request, List<? extends
AtlasBaseTypeDef> typeDefs) {
if (typeDefs != null) {
for (ListIterator<? extends AtlasBaseTypeDef> iter =
typeDefs.listIterator(); iter.hasNext();) {
AtlasBaseTypeDef typeDef = iter.next();
@@ -373,7 +372,7 @@ private RangerServiceDef getServiceDef() {
return plugin != null ? plugin.getServiceDef() : null;
}
- private boolean isAccessAllowed(AtlasEntityAccessRequest request,
RangerAtlasAuditHandler auditHandler) throws AtlasAuthorizationException {
+ private boolean isAccessAllowed(AtlasEntityAccessRequest request,
RangerAtlasAuditHandler auditHandler) {
if (LOG.isDebugEnabled()) {
LOG.debug("==> isAccessAllowed(" + request + ")");
}
@@ -470,7 +469,7 @@ private boolean checkAccess(RangerAccessRequestImpl
request, RangerAtlasAuditHan
return ret;
}
- private void checkAccessAndScrub(AtlasEntityHeader entity,
AtlasSearchResultScrubRequest request) throws AtlasAuthorizationException {
+ private void checkAccessAndScrub(AtlasEntityHeader entity,
AtlasSearchResultScrubRequest request) {
if (entity != null && request != null) {
final AtlasEntityAccessRequest entityAccessRequest = new
AtlasEntityAccessRequest(request.getTypeRegistry(), AtlasPrivilege.ENTITY_READ,
entity, request.getUser(), request.getUserGroups());
diff --git
a/plugin-atlas/src/test/java/org/apache/ranger/authorization/atlas/authorizer/TestRangerAtlasAuthorizer.java
b/plugin-atlas/src/test/java/org/apache/ranger/authorization/atlas/authorizer/TestRangerAtlasAuthorizer.java
new file mode 100644
index 000000000..502dd93ab
--- /dev/null
+++
b/plugin-atlas/src/test/java/org/apache/ranger/authorization/atlas/authorizer/TestRangerAtlasAuthorizer.java
@@ -0,0 +1,522 @@
+/*
+ * 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.authorization.atlas.authorizer;
+
+import org.apache.atlas.authorize.AtlasAdminAccessRequest;
+import org.apache.atlas.authorize.AtlasEntityAccessRequest;
+import org.apache.atlas.authorize.AtlasPrivilege;
+import org.apache.atlas.authorize.AtlasRelationshipAccessRequest;
+import org.apache.atlas.authorize.AtlasTypeAccessRequest;
+import org.apache.atlas.model.instance.AtlasClassification;
+import org.apache.atlas.model.instance.AtlasEntityHeader;
+import org.apache.atlas.model.typedef.AtlasClassificationDef;
+import org.apache.atlas.model.typedef.AtlasEntityDef;
+import org.apache.atlas.type.AtlasTypeRegistry;
+import org.junit.jupiter.api.Test;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class TestRangerAtlasAuthorizer {
+ private static final String USER_USER1 = "user1";
+ private static final Set<String> USER_USER1_GROUPS =
Collections.singleton("users");
+ private static final String USER_ADMIN1 = "admin1";
+ private static final Set<String> USER_ADMIN1_GROUPS =
Collections.singleton("admins");
+ private static final String USER_STEWARD1 =
"data-steward1";
+ private static final Set<String> USER_STEWARD1_GROUPS =
Collections.singleton("stewards");
+ private static final String USER_FINANCE_STEWARD1 =
"finance-data-steward1";
+ private static final Set<String> USER_FINANCE_STEWARD1_GROUPS = new
HashSet<>(Arrays.asList("finance-stewards", "stewards"));
+
+ private static final AtlasEntityDef ENTITY_DEF_HIVE_TABLE
= new AtlasEntityDef("hive_table");
+ private static final AtlasClassificationDef CLASSIFICATION_DEF_FINANCE
= new AtlasClassificationDef("FINANCE");
+ private static final AtlasClassificationDef CLASSIFICATION_DEF_PII
= new AtlasClassificationDef("PII");
+ private static final AtlasClassificationDef
CLASSIFICATION_DEF_DATA_QUALITY = new AtlasClassificationDef("DATA_QUALITY");
+ private static final AtlasEntityHeader ENTITY_HIVE_TABLE_DB1_TBL1
= new AtlasEntityHeader(ENTITY_DEF_HIVE_TABLE.getName(),
Collections.singletonMap("qualifiedName", "db1.tbl1@dev"));
+ private static final AtlasEntityHeader ENTITY_HIVE_TABLE_DB1_TBL2
= new AtlasEntityHeader(ENTITY_DEF_HIVE_TABLE.getName(),
Collections.singletonMap("qualifiedName", "db1.tbl2@dev"));
+ private static final AtlasClassification CLASSIFICATION_FINANCE
= new AtlasClassification(CLASSIFICATION_DEF_FINANCE.getName());
+ private static final AtlasClassification CLASSIFICATION_PII
= new AtlasClassification(CLASSIFICATION_DEF_PII.getName());
+ private static final AtlasClassification CLASSIFICATION_DATA_QUALITY
= new AtlasClassification(CLASSIFICATION_DEF_DATA_QUALITY.getName());
+ private static final String LABEL_APPROVED
= "approved";
+ private static final String
BUSINESS_METADATA_DATA_PROVIDER = "data-provider";
+ private static final String RELATIONSHIP_TYPE_CLONE_OF
= "cloneOf";
+
+ private final AtlasTypeRegistry typeRegistry;
+ private final RangerAtlasAuthorizer authorizer;
+
+ public TestRangerAtlasAuthorizer() {
+ typeRegistry = new AtlasTypeRegistry();
+ authorizer = new RangerAtlasAuthorizer();
+
+ authorizer.init();
+ }
+
+ @Test
+ public void testTypeDefRead() {
+ AtlasTypeAccessRequest request = new
AtlasTypeAccessRequest(AtlasPrivilege.TYPE_READ, ENTITY_DEF_HIVE_TABLE);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to read typedef %s",
request.getUser(), ENTITY_DEF_HIVE_TABLE.getName())
+ .isTrue();
+ }
+
+ @Test
+ public void testTypeDefCreate() {
+ AtlasTypeAccessRequest request = new
AtlasTypeAccessRequest(AtlasPrivilege.TYPE_CREATE, ENTITY_DEF_HIVE_TABLE);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to create typedef %s",
request.getUser(), ENTITY_DEF_HIVE_TABLE.getName())
+ .isFalse();
+
+ request.setUser(USER_ADMIN1, USER_ADMIN1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to create typedef %s",
request.getUser(), ENTITY_DEF_HIVE_TABLE.getName())
+ .isTrue();
+ }
+
+ @Test
+ public void testTypeDefUpdate() {
+ AtlasTypeAccessRequest request = new
AtlasTypeAccessRequest(AtlasPrivilege.TYPE_UPDATE, ENTITY_DEF_HIVE_TABLE);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to update typedef %s",
request.getUser(), ENTITY_DEF_HIVE_TABLE.getName())
+ .isFalse();
+
+ request.setUser(USER_ADMIN1, USER_ADMIN1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to update typedef %s",
request.getUser(), ENTITY_DEF_HIVE_TABLE.getName())
+ .isTrue();
+ }
+
+ @Test
+ public void testTypeDefDelete() {
+ AtlasTypeAccessRequest request = new
AtlasTypeAccessRequest(AtlasPrivilege.TYPE_DELETE, ENTITY_DEF_HIVE_TABLE);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to delete typedef %s",
request.getUser(), ENTITY_DEF_HIVE_TABLE.getName())
+ .isFalse();
+
+ request.setUser(USER_ADMIN1, USER_ADMIN1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to delete typedef %s",
request.getUser(), ENTITY_DEF_HIVE_TABLE.getName())
+ .isTrue();
+ }
+
+ @Test
+ public void testEntityRead() {
+ AtlasEntityAccessRequest request = new
AtlasEntityAccessRequest(typeRegistry, AtlasPrivilege.ENTITY_READ,
ENTITY_HIVE_TABLE_DB1_TBL1);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to read entity %s",
request.getUser(), request.getEntityId())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to read entity %s",
request.getUser(), request.getEntityId())
+ .isTrue();
+
+ request.setUser(USER_ADMIN1, USER_ADMIN1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to read entity %s",
request.getUser(), request.getEntityId())
+ .isTrue();
+ }
+
+ @Test
+ public void testEntityCreate() {
+ AtlasEntityAccessRequest request = new
AtlasEntityAccessRequest(typeRegistry, AtlasPrivilege.ENTITY_CREATE,
ENTITY_HIVE_TABLE_DB1_TBL1);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to create entity %s",
request.getUser(), request.getEntityId())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to create entity %s",
request.getUser(), request.getEntityId())
+ .isFalse();
+
+ request.setUser(USER_ADMIN1, USER_ADMIN1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to create entity %s",
request.getUser(), request.getEntityId())
+ .isTrue();
+ }
+
+ @Test
+ public void testEntityUpdate() {
+ AtlasEntityAccessRequest request = new
AtlasEntityAccessRequest(typeRegistry, AtlasPrivilege.ENTITY_UPDATE,
ENTITY_HIVE_TABLE_DB1_TBL1);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to update entity %s",
request.getUser(), request.getEntityId())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to update entity %s",
request.getUser(), request.getEntityId())
+ .isFalse();
+
+ request.setUser(USER_ADMIN1, USER_ADMIN1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to update entity %s",
request.getUser(), request.getEntityId())
+ .isTrue();
+ }
+
+ @Test
+ public void testEntityDelete() {
+ AtlasEntityAccessRequest request = new
AtlasEntityAccessRequest(typeRegistry, AtlasPrivilege.ENTITY_DELETE,
ENTITY_HIVE_TABLE_DB1_TBL1);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to delete entity %s",
request.getUser(), request.getEntityId())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to delete entity %s",
request.getUser(), request.getEntityId())
+ .isFalse();
+
+ request.setUser(USER_ADMIN1, USER_ADMIN1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to delete entity %s",
request.getUser(), request.getEntityId())
+ .isTrue();
+ }
+
+ @Test
+ public void testAddClassification() {
+ AtlasEntityAccessRequest request = new
AtlasEntityAccessRequest(typeRegistry,
AtlasPrivilege.ENTITY_ADD_CLASSIFICATION, ENTITY_HIVE_TABLE_DB1_TBL1,
CLASSIFICATION_PII);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to add classification %s",
request.getUser(), request.getClassification().getTypeName())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to add classification %s",
request.getUser(), request.getClassification().getTypeName())
+ .isTrue();
+ }
+
+ @Test
+ public void testAddClassificationOnEntityHavingFinanceTag() {
+ AtlasEntityHeader entityHavingFinanceTag = new
AtlasEntityHeader(ENTITY_HIVE_TABLE_DB1_TBL1);
+
+
entityHavingFinanceTag.setClassifications(Collections.singletonList(CLASSIFICATION_FINANCE));
+
+ AtlasEntityAccessRequest request = new
AtlasEntityAccessRequest(typeRegistry,
AtlasPrivilege.ENTITY_ADD_CLASSIFICATION, entityHavingFinanceTag,
CLASSIFICATION_DATA_QUALITY);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to add classification %s to entity
having classifications %s", request.getUser(),
request.getClassification().getTypeName(),
entityHavingFinanceTag.getClassifications())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to add classification %s to entity
having classifications %s", request.getUser(),
request.getClassification().getTypeName(),
entityHavingFinanceTag.getClassifications())
+ .isFalse();
+
+ request.setUser(USER_FINANCE_STEWARD1, USER_FINANCE_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to add classification %s to entity
having classifications %s", request.getUser(),
request.getClassification().getTypeName(),
entityHavingFinanceTag.getClassifications())
+ .isTrue();
+ }
+
+ @Test
+ public void testAddClassificationOnEntityHavingFinanceDataQualityTags() {
+ AtlasEntityHeader entityHavingFinanceTag = new
AtlasEntityHeader(ENTITY_HIVE_TABLE_DB1_TBL1);
+
+
entityHavingFinanceTag.setClassifications(Arrays.asList(CLASSIFICATION_FINANCE,
CLASSIFICATION_DATA_QUALITY));
+
+ AtlasEntityAccessRequest request = new
AtlasEntityAccessRequest(typeRegistry,
AtlasPrivilege.ENTITY_ADD_CLASSIFICATION, entityHavingFinanceTag,
CLASSIFICATION_PII);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to add classification %s to entity
having classifications %s", request.getUser(),
request.getClassification().getTypeName(),
entityHavingFinanceTag.getClassifications())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to add classification %s to entity
having classifications %s", request.getUser(),
request.getClassification().getTypeName(),
entityHavingFinanceTag.getClassifications())
+ .isFalse();
+
+ request.setUser(USER_FINANCE_STEWARD1, USER_FINANCE_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to add classification %s to entity
having classifications %s", request.getUser(),
request.getClassification().getTypeName(),
entityHavingFinanceTag.getClassifications())
+ .isTrue();
+ }
+
+ @Test
+ public void testUpdateClassification() {
+ AtlasEntityAccessRequest request = new
AtlasEntityAccessRequest(typeRegistry,
AtlasPrivilege.ENTITY_UPDATE_CLASSIFICATION, ENTITY_HIVE_TABLE_DB1_TBL1,
CLASSIFICATION_PII);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to update classification %s",
request.getUser(), request.getClassification().getTypeName())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to update classification %s",
request.getUser(), request.getClassification().getTypeName())
+ .isTrue();
+ }
+
+ @Test
+ public void testRemoveClassification() {
+ AtlasEntityAccessRequest request = new
AtlasEntityAccessRequest(typeRegistry,
AtlasPrivilege.ENTITY_REMOVE_CLASSIFICATION, ENTITY_HIVE_TABLE_DB1_TBL1,
CLASSIFICATION_PII);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to remove classification %s",
request.getUser(), request.getClassification().getTypeName())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to remove classification %s",
request.getUser(), request.getClassification().getTypeName())
+ .isTrue();
+ }
+
+ @Test
+ public void testAddLabel() {
+ AtlasEntityAccessRequest request = new
AtlasEntityAccessRequest(typeRegistry, AtlasPrivilege.ENTITY_ADD_LABEL,
ENTITY_HIVE_TABLE_DB1_TBL1, null, null, LABEL_APPROVED, null);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to add label ", request.getUser(),
request.getLabel())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to add label %s", request.getUser(),
request.getLabel())
+ .isTrue();
+ }
+
+ @Test
+ public void testRemoveLabel() {
+ AtlasEntityAccessRequest request = new
AtlasEntityAccessRequest(typeRegistry, AtlasPrivilege.ENTITY_REMOVE_LABEL,
ENTITY_HIVE_TABLE_DB1_TBL1, null, null, LABEL_APPROVED, null);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to remove label %s",
request.getUser(), request.getLabel())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to remove label %s",
request.getUser(), request.getLabel())
+ .isTrue();
+ }
+
+ @Test
+ public void testUpdateBusinessMetadata() {
+ AtlasEntityAccessRequest request = new
AtlasEntityAccessRequest(typeRegistry,
AtlasPrivilege.ENTITY_UPDATE_BUSINESS_METADATA, ENTITY_HIVE_TABLE_DB1_TBL1,
null, null, null, BUSINESS_METADATA_DATA_PROVIDER, USER_USER1,
USER_USER1_GROUPS);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to update business metadata %s",
request.getUser(), request.getBusinessMetadata())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to update business metadata %s",
request.getUser(), request.getBusinessMetadata())
+ .isTrue();
+ }
+
+ @Test
+ public void testImport() {
+ AtlasAdminAccessRequest request = new
AtlasAdminAccessRequest(AtlasPrivilege.ADMIN_IMPORT);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to import", request.getUser())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to import", request.getUser())
+ .isFalse();
+
+ request.setUser(USER_ADMIN1, USER_ADMIN1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to import", request.getUser())
+ .isTrue();
+ }
+
+ @Test
+ public void testExport() {
+ AtlasAdminAccessRequest request = new
AtlasAdminAccessRequest(AtlasPrivilege.ADMIN_EXPORT);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to export", request.getUser())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to export", request.getUser())
+ .isFalse();
+
+ request.setUser(USER_ADMIN1, USER_ADMIN1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to export", request.getUser())
+ .isTrue();
+ }
+
+ @Test
+ public void testPurge() {
+ AtlasAdminAccessRequest request = new
AtlasAdminAccessRequest(AtlasPrivilege.ADMIN_PURGE);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to purge", request.getUser())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to purge", request.getUser())
+ .isFalse();
+
+ request.setUser(USER_ADMIN1, USER_ADMIN1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to purge", request.getUser())
+ .isTrue();
+ }
+
+ @Test
+ public void testAudits() {
+ AtlasAdminAccessRequest request = new
AtlasAdminAccessRequest(AtlasPrivilege.ADMIN_AUDITS);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to admin audits", request.getUser())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to admin audits", request.getUser())
+ .isFalse();
+
+ request.setUser(USER_ADMIN1, USER_ADMIN1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to admin audits", request.getUser())
+ .isTrue();
+ }
+
+ @Test
+ public void testAddRelationship() {
+ AtlasRelationshipAccessRequest request = new
AtlasRelationshipAccessRequest(typeRegistry, AtlasPrivilege.RELATIONSHIP_ADD,
RELATIONSHIP_TYPE_CLONE_OF, ENTITY_HIVE_TABLE_DB1_TBL1,
ENTITY_HIVE_TABLE_DB1_TBL2);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to add relationship %s",
request.getUser(), request.getRelationshipType())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to add relationship %s",
request.getUser(), request.getRelationshipType()).isTrue();
+ }
+
+ @Test
+ public void testUpdateRelationship() {
+ AtlasRelationshipAccessRequest request = new
AtlasRelationshipAccessRequest(typeRegistry,
AtlasPrivilege.RELATIONSHIP_UPDATE, RELATIONSHIP_TYPE_CLONE_OF,
ENTITY_HIVE_TABLE_DB1_TBL1, ENTITY_HIVE_TABLE_DB1_TBL2);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to update relationship %s",
request.getUser(), request.getRelationshipType())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to update relationship %s",
request.getUser(), request.getRelationshipType())
+ .isTrue();
+ }
+
+ @Test
+ public void testRemoveRelationship() {
+ AtlasRelationshipAccessRequest request = new
AtlasRelationshipAccessRequest(typeRegistry,
AtlasPrivilege.RELATIONSHIP_REMOVE, RELATIONSHIP_TYPE_CLONE_OF,
ENTITY_HIVE_TABLE_DB1_TBL1, ENTITY_HIVE_TABLE_DB1_TBL2);
+
+ request.setUser(USER_USER1, USER_USER1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be denied to remove relationship %s",
request.getUser(), request.getRelationshipType())
+ .isFalse();
+
+ request.setUser(USER_STEWARD1, USER_STEWARD1_GROUPS);
+
+ assertThat(authorizer.isAccessAllowed(request))
+ .as("%s should be allowed to remove relationship %s",
request.getUser(), request.getRelationshipType()).isTrue();
+ }
+}
diff --git
a/plugin-atlas/src/test/java/org/apache/ranger/authorization/atlas/testutil/RangerAdminClientImpl.java
b/plugin-atlas/src/test/java/org/apache/ranger/authorization/atlas/testutil/RangerAdminClientImpl.java
new file mode 100644
index 000000000..0c5833937
--- /dev/null
+++
b/plugin-atlas/src/test/java/org/apache/ranger/authorization/atlas/testutil/RangerAdminClientImpl.java
@@ -0,0 +1,45 @@
+/*
+ * 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.authorization.atlas.testutil;
+
+import org.apache.ranger.admin.client.AbstractRangerAdminClient;
+import org.apache.ranger.plugin.util.ServicePolicies;
+
+import java.io.File;
+import java.nio.file.FileSystems;
+import java.nio.file.Files;
+
+/**
+ * A test implementation of the RangerAdminClient interface that just reads
policies in from a file and returns them
+ */
+public class RangerAdminClientImpl extends AbstractRangerAdminClient {
+ private static final String TEST_POLICIES_FILENAME = "atlas-policies.json";
+
+ public ServicePolicies getServicePoliciesIfUpdated(long lastKnownVersion,
long lastActivationTimeInMillis) throws Exception {
+ String basedir = System.getProperty("basedir");
+
+ if (basedir == null) {
+ basedir = new File(".").getCanonicalPath();
+ }
+
+ java.nio.file.Path cachePath =
FileSystems.getDefault().getPath(basedir, "src/test/resources/" +
TEST_POLICIES_FILENAME);
+ byte[] cacheBytes = Files.readAllBytes(cachePath);
+
+ return gson.fromJson(new String(cacheBytes), ServicePolicies.class);
+ }
+}
diff --git a/plugin-atlas/src/test/resources/atlas-application.properties
b/plugin-atlas/src/test/resources/atlas-application.properties
new file mode 100644
index 000000000..828a238e5
--- /dev/null
+++ b/plugin-atlas/src/test/resources/atlas-application.properties
@@ -0,0 +1,18 @@
+# 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.
+
+#
+# Empty properties file - needed to initialize RangerAtlasAuthorizer
+#
diff --git a/plugin-atlas/src/test/resources/atlas-policies.json
b/plugin-atlas/src/test/resources/atlas-policies.json
new file mode 100644
index 000000000..1020dd8f6
--- /dev/null
+++ b/plugin-atlas/src/test/resources/atlas-policies.json
@@ -0,0 +1,181 @@
+{
+ "serviceName": "dev_atlas", "serviceId": 8, "policyVersion": 19,
+ "policies": [
+ {
+ "id": 1, "name": "Default: all type-category, type",
+ "resources": {
+ "type-category": { "values": [ "*" ] },
+ "type": { "values": [ "*" ] }
+ },
+ "policyItems": [
+ {
+ "accesses": [ { "type": "type-read" }],
+ "groups": [ "public" ]
+ },
+ {
+ "accesses": [ { "type": "type-create" }, { "type": "type-update" },
{ "type": "type-delete"} ],
+ "groups": [ "admins" ]
+ }
+ ]
+ },
+ {
+ "id": 2, "name": "Default: all entity-type, entity-classification,
entity",
+ "resources": {
+ "entity-type": { "values": [ "*" ] },
+ "entity-classification": { "values": [ "*" ] },
+ "entity": { "values": [ "*" ] }
+ },
+ "policyItems": [
+ {
+ "accesses": [ { "type": "entity-read" } ],
+ "groups": [ "stewards" ]
+ },
+ {
+ "accesses": [ { "type": "entity-read" }, { "type": "entity-create"
}, { "type": "entity-update" }, { "type": "entity-delete"} ],
+ "groups": [ "admins" ]
+ }
+ ]
+ },
+ {
+ "id": 3, "name": "Default: all entity-type, entity-classification,
entity, classification",
+ "resources": {
+ "entity-type": { "values": [ "*" ] },
+ "entity-classification": { "values": [ "*" ] },
+ "entity": { "values": [ "*" ] },
+ "classification": { "values": [ "*" ] }
+ },
+ "policyItems": [
+ {
+ "accesses": [ { "type": "entity-add-classification" }, { "type":
"entity-update-classification" }, { "type": "entity-remove-classification"} ],
+ "groups": [ "stewards" ]
+ }
+ ]
+ },
+ {
+ "id": 4, "name": "Default: all entity-type, entity-classification,
entity, label",
+ "resources": {
+ "entity-type": { "values": [ "*" ] },
+ "entity-classification": { "values": [ "*" ] },
+ "entity": { "values": [ "*" ] },
+ "entity-label": { "values": [ "*" ] }
+ },
+ "policyItems": [
+ {
+ "accesses": [ { "type": "entity-add-label" }, { "type":
"entity-update-label" }, { "type": "entity-remove-label"} ],
+ "groups": [ "stewards" ]
+ }
+ ]
+ },
+ {
+ "id": 5, "name": "Default: all entity-type, entity-classification,
entity, business-metadata",
+ "resources": {
+ "entity-type": { "values": [ "*" ] },
+ "entity-classification": { "values": [ "*" ] },
+ "entity": { "values": [ "*" ] },
+ "entity-business-metadata": { "values": [ "*" ] }
+ },
+ "policyItems": [
+ {
+ "accesses": [ { "type": "entity-update-business-metadata" } ],
+ "groups": [ "stewards" ]
+ }
+ ]
+ },
+ {
+ "id": 6, "name": "Default: all relationship-type, end-one-entity-type,
end-one-entity-classification, end-one-entity, end-two-entity-type,
end-two-entity-classification, end-two-entity",
+ "resources": {
+ "relationship-type": { "values": [ "*" ] },
+ "end-one-entity-type": { "values": [ "*" ] },
+ "end-one-entity-classification": { "values": [ "*" ] },
+ "end-one-entity": { "values": [ "*" ] },
+ "end-two-entity-type": { "values": [ "*" ] },
+ "end-two-entity-classification": { "values": [ "*" ] },
+ "end-two-entity": { "values": [ "*" ] }
+ },
+ "policyItems": [
+ {
+ "accesses": [ { "type": "add-relationship" }, { "type":
"update-relationship" }, { "type": "remove-relationship" } ],
+ "groups": [ "stewards" ]
+ }
+ ]
+ },
+ {
+ "id": 7, "name": "Default: all atlas-service",
+ "resources": {
+ "atlas-service": { "values": [ "*" ] }
+ },
+ "policyItems": [
+ {
+ "accesses": [ { "type": "admin-import" }, { "type": "admin-export"
}, { "type": "admin-purge" }, { "type": "admin-audits" } ],
+ "groups": [ "admins" ]
+ }
+ ]
+ },
+ {
+ "id": 8, "name": "Entities having FINANCE classification",
"isDenyAllElse": true,
+ "resources": {
+ "entity-type": { "values": [ "*" ] },
+ "entity-classification": { "values": [ "FINANCE" ] },
+ "entity": { "values": [ "*" ] },
+ "classification": { "values": [ "*" ] }
+ },
+ "policyItems": [
+ {
+ "accesses": [ { "type": "entity-add-classification" }, { "type":
"entity-update-classification" }, { "type": "entity-remove-classification"} ],
+ "groups": [ "finance-stewards" ]
+ }
+ ]
+ }
+ ],
+ "serviceDef": {
+ "id": 3, "name": "atlas", "implClass":
"org.apache.ranger.services.atlas.RangerServiceAtlas",
+ "resources": [
+ { "itemId": 1, "name": "type-category", "level": 10 },
+ { "itemId": 2, "name": "type", "level": 20,
"parent": "type-category", "accessTypeRestrictions": [ "type-read",
"type-create", "type-update", "type-delete" ] },
+ { "itemId": 3, "name": "entity-type", "level": 10 },
+ { "itemId": 4, "name": "entity-classification", "level": 20,
"parent": "entity-type" },
+ { "itemId": 5, "name": "entity", "level": 30,
"parent": "entity-classification", "accessTypeRestrictions": [ "entity-read",
"entity-create", "entity-update", "entity-delete" ] },
+ { "itemId": 6, "name": "entity-label", "level": 40,
"parent": "entity", "accessTypeRestrictions": [
"entity-add-label", "entity-remove-label" ] },
+ { "itemId": 7, "name": "entity-business-metadata", "level": 40,
"parent": "entity", "accessTypeRestrictions": [
"entity-update-business-metadata" ] },
+ { "itemId": 8, "name": "classification", "level": 20,
"parent": "entity", "accessTypeRestrictions": [
"entity-add-classification", "entity-update-classification",
"entity-remove-classification" ] },
+ { "itemId": 9, "name": "atlas-service", "level": 10,
"accessTypeRestrictions": [ "admin-import",
"admin-export", "admin-purge", "admin-audits" ] },
+ { "itemId": 10, "name": "relationship-type", "level": 10 },
+ { "itemId": 11, "name": "end-one-entity-type", "level": 20,
"parent": "relationship-type" },
+ { "itemId": 12, "name": "end-one-entity-classification", "level": 30,
"parent": "end-one-entity-type" },
+ { "itemId": 13, "name": "end-one-entity", "level": 40,
"parent": "end-one-entity-classification", "accessTypeRestrictions": [
"add-relationship", "update-relationship", "remove-relationship" ] },
+ { "itemId": 14, "name": "end-two-entity-type", "level": 50,
"parent": "end-one-entity" },
+ { "itemId": 15, "name": "end-two-entity-classification", "level": 60,
"parent": "end-two-entity-type" },
+ { "itemId": 16, "name": "end-two-entity", "level": 70,
"parent": "end-two-entity-classification", "accessTypeRestrictions": [
"add-relationship", "update-relationship", "remove-relationship" ] }
+ ],
+ "accessTypes": [
+ { "itemId": 1, "name": "type-read", "category":
"READ", "label": "Read Type" },
+ { "itemId": 2, "name": "type-create", "category":
"MANAGE", "label": "Create Type" },
+ { "itemId": 3, "name": "type-update", "category":
"MANAGE", "label": "Update Type" },
+ { "itemId": 4, "name": "type-delete", "category":
"MANAGE", "label": "Delete Type" },
+ { "itemId": 5, "name": "entity-read", "category":
"READ", "label": "Read Entity" },
+ { "itemId": 6, "name": "entity-create", "category":
"CREATE", "label": "Create Entity" },
+ { "itemId": 7, "name": "entity-update", "category":
"UPDATE", "label": "Update Entity" },
+ { "itemId": 8, "name": "entity-delete", "category":
"DELETE", "label": "Delete Entity" },
+ { "itemId": 9, "name": "entity-add-classification", "category":
"UPDATE", "label": "Add Classification" },
+ { "itemId": 10, "name": "entity-update-classification", "category":
"UPDATE", "label": "Update Classification" },
+ { "itemId": 11, "name": "entity-remove-classification", "category":
"UPDATE", "label": "Remove Classification" },
+ { "itemId": 12, "name": "entity-add-label", "category":
"UPDATE", "label": "Add Label" },
+ { "itemId": 13, "name": "entity-remove-label", "category":
"UPDATE", "label": "Remove Label" },
+ { "itemId": 14, "name": "entity-update-business-metadata", "category":
"UPDATE", "label": "Update Business Metadata" },
+ { "itemId": 15, "name": "add-relationship", "category":
"UPDATE", "label": "Add Relationship" },
+ { "itemId": 16, "name": "update-relationship", "category":
"UPDATE", "label": "Update Relationship" },
+ { "itemId": 17, "name": "remove-relationship", "category":
"UPDATE", "label": "Remove Relationship" },
+ { "itemId": 18, "name": "admin-export", "category":
"MANAGE", "label": "Export" },
+ { "itemId": 19, "name": "admin-import", "category":
"MANAGE", "label": "Import" },
+ { "itemId": 20, "name": "admin-purge", "category":
"MANAGE", "label": "Purge" },
+ { "itemId": 21, "name": "admin-audits", "category":
"MANAGE", "label": "Admin Audits" }
+ ],
+ "configs": [
+ { "itemId": 1, "name": "username", "type": "string",
"mandatory": true },
+ { "itemId": 2, "name": "password", "type":
"password", "mandatory": true },
+ { "itemId": 3, "name": "atlas.rest.address", "type": "string",
"mandatory": true, "defaultValue": "http://localhost:21000" },
+ { "itemId": 4, "name": "commonNameForCertificate", "type": "string",
"mandatory": false },
+ { "itemId": 5, "name": "ranger.plugin.audit.filters", "type": "string",
"mandatory": false }
+ ]
+ }
+}
diff --git a/plugin-atlas/src/test/resources/logback.xml
b/plugin-atlas/src/test/resources/logback.xml
new file mode 100644
index 000000000..aacad9620
--- /dev/null
+++ b/plugin-atlas/src/test/resources/logback.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+
+<configuration>
+ <root level="warn">
+ </root>
+</configuration>
diff --git a/plugin-atlas/src/test/resources/ranger-atlas-security.xml
b/plugin-atlas/src/test/resources/ranger-atlas-security.xml
new file mode 100644
index 000000000..8b5b1af01
--- /dev/null
+++ b/plugin-atlas/src/test/resources/ranger-atlas-security.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0"?>
+<!--
+ 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.
+-->
+<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
+<configuration xmlns:xi="http://www.w3.org/2001/XInclude">
+ <property>
+ <name>ranger.plugin.atlas.service.name</name>
+ <value>dev_atlas</value>
+ <description>Name of the Ranger service containing policies for this
SampleApp instance</description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.atlas.policy.source.impl</name>
+
<value>org.apache.ranger.authorization.atlas.testutil.RangerAdminClientImpl</value>
+ <description>Policy source</description>
+ </property>
+
+ <property>
+ <name>ranger.plugin.atlas.policy.cache.dir</name>
+ <value>target/policyCache</value>
+ <description>Directory where Ranger policies are cached after
successful retrieval from the source</description>
+ </property>
+</configuration>
diff --git a/pom.xml b/pom.xml
index 4df56ae69..e05680674 100644
--- a/pom.xml
+++ b/pom.xml
@@ -38,6 +38,7 @@
<asm.all.version>3.2</asm.all.version>
<aspectj.version>1.8.2</aspectj.version>
<assembly.plugin.version>2.6</assembly.plugin.version>
+ <assertj.version>3.27.3</assertj.version>
<atlas.commons.logging.version>1.1.3</atlas.commons.logging.version>
<atlas.jackson.databind.version>2.11.3</atlas.jackson.databind.version>
<atlas.jackson.version>2.11.3</atlas.jackson.version>