This is an automated email from the ASF dual-hosted git repository.

mandarambawane pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/atlas.git


The following commit(s) were added to refs/heads/master by this push:
     new 134148188 ATLAS-5418: Enforce entity read check on v1 entity audit API 
(#770)
134148188 is described below

commit 13414818896c2efb902b1c14ddb23bfe69f97b9d
Author: sheetalshah1007 <[email protected]>
AuthorDate: Fri Sep 25 17:56:12 2026 +0530

    ATLAS-5418: Enforce entity read check on v1 entity audit API (#770)
---
 .../apache/atlas/web/resources/EntityResource.java |  6 +++
 .../java/org/apache/atlas/web/rest/EntityREST.java | 27 ++++++-----
 .../atlas/web/resources/EntityResourceTest.java    | 52 +++++++++++++++++++++-
 3 files changed, 71 insertions(+), 14 deletions(-)

diff --git 
a/webapp/src/main/java/org/apache/atlas/web/resources/EntityResource.java 
b/webapp/src/main/java/org/apache/atlas/web/resources/EntityResource.java
index ccf66c595..a011902a2 100755
--- a/webapp/src/main/java/org/apache/atlas/web/resources/EntityResource.java
+++ b/webapp/src/main/java/org/apache/atlas/web/resources/EntityResource.java
@@ -992,6 +992,8 @@ public class EntityResource {
                 perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, 
"EntityResource.getAuditEvents(" + guid + ", " + startKey + ", " + count + ")");
             }
 
+            entityREST.verifyEntityReadForAudit(guid);
+
             List<Object>           events   = 
entityAuditRepository.listEvents(guid, startKey, count);
             List<EntityAuditEvent> v1Events = new ArrayList<>();
 
@@ -1011,6 +1013,10 @@ public class EntityResource {
             response.put(AtlasClient.EVENTS, v1Events);
 
             return Response.ok(AtlasJson.toV1Json(response)).build();
+        } catch (AtlasBaseException e) {
+            LOG.error("Unable to get audit events for entity guid={} 
startKey={}", guid, startKey, e);
+
+            throw toWebApplicationException(e);
         } catch (IllegalArgumentException e) {
             LOG.error("Unable to get audit events for entity guid={} 
startKey={}", guid, startKey, e);
 
diff --git a/webapp/src/main/java/org/apache/atlas/web/rest/EntityREST.java 
b/webapp/src/main/java/org/apache/atlas/web/rest/EntityREST.java
index 1f0e380cd..9f5f7b01c 100644
--- a/webapp/src/main/java/org/apache/atlas/web/rest/EntityREST.java
+++ b/webapp/src/main/java/org/apache/atlas/web/rest/EntityREST.java
@@ -850,18 +850,7 @@ public class EntityREST {
                 perf = AtlasPerfTracer.getPerfTracer(PERF_LOG, 
"EntityREST.getAuditEvents(" + guid + ", " + startKey + ", " + count + ")");
             }
 
-            // Enforces authorization for entity-read
-            try {
-                entitiesStore.getHeaderById(guid);
-            } catch (AtlasBaseException e) {
-                if (e.getAtlasErrorCode() == 
AtlasErrorCode.INSTANCE_GUID_NOT_FOUND) {
-                    AtlasEntityHeader entityHeader = 
getEntityHeaderFromPurgedAudit(guid);
-
-                    AtlasAuthorizationUtils.verifyAccess(new 
AtlasEntityAccessRequest(typeRegistry, AtlasPrivilege.ENTITY_READ, 
entityHeader), "read entity audit: guid=", guid);
-                } else {
-                    throw e;
-                }
-            }
+            verifyEntityReadForAudit(guid);
 
             List<EntityAuditEventV2> ret = new ArrayList<>();
 
@@ -1288,6 +1277,20 @@ public class EntityREST {
         }
     }
 
+    public void verifyEntityReadForAudit(String guid) throws 
AtlasBaseException {
+        try {
+            entitiesStore.getHeaderById(guid);
+        } catch (AtlasBaseException e) {
+            if (e.getAtlasErrorCode() == 
AtlasErrorCode.INSTANCE_GUID_NOT_FOUND) {
+                AtlasEntityHeader entityHeader = 
getEntityHeaderFromPurgedAudit(guid);
+
+                AtlasAuthorizationUtils.verifyAccess(new 
AtlasEntityAccessRequest(typeRegistry, AtlasPrivilege.ENTITY_READ, 
entityHeader), "read entity audit: guid=", guid);
+            } else {
+                throw e;
+            }
+        }
+    }
+
     private AtlasEntityHeader getEntityHeaderFromPurgedAudit(String guid) 
throws AtlasBaseException {
         List<EntityAuditEventV2> auditEvents = 
auditRepository.listEventsV2(guid, EntityAuditActionV2.ENTITY_PURGE, null, 
(short) 1);
         AtlasEntityHeader        ret         = 
CollectionUtils.isNotEmpty(auditEvents) ? auditEvents.get(0).getEntityHeader() 
: null;
diff --git 
a/webapp/src/test/java/org/apache/atlas/web/resources/EntityResourceTest.java 
b/webapp/src/test/java/org/apache/atlas/web/resources/EntityResourceTest.java
index 7a62a726b..23e8bcb16 100644
--- 
a/webapp/src/test/java/org/apache/atlas/web/resources/EntityResourceTest.java
+++ 
b/webapp/src/test/java/org/apache/atlas/web/resources/EntityResourceTest.java
@@ -17,22 +17,37 @@
  */
 package org.apache.atlas.web.resources;
 
+import org.apache.atlas.AtlasErrorCode;
+import org.apache.atlas.exception.AtlasBaseException;
 import org.apache.atlas.model.instance.AtlasEntityHeader;
 import org.apache.atlas.model.instance.EntityMutationResponse;
 import org.apache.atlas.model.instance.EntityMutations;
+import org.apache.atlas.repository.audit.EntityAuditRepository;
+import org.apache.atlas.repository.converters.AtlasInstanceConverter;
 import org.apache.atlas.repository.store.graph.AtlasEntityStore;
+import org.apache.atlas.type.AtlasTypeRegistry;
+import org.apache.atlas.web.rest.EntityREST;
 import org.apache.commons.collections.CollectionUtils;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Response;
+
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
 
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.anyString;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.expectThrows;
 
 /**
  * Unit test of {@link EntityResource}
@@ -41,11 +56,30 @@ public class EntityResourceTest {
     private static final String DELETED_GUID = "deleted_guid";
 
     @Mock
-    AtlasEntityStore entitiesStore;
+    private AtlasInstanceConverter restAdapters;
+
+    @Mock
+    private AtlasEntityStore entitiesStore;
+
+    @Mock
+    private AtlasTypeRegistry typeRegistry;
+
+    @Mock
+    private EntityREST entityREST;
+
+    @Mock
+    private EntityAuditRepository entityAuditRepository;
+
+    @Mock
+    private AtlasInstanceConverter instanceConverter;
+
+    private EntityResource entityResource;
 
     @BeforeMethod
     public void setUp() {
-        MockitoAnnotations.initMocks(this);
+        MockitoAnnotations.openMocks(this);
+        entityResource = new EntityResource(restAdapters, entitiesStore, 
typeRegistry, entityREST, entityAuditRepository,
+                instanceConverter);
     }
 
     @Test
@@ -72,6 +106,20 @@ public class EntityResourceTest {
         assertEquals(responseDeletedEntities, deletedEntities);
     }
 
+    @Test
+    public void testGetAuditEvents_deniedWhenEntityReadNotAllowed() throws 
Exception {
+        String guid = "test-guid";
+
+        doThrow(new AtlasBaseException(AtlasErrorCode.UNAUTHORIZED_ACCESS, 
"bob", "entity-read")).when(entityREST)
+                .verifyEntityReadForAudit(guid);
+
+        WebApplicationException exception = 
expectThrows(WebApplicationException.class,
+                () -> entityResource.getAuditEvents(guid, null, (short) 10));
+
+        assertEquals(exception.getResponse().getStatus(), 
Response.Status.FORBIDDEN.getStatusCode());
+        verify(entityAuditRepository, never()).listEvents(anyString(), any(), 
any(Short.class));
+    }
+
     private List<AtlasEntityHeader> toAtlasEntityHeaders(List<String> guids) {
         List<AtlasEntityHeader> ret = null;
 

Reply via email to