diff --git a/awx/main/migrations/0197_add_opa_query_path.py b/awx/main/migrations/0197_add_opa_query_path.py new file mode 100644 index 0000000000..fdab27fdc1 --- /dev/null +++ b/awx/main/migrations/0197_add_opa_query_path.py @@ -0,0 +1,46 @@ +# Generated by Django 4.2.18 on 2025-03-17 16:10 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('main', '0196_indirect_managed_node_audit'), + ] + + operations = [ + migrations.AddField( + model_name='inventory', + name='opa_query_path', + field=models.CharField( + blank=True, + default=None, + help_text='The query path for the OPA policy to evaluate prior to job execution. The query path should be formatted as package/rule.', + max_length=128, + null=True, + ), + ), + migrations.AddField( + model_name='jobtemplate', + name='opa_query_path', + field=models.CharField( + blank=True, + default=None, + help_text='The query path for the OPA policy to evaluate prior to job execution. The query path should be formatted as package/rule.', + max_length=128, + null=True, + ), + ), + migrations.AddField( + model_name='organization', + name='opa_query_path', + field=models.CharField( + blank=True, + default=None, + help_text='The query path for the OPA policy to evaluate prior to job execution. The query path should be formatted as package/rule.', + max_length=128, + null=True, + ), + ), + ] diff --git a/awx/main/migrations/0197_delete_profile.py b/awx/main/migrations/0198_delete_profile.py similarity index 82% rename from awx/main/migrations/0197_delete_profile.py rename to awx/main/migrations/0198_delete_profile.py index 0dd8d8fc5c..cb843cbf06 100644 --- a/awx/main/migrations/0197_delete_profile.py +++ b/awx/main/migrations/0198_delete_profile.py @@ -5,7 +5,7 @@ from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('main', '0196_indirect_managed_node_audit'), + ('main', '0197_add_opa_query_path'), ] operations = [ diff --git a/awx/main/migrations/0198_remove_sso_app_content.py b/awx/main/migrations/0199_remove_sso_app_content.py similarity index 96% rename from awx/main/migrations/0198_remove_sso_app_content.py rename to awx/main/migrations/0199_remove_sso_app_content.py index 7c05bc2fb6..9ae0ecdf8e 100644 --- a/awx/main/migrations/0198_remove_sso_app_content.py +++ b/awx/main/migrations/0199_remove_sso_app_content.py @@ -5,7 +5,7 @@ from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('main', '0197_delete_profile'), + ('main', '0198_delete_profile'), ] operations = [ diff --git a/awx/main/migrations/0199_alter_inventorysource_source_and_more.py b/awx/main/migrations/0200_alter_inventorysource_source_and_more.py similarity index 91% rename from awx/main/migrations/0199_alter_inventorysource_source_and_more.py rename to awx/main/migrations/0200_alter_inventorysource_source_and_more.py index b7d0cb3e1a..be224358d5 100644 --- a/awx/main/migrations/0199_alter_inventorysource_source_and_more.py +++ b/awx/main/migrations/0200_alter_inventorysource_source_and_more.py @@ -6,7 +6,7 @@ from django.db import migrations, models class Migration(migrations.Migration): dependencies = [ - ('main', '0198_remove_sso_app_content'), + ('main', '0199_remove_sso_app_content'), ] operations = [ diff --git a/awx/main/migrations/0200_alter_oauth2application_unique_together_and_more.py b/awx/main/migrations/0201_alter_oauth2application_unique_together_and_more.py similarity index 93% rename from awx/main/migrations/0200_alter_oauth2application_unique_together_and_more.py rename to awx/main/migrations/0201_alter_oauth2application_unique_together_and_more.py index aaf89b440c..8912c81d0c 100644 --- a/awx/main/migrations/0200_alter_oauth2application_unique_together_and_more.py +++ b/awx/main/migrations/0201_alter_oauth2application_unique_together_and_more.py @@ -6,7 +6,7 @@ from django.db import migrations class Migration(migrations.Migration): dependencies = [ - ('main', '0199_alter_inventorysource_source_and_more'), + ('main', '0200_alter_inventorysource_source_and_more'), ] operations = [ diff --git a/awx/main/migrations/0201_delete_token_cleanup_job.py b/awx/main/migrations/0202_delete_token_cleanup_job.py similarity index 96% rename from awx/main/migrations/0201_delete_token_cleanup_job.py rename to awx/main/migrations/0202_delete_token_cleanup_job.py index f09b4f6bf0..5df8edca65 100644 --- a/awx/main/migrations/0201_delete_token_cleanup_job.py +++ b/awx/main/migrations/0202_delete_token_cleanup_job.py @@ -8,7 +8,7 @@ from awx.main.migrations._create_system_jobs import delete_clear_tokens_sjt class Migration(migrations.Migration): dependencies = [ - ('main', '0200_alter_oauth2application_unique_together_and_more'), + ('main', '0201_alter_oauth2application_unique_together_and_more'), ] operations = [ diff --git a/awx/main/models/inventory.py b/awx/main/models/inventory.py index 7c8758f40b..0b61f981fc 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -43,6 +43,7 @@ from awx.main.models.mixins import ( TaskManagerInventoryUpdateMixin, RelatedJobsMixin, CustomVirtualEnvMixin, + OpaQueryPathMixin, ) from awx.main.models.notifications import ( NotificationTemplate, @@ -68,7 +69,7 @@ class InventoryConstructedInventoryMembership(models.Model): ) -class Inventory(CommonModelNameNotUnique, ResourceMixin, RelatedJobsMixin): +class Inventory(CommonModelNameNotUnique, ResourceMixin, RelatedJobsMixin, OpaQueryPathMixin): """ an inventory source contains lists and hosts. """ diff --git a/awx/main/models/jobs.py b/awx/main/models/jobs.py index c6b8b09883..6fde8d159e 100644 --- a/awx/main/models/jobs.py +++ b/awx/main/models/jobs.py @@ -51,6 +51,7 @@ from awx.main.models.mixins import ( RelatedJobsMixin, WebhookMixin, WebhookTemplateMixin, + OpaQueryPathMixin, ) from awx.main.constants import JOB_VARIABLE_PREFIXES @@ -192,7 +193,9 @@ class JobOptions(BaseModel): return needed -class JobTemplate(UnifiedJobTemplate, JobOptions, SurveyJobTemplateMixin, ResourceMixin, CustomVirtualEnvMixin, RelatedJobsMixin, WebhookTemplateMixin): +class JobTemplate( + UnifiedJobTemplate, JobOptions, SurveyJobTemplateMixin, ResourceMixin, CustomVirtualEnvMixin, RelatedJobsMixin, WebhookTemplateMixin, OpaQueryPathMixin +): """ A job template is a reusable job definition for applying a project (with playbook) to an inventory source with a given credential. diff --git a/awx/main/models/mixins.py b/awx/main/models/mixins.py index 5df78e15b6..373271aed8 100644 --- a/awx/main/models/mixins.py +++ b/awx/main/models/mixins.py @@ -42,6 +42,7 @@ __all__ = [ 'TaskManagerInventoryUpdateMixin', 'ExecutionEnvironmentMixin', 'CustomVirtualEnvMixin', + 'OpaQueryPathMixin', ] @@ -692,3 +693,16 @@ class WebhookMixin(models.Model): logger.debug("Webhook status update sent.") else: logger.error("Posting webhook status failed, code: {}\n" "{}\nPayload sent: {}".format(response.status_code, response.text, json.dumps(data))) + + +class OpaQueryPathMixin(models.Model): + class Meta: + abstract = True + + opa_query_path = models.CharField( + max_length=128, + blank=True, + null=True, + default=None, + help_text=_("The query path for the OPA policy to evaluate prior to job execution. The query path should be formatted as package/rule."), + ) diff --git a/awx/main/models/organization.py b/awx/main/models/organization.py index 23ce7598a2..49929307f8 100644 --- a/awx/main/models/organization.py +++ b/awx/main/models/organization.py @@ -22,12 +22,12 @@ from awx.main.models.rbac import ( ROLE_SINGLETON_SYSTEM_AUDITOR, ) from awx.main.models.unified_jobs import UnifiedJob -from awx.main.models.mixins import ResourceMixin, CustomVirtualEnvMixin, RelatedJobsMixin +from awx.main.models.mixins import ResourceMixin, CustomVirtualEnvMixin, RelatedJobsMixin, OpaQueryPathMixin __all__ = ['Organization', 'Team', 'UserSessionMembership'] -class Organization(CommonModel, NotificationFieldsModel, ResourceMixin, CustomVirtualEnvMixin, RelatedJobsMixin): +class Organization(CommonModel, NotificationFieldsModel, ResourceMixin, CustomVirtualEnvMixin, RelatedJobsMixin, OpaQueryPathMixin): """ An organization is the basic unit of multi-tenancy divisions """