From 274dc0882f05a0eaba6a03e169db669ed3a828d4 Mon Sep 17 00:00:00 2001 From: Ram Narayan Balaji <81347100+yan-3005@users.noreply.github.com> Date: Thu, 14 Aug 2025 18:46:39 +0530 Subject: [PATCH] Fix Bug: Match All Tags giving a NPE with the resource doesn't have tags (#22937) (cherry picked from commit 5c76e78ff56964c0a4bba6e783fc1bf62a3ec2a4) --- .../policyevaluator/RuleEvaluator.java | 4 +++ .../policyevaluator/RuleEvaluatorTest.java | 30 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/RuleEvaluator.java b/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/RuleEvaluator.java index 569ffdffed9..c825fe3514b 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/RuleEvaluator.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/security/policyevaluator/RuleEvaluator.java @@ -110,6 +110,10 @@ public class RuleEvaluator { return false; } List tags = resourceContext.getTags(); + if (nullOrEmpty(tags)) { + LOG.debug("No Tags found for resource"); + return false; + } LOG.debug( "matchAllTags {} resourceTags {}", Arrays.toString(tagFQNs), diff --git a/openmetadata-service/src/test/java/org/openmetadata/service/security/policyevaluator/RuleEvaluatorTest.java b/openmetadata-service/src/test/java/org/openmetadata/service/security/policyevaluator/RuleEvaluatorTest.java index 1c7fb333e89..30ab7b0b7b5 100644 --- a/openmetadata-service/src/test/java/org/openmetadata/service/security/policyevaluator/RuleEvaluatorTest.java +++ b/openmetadata-service/src/test/java/org/openmetadata/service/security/policyevaluator/RuleEvaluatorTest.java @@ -1,6 +1,7 @@ package org.openmetadata.service.security.policyevaluator; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; @@ -138,6 +139,8 @@ class RuleEvaluatorTest { Mockito.when(dataProductRepository.getEntityType()).thenReturn(Entity.DATA_PRODUCT); Mockito.when(dataProductRepository.isSupportsOwners()).thenReturn(Boolean.TRUE); Entity.registerEntity(DataProduct.class, Entity.DATA_PRODUCT, dataProductRepository); + Mockito.when(dataProductRepository.getParentEntity(any(DataProduct.class), anyString())) + .thenReturn(null); // DataProduct doesn't have direct parent, should use domains user = new User().withId(UUID.randomUUID()).withName("user"); ownerUser = new User().withId(UUID.randomUUID()).withName("owner"); @@ -328,6 +331,33 @@ class RuleEvaluatorTest { assertTrue(evaluateExpression("!matchAllTags('tag4')")); } + @Test + void test_matchAllTags_withNullTags() { + // Test the scenario where getTags() returns null (e.g., due to deny policies) + // Set table tags to null to simulate the deny policy scenario + table.setTags(null); + + // Create a mock ResourceContext that returns null for getTags() + ResourceContext nullTagsResourceContext = Mockito.spy(resourceContext); + Mockito.when(nullTagsResourceContext.getTags()).thenReturn(null); + + // Create RuleEvaluator with the mock context + RuleEvaluator ruleEvaluator = new RuleEvaluator(null, subjectContext, nullTagsResourceContext); + EvaluationContext testEvaluationContext = new StandardEvaluationContext(ruleEvaluator); + + // Test that matchAllTags handles null tags gracefully without throwing NPE + // Before the fix, this would throw: "Cannot invoke \"java.util.List.toArray()\" because + // \"tags\" is null" + Boolean result = + parseExpression("matchAllTags('tag1', 'tag2')") + .getValue(testEvaluationContext, Boolean.class); + assertNotEquals(Boolean.TRUE, result, "matchAllTags should return false when tags is null"); + + // Test with single tag + result = parseExpression("matchAllTags('tag1')").getValue(testEvaluationContext, Boolean.class); + assertNotEquals(Boolean.TRUE, result, "matchAllTags should return false when tags is null"); + } + @Test void test_matchAnyTag() { table.withTags(getTags("tag1", "tag2", "tag3"));