diff --git a/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/IngestionPipelineOwnerInheritanceIT.java b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/IngestionPipelineOwnerInheritanceIT.java new file mode 100644 index 000000000000..964090dc9cfa --- /dev/null +++ b/openmetadata-integration-tests/src/test/java/org/openmetadata/it/tests/IngestionPipelineOwnerInheritanceIT.java @@ -0,0 +1,244 @@ +package org.openmetadata.it.tests; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.Instant; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.api.parallel.Execution; +import org.junit.jupiter.api.parallel.ExecutionMode; +import org.openmetadata.it.factories.DashboardServiceTestFactory; +import org.openmetadata.it.util.SdkClients; +import org.openmetadata.it.util.TestNamespace; +import org.openmetadata.it.util.TestNamespaceExtension; +import org.openmetadata.schema.api.policies.CreatePolicy; +import org.openmetadata.schema.api.services.ingestionPipelines.CreateIngestionPipeline; +import org.openmetadata.schema.api.teams.CreateRole; +import org.openmetadata.schema.api.teams.CreateUser; +import org.openmetadata.schema.entity.policies.Policy; +import org.openmetadata.schema.entity.policies.accessControl.Rule; +import org.openmetadata.schema.entity.services.DashboardService; +import org.openmetadata.schema.entity.services.ingestionPipelines.AirflowConfig; +import org.openmetadata.schema.entity.services.ingestionPipelines.IngestionPipeline; +import org.openmetadata.schema.entity.services.ingestionPipelines.PipelineType; +import org.openmetadata.schema.entity.teams.Role; +import org.openmetadata.schema.entity.teams.User; +import org.openmetadata.schema.metadataIngestion.DashboardServiceMetadataPipeline; +import org.openmetadata.schema.metadataIngestion.SourceConfig; +import org.openmetadata.schema.type.EntityReference; +import org.openmetadata.schema.type.MetadataOperation; +import org.openmetadata.sdk.client.OpenMetadataClient; +import org.openmetadata.sdk.network.HttpMethod; + +/** + * Integration tests for IngestionPipeline owner inheritance and trigger authorization. + * + *

Covers two coordinated changes that fix GH-27962 (Pylon-19838): + * + *

+ */ +@Execution(ExecutionMode.CONCURRENT) +@ExtendWith(TestNamespaceExtension.class) +public class IngestionPipelineOwnerInheritanceIT { + + private static final Date START_DATE = Date.from(Instant.parse("2022-06-10T15:06:47Z")); + + @Test + void test_inheritedOwners_fromService(TestNamespace ns) { + OpenMetadataClient adminClient = SdkClients.adminClient(); + String unique = UUID.randomUUID().toString().substring(0, 8); + String userName = "ipinhowner_" + unique; + User serviceOwner = + adminClient + .users() + .create( + new CreateUser().withName(userName).withEmail(userName + "@test.openmetadata.org")); + + try { + DashboardService service = DashboardServiceTestFactory.createMetabase(ns); + DashboardService fetchedService = + adminClient.dashboardServices().get(service.getId().toString()); + fetchedService.setOwners(List.of(serviceOwner.getEntityReference())); + adminClient.dashboardServices().update(service.getId().toString(), fetchedService); + + try { + IngestionPipeline pipeline = + adminClient + .ingestionPipelines() + .create( + new CreateIngestionPipeline() + .withName(ns.prefix("ipinhPipeline")) + .withPipelineType(PipelineType.METADATA) + .withService(service.getEntityReference()) + .withSourceConfig( + new SourceConfig().withConfig(new DashboardServiceMetadataPipeline())) + .withAirflowConfig(new AirflowConfig().withStartDate(START_DATE))); + + try { + IngestionPipeline withOwners = + adminClient.ingestionPipelines().get(pipeline.getId().toString(), "owners"); + assertNotNull(withOwners.getOwners(), "Inherited owners should be populated"); + assertEquals(1, withOwners.getOwners().size(), "Pipeline should inherit one owner"); + EntityReference inherited = withOwners.getOwners().get(0); + assertEquals( + serviceOwner.getId(), + inherited.getId(), + "Inherited owner should match service owner"); + assertTrue( + Boolean.TRUE.equals(inherited.getInherited()), + "Owner inherited from the parent service must be marked inherited=true"); + } finally { + adminClient.ingestionPipelines().delete(pipeline.getId().toString()); + } + } finally { + adminClient + .dashboardServices() + .delete(service.getId().toString(), Map.of("hardDelete", "true", "recursive", "true")); + } + } finally { + adminClient.users().delete(serviceOwner.getId()); + } + } + + @Test + void test_isOwnerPolicy_appliesToEditAndTrigger(TestNamespace ns) { + OpenMetadataClient adminClient = SdkClients.adminClient(); + String unique = UUID.randomUUID().toString().substring(0, 8); + + Rule ownerRule = + new Rule() + .withName("pipelineOwnerEditAndTrigger") + .withDescription("Allow owners to edit and trigger ingestion pipelines") + .withEffect(Rule.Effect.ALLOW) + .withOperations(List.of(MetadataOperation.EDIT_ALL, MetadataOperation.TRIGGER)) + .withResources(List.of("ingestionPipeline")) + .withCondition("isOwner()"); + Policy ownerPolicy = + adminClient + .policies() + .create( + new CreatePolicy() + .withName("ipauthPolicy_" + unique) + .withDescription("Owner-only policy for ingestion pipelines") + .withRules(List.of(ownerRule))); + + try { + Role ownerRole = + adminClient + .roles() + .create( + new CreateRole() + .withName("ipauthRole_" + unique) + .withPolicies(List.of(ownerPolicy.getFullyQualifiedName()))); + + try { + String ownerName = "ipauthowner_" + unique; + User pipelineOwner = + adminClient + .users() + .create( + new CreateUser() + .withName(ownerName) + .withEmail(ownerName + "@test.openmetadata.org") + .withRoles(List.of(ownerRole.getId()))); + + String otherName = "ipauthother_" + unique; + User otherUser = + adminClient + .users() + .create( + new CreateUser() + .withName(otherName) + .withEmail(otherName + "@test.openmetadata.org")); + + try { + DashboardService service = DashboardServiceTestFactory.createMetabase(ns); + DashboardService fetchedService = + adminClient.dashboardServices().get(service.getId().toString()); + fetchedService.setOwners(List.of(pipelineOwner.getEntityReference())); + adminClient.dashboardServices().update(service.getId().toString(), fetchedService); + + try { + IngestionPipeline pipeline = + adminClient + .ingestionPipelines() + .create( + new CreateIngestionPipeline() + .withName(ns.prefix("ipauthPipeline_" + unique)) + .withPipelineType(PipelineType.METADATA) + .withService(service.getEntityReference()) + .withSourceConfig( + new SourceConfig() + .withConfig(new DashboardServiceMetadataPipeline())) + .withAirflowConfig(new AirflowConfig().withStartDate(START_DATE))); + + try { + OpenMetadataClient ownerClient = + SdkClients.createClient(ownerName, ownerName, new String[] {}); + OpenMetadataClient otherClient = + SdkClients.createClient(otherName, otherName, new String[] {}); + + // Owner can PATCH displayName. + IngestionPipeline ownerEdit = + adminClient.ingestionPipelines().get(pipeline.getId().toString()); + ownerEdit.setDisplayName("owner-updated-display-name"); + ownerClient.ingestionPipelines().update(pipeline.getId().toString(), ownerEdit); + + // Non-owner cannot PATCH displayName. + IngestionPipeline otherEdit = + adminClient.ingestionPipelines().get(pipeline.getId().toString()); + otherEdit.setDisplayName("non-owner-attempt"); + assertThrows( + Exception.class, + () -> + otherClient + .ingestionPipelines() + .update(pipeline.getId().toString(), otherEdit), + "Non-owner PATCH should be forbidden"); + + // Owner can trigger. + String triggerPath = "/v1/services/ingestionPipelines/trigger/" + pipeline.getId(); + ownerClient.getHttpClient().execute(HttpMethod.POST, triggerPath, null, Void.class); + + // Non-owner cannot trigger. + assertThrows( + Exception.class, + () -> + otherClient + .getHttpClient() + .execute(HttpMethod.POST, triggerPath, null, Void.class), + "Non-owner trigger should be forbidden"); + } finally { + adminClient.ingestionPipelines().delete(pipeline.getId().toString()); + } + } finally { + adminClient + .dashboardServices() + .delete( + service.getId().toString(), Map.of("hardDelete", "true", "recursive", "true")); + } + } finally { + adminClient.users().delete(otherUser.getId()); + adminClient.users().delete(pipelineOwner.getId()); + } + } finally { + adminClient.roles().delete(ownerRole.getId()); + } + } finally { + adminClient.policies().delete(ownerPolicy.getId()); + } + } +} diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/IngestionPipelineRepository.java b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/IngestionPipelineRepository.java index 04c121b7c27f..5a022806d14a 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/IngestionPipelineRepository.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/jdbi3/IngestionPipelineRepository.java @@ -15,6 +15,7 @@ import static org.openmetadata.schema.type.EventType.ENTITY_FIELDS_CHANGED; import static org.openmetadata.schema.type.EventType.ENTITY_UPDATED; +import static org.openmetadata.schema.type.Include.ALL; import static org.openmetadata.service.Entity.INGESTION_PIPELINE; import jakarta.ws.rs.core.Response; @@ -67,6 +68,7 @@ import org.openmetadata.service.Entity; import org.openmetadata.service.OpenMetadataApplicationConfig; import org.openmetadata.service.events.lifecycle.EntityLifecycleEventDispatcher; +import org.openmetadata.service.exception.EntityNotFoundException; import org.openmetadata.service.logstorage.LogStorageInterface; import org.openmetadata.service.logstorage.S3LogStorage.LogStreamListener; import org.openmetadata.service.monitoring.IngestionProgressTracker; @@ -150,6 +152,24 @@ public void setFields( } } + @Override + public void setInheritedFields(IngestionPipeline ingestionPipeline, Fields fields) { + EntityReference serviceRef = ingestionPipeline.getService(); + if (serviceRef == null) { + return; + } + try { + EntityInterface parent = Entity.getEntity(serviceRef, "owners,domains", ALL); + inheritOwners(ingestionPipeline, fields, parent); + inheritDomains(ingestionPipeline, fields, parent); + } catch (EntityNotFoundException e) { + LOG.debug( + "Parent service {} not found for ingestion pipeline {}; skipping owner/domain inheritance", + serviceRef.getFullyQualifiedName(), + ingestionPipeline.getFullyQualifiedName()); + } + } + @Override public void setFieldsInBulk(Fields fields, List entities) { if (entities == null || entities.isEmpty()) { diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/migration/mysql/v1129/Migration.java b/openmetadata-service/src/main/java/org/openmetadata/service/migration/mysql/v1129/Migration.java new file mode 100644 index 000000000000..4d3924ae4610 --- /dev/null +++ b/openmetadata-service/src/main/java/org/openmetadata/service/migration/mysql/v1129/Migration.java @@ -0,0 +1,22 @@ +package org.openmetadata.service.migration.mysql.v1129; + +import static org.openmetadata.service.migration.utils.v1129.MigrationUtil.addTriggerOperationToDefaultBotPolicies; +import static org.openmetadata.service.migration.utils.v1129.MigrationUtil.addTriggerRuleToDataStewardPolicy; + +import lombok.SneakyThrows; +import org.openmetadata.service.migration.api.MigrationProcessImpl; +import org.openmetadata.service.migration.utils.MigrationFile; + +public class Migration extends MigrationProcessImpl { + + public Migration(MigrationFile migrationFile) { + super(migrationFile); + } + + @Override + @SneakyThrows + public void runDataMigration() { + addTriggerOperationToDefaultBotPolicies(collectionDAO); + addTriggerRuleToDataStewardPolicy(collectionDAO); + } +} diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/migration/mysql/v1130/Migration.java b/openmetadata-service/src/main/java/org/openmetadata/service/migration/mysql/v1130/Migration.java index 9584febe0a43..d7592a4c154a 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/migration/mysql/v1130/Migration.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/migration/mysql/v1130/Migration.java @@ -1,5 +1,8 @@ package org.openmetadata.service.migration.mysql.v1130; +import static org.openmetadata.service.migration.utils.v1129.MigrationUtil.addTriggerOperationToDefaultBotPolicies; +import static org.openmetadata.service.migration.utils.v1129.MigrationUtil.addTriggerRuleToDataStewardPolicy; + import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.openmetadata.service.migration.api.MigrationProcessImpl; @@ -31,5 +34,7 @@ public void runDataMigration() { LOG.error("v1130 glossaryTerm version relatedTerms transform failed; re-run to retry.", e); } MigrationUtil.addTableColumnSearchSettings(); + addTriggerOperationToDefaultBotPolicies(collectionDAO); + addTriggerRuleToDataStewardPolicy(collectionDAO); } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/migration/postgres/v1129/Migration.java b/openmetadata-service/src/main/java/org/openmetadata/service/migration/postgres/v1129/Migration.java new file mode 100644 index 000000000000..9b008f413532 --- /dev/null +++ b/openmetadata-service/src/main/java/org/openmetadata/service/migration/postgres/v1129/Migration.java @@ -0,0 +1,22 @@ +package org.openmetadata.service.migration.postgres.v1129; + +import static org.openmetadata.service.migration.utils.v1129.MigrationUtil.addTriggerOperationToDefaultBotPolicies; +import static org.openmetadata.service.migration.utils.v1129.MigrationUtil.addTriggerRuleToDataStewardPolicy; + +import lombok.SneakyThrows; +import org.openmetadata.service.migration.api.MigrationProcessImpl; +import org.openmetadata.service.migration.utils.MigrationFile; + +public class Migration extends MigrationProcessImpl { + + public Migration(MigrationFile migrationFile) { + super(migrationFile); + } + + @Override + @SneakyThrows + public void runDataMigration() { + addTriggerOperationToDefaultBotPolicies(collectionDAO); + addTriggerRuleToDataStewardPolicy(collectionDAO); + } +} diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/migration/postgres/v1130/Migration.java b/openmetadata-service/src/main/java/org/openmetadata/service/migration/postgres/v1130/Migration.java index 64f070b32790..d43dee9f5c11 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/migration/postgres/v1130/Migration.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/migration/postgres/v1130/Migration.java @@ -1,5 +1,8 @@ package org.openmetadata.service.migration.postgres.v1130; +import static org.openmetadata.service.migration.utils.v1129.MigrationUtil.addTriggerOperationToDefaultBotPolicies; +import static org.openmetadata.service.migration.utils.v1129.MigrationUtil.addTriggerRuleToDataStewardPolicy; + import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.openmetadata.service.migration.api.MigrationProcessImpl; @@ -31,5 +34,7 @@ public void runDataMigration() { LOG.error("v1130 glossaryTerm version relatedTerms transform failed; re-run to retry.", e); } MigrationUtil.addTableColumnSearchSettings(); + addTriggerOperationToDefaultBotPolicies(collectionDAO); + addTriggerRuleToDataStewardPolicy(collectionDAO); } } diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v1129/MigrationUtil.java b/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v1129/MigrationUtil.java new file mode 100644 index 000000000000..77ce7f54fe46 --- /dev/null +++ b/openmetadata-service/src/main/java/org/openmetadata/service/migration/utils/v1129/MigrationUtil.java @@ -0,0 +1,88 @@ +package org.openmetadata.service.migration.utils.v1129; + +import static org.openmetadata.service.migration.utils.v160.MigrationUtil.addOperationsToPolicyRule; + +import java.util.List; +import lombok.extern.slf4j.Slf4j; +import org.openmetadata.schema.entity.policies.Policy; +import org.openmetadata.schema.entity.policies.accessControl.Rule; +import org.openmetadata.schema.type.Include; +import org.openmetadata.schema.type.MetadataOperation; +import org.openmetadata.schema.utils.JsonUtils; +import org.openmetadata.service.Entity; +import org.openmetadata.service.exception.EntityNotFoundException; +import org.openmetadata.service.jdbi3.CollectionDAO; +import org.openmetadata.service.jdbi3.PolicyRepository; + +@Slf4j +public class MigrationUtil { + + private MigrationUtil() {} + + /** + * Retrofits seeded bot policies that grant broad {@code EditAll} on {@code ["All"]} resources + * with the {@code Trigger} operation. Pre-fix these identities could trigger pipelines because + * {@code /trigger} skipped authz; the migration preserves that behavior under the new authz + * enforcement (GH-27962). + * + *

Each entry is idempotent via {@link + * org.openmetadata.service.migration.utils.v160.MigrationUtil#addOperationsToPolicyRule}. + */ + public static void addTriggerOperationToDefaultBotPolicies(CollectionDAO collectionDAO) { + record PolicyRule(String policy, String rule) {} + List targets = + List.of( + new PolicyRule("IngestionBotPolicy", "IngestionBotRule-Allow"), + new PolicyRule("LineageBotPolicy", "LineageBotRule-Allow"), + new PolicyRule("ProfilerBotPolicy", "ProfilerBotBotRule-Allow"), + new PolicyRule("QualityBotPolicy", "QualityBotBotRule-Allow"), + new PolicyRule("UsageBotPolicy", "UsageBotRule-Allow-Usage")); + for (PolicyRule t : targets) { + addOperationsToPolicyRule( + t.policy(), t.rule(), List.of(MetadataOperation.TRIGGER), collectionDAO); + } + } + + /** + * Adds a dedicated {@code DataStewardPolicy-TriggerRule} to the existing {@code + * DataStewardPolicy} if not already present. Data stewards already have {@code EditOwners} on + * all resources, so they could already reach trigger via an ownership rewrite; this rule makes + * the capability explicit for audit clarity rather than burying it inside the existing edit + * rule. + * + *

Mirrors the new-rule shape used by {@code + * v180.MigrationUtil.addDenyDisplayNameRuleToBotPolicies}. Idempotent — skips when the rule + * already exists. + */ + public static void addTriggerRuleToDataStewardPolicy(CollectionDAO collectionDAO) { + PolicyRepository repository = (PolicyRepository) Entity.getEntityRepository(Entity.POLICY); + try { + Policy policy = repository.findByName("DataStewardPolicy", Include.NON_DELETED); + boolean hasTriggerRule = + policy.getRules().stream() + .anyMatch( + r -> + "DataStewardPolicy-TriggerRule".equals(r.getName()) + && r.getEffect() == Rule.Effect.ALLOW + && r.getOperations() != null + && r.getOperations().contains(MetadataOperation.TRIGGER)); + if (!hasTriggerRule) { + Rule triggerRule = + new Rule() + .withName("DataStewardPolicy-TriggerRule") + .withResources(List.of("all")) + .withOperations(List.of(MetadataOperation.TRIGGER)) + .withEffect(Rule.Effect.ALLOW); + policy.getRules().add(triggerRule); + collectionDAO + .policyDAO() + .update(policy.getId(), policy.getFullyQualifiedName(), JsonUtils.pojoToJson(policy)); + LOG.info("Added DataStewardPolicy-TriggerRule to DataStewardPolicy"); + } else { + LOG.debug("DataStewardPolicy already has TriggerRule, skipping"); + } + } catch (EntityNotFoundException ex) { + LOG.warn("DataStewardPolicy not found, skipping TriggerRule addition"); + } + } +} diff --git a/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/ingestionpipelines/IngestionPipelineResource.java b/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/ingestionpipelines/IngestionPipelineResource.java index 9216cdd4eb2b..510ff88282af 100644 --- a/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/ingestionpipelines/IngestionPipelineResource.java +++ b/openmetadata-service/src/main/java/org/openmetadata/service/resources/services/ingestionpipelines/IngestionPipelineResource.java @@ -1337,6 +1337,8 @@ private PipelineServiceClientResponse deployPipelineInternal( public PipelineServiceClientResponse triggerPipelineInternal( UUID id, UriInfo uriInfo, SecurityContext securityContext, String botName) { + OperationContext operationContext = new OperationContext(entityType, MetadataOperation.TRIGGER); + authorizer.authorize(securityContext, operationContext, getResourceContextById(id)); if (pipelineServiceClient == null) { return new PipelineServiceClientResponse() .withCode(200) @@ -1346,7 +1348,6 @@ public PipelineServiceClientResponse triggerPipelineInternal( IngestionPipeline ingestionPipeline = repository.get(uriInfo, id, fields); CreateResourceContext createResourceContext = new CreateResourceContext<>(entityType, ingestionPipeline); - OperationContext operationContext = new OperationContext(entityType, MetadataOperation.TRIGGER); limits.enforceLimits(securityContext, createResourceContext, operationContext); if (CommonUtil.nullOrEmpty(botName)) { // Use Default Ingestion Bot diff --git a/openmetadata-service/src/main/resources/json/data/policy/DataStewardPolicy.json b/openmetadata-service/src/main/resources/json/data/policy/DataStewardPolicy.json index 76a586bfcb12..6b894ace543b 100644 --- a/openmetadata-service/src/main/resources/json/data/policy/DataStewardPolicy.json +++ b/openmetadata-service/src/main/resources/json/data/policy/DataStewardPolicy.json @@ -12,6 +12,12 @@ "resources" : ["all"], "operations": ["ViewAll", "EditDescription", "EditDisplayName", "EditLineage", "EditOwners", "EditTags", "EditTier", "EditGlossaryTerms", "EditCertification"], "effect": "allow" + }, + { + "name": "DataStewardPolicy-TriggerRule", + "resources": ["all"], + "operations": ["Trigger"], + "effect": "allow" } ] -} \ No newline at end of file +} diff --git a/openmetadata-service/src/main/resources/json/data/policy/IngestionBotPolicy.json b/openmetadata-service/src/main/resources/json/data/policy/IngestionBotPolicy.json index 7b75e412f8fd..dc7cb21edaf3 100644 --- a/openmetadata-service/src/main/resources/json/data/policy/IngestionBotPolicy.json +++ b/openmetadata-service/src/main/resources/json/data/policy/IngestionBotPolicy.json @@ -11,7 +11,7 @@ "name": "IngestionBotRule-Allow", "description" : "Allow ingestion bots to create/update/delete data entities", "resources" : ["All"], - "operations": ["Create", "BulkCreate", "BulkUpdate", "EditAll", "ViewAll", "Delete"], + "operations": ["Create", "BulkCreate", "BulkUpdate", "EditAll", "ViewAll", "Delete", "Trigger"], "effect": "allow" }, { diff --git a/openmetadata-service/src/main/resources/json/data/policy/LineageBotPolicy.json b/openmetadata-service/src/main/resources/json/data/policy/LineageBotPolicy.json index 54e26cd92c30..4028df985789 100644 --- a/openmetadata-service/src/main/resources/json/data/policy/LineageBotPolicy.json +++ b/openmetadata-service/src/main/resources/json/data/policy/LineageBotPolicy.json @@ -18,7 +18,7 @@ "name": "LineageBotRule-Allow", "description" : "Allow creating and updating lineage", "resources" : ["All"], - "operations": ["EditAll", "ViewAll"], + "operations": ["EditAll", "ViewAll", "Trigger"], "effect": "allow" }, { diff --git a/openmetadata-service/src/main/resources/json/data/policy/ProfilerBotPolicy.json b/openmetadata-service/src/main/resources/json/data/policy/ProfilerBotPolicy.json index 042b882d47d9..f723c5d7826d 100644 --- a/openmetadata-service/src/main/resources/json/data/policy/ProfilerBotPolicy.json +++ b/openmetadata-service/src/main/resources/json/data/policy/ProfilerBotPolicy.json @@ -11,7 +11,7 @@ "name": "ProfilerBotBotRule-Allow", "description" : "Allow updating sample data, profile data, and tests for all the resources.", "resources" : ["All"], - "operations": ["EditAll", "ViewAll"], + "operations": ["EditAll", "ViewAll", "Trigger"], "effect": "allow" }, { diff --git a/openmetadata-service/src/main/resources/json/data/policy/QualityBotPolicy.json b/openmetadata-service/src/main/resources/json/data/policy/QualityBotPolicy.json index 1ef5c06808c9..dc1d8cc04c90 100644 --- a/openmetadata-service/src/main/resources/json/data/policy/QualityBotPolicy.json +++ b/openmetadata-service/src/main/resources/json/data/policy/QualityBotPolicy.json @@ -11,7 +11,7 @@ "name": "QualityBotBotRule-Allow", "description" : "Allow updating sample data, profile data, and tests for all the resources.", "resources" : ["All"], - "operations": ["EditAll", "ViewAll"], + "operations": ["EditAll", "ViewAll", "Trigger"], "effect": "allow" }, { diff --git a/openmetadata-service/src/main/resources/json/data/policy/UsageBotPolicy.json b/openmetadata-service/src/main/resources/json/data/policy/UsageBotPolicy.json index 993c02e99a9e..f8400ea4d2c5 100644 --- a/openmetadata-service/src/main/resources/json/data/policy/UsageBotPolicy.json +++ b/openmetadata-service/src/main/resources/json/data/policy/UsageBotPolicy.json @@ -18,7 +18,7 @@ "name": "UsageBotRule-Allow-Usage", "description" : "Allow handling usage and lifecycle information.", "resources" : ["All"], - "operations": ["EditAll", "ViewAll"], + "operations": ["EditAll", "ViewAll", "Trigger"], "effect": "allow" }, {