diff --git a/awx/main/migrations/0197_inventory_opa_query_path_jobtemplate_opa_query_path_and_more.py b/awx/main/migrations/0197_inventory_opa_query_path_jobtemplate_opa_query_path_and_more.py new file mode 100644 index 000000000000..7874d3ca82a8 --- /dev/null +++ b/awx/main/migrations/0197_inventory_opa_query_path_jobtemplate_opa_query_path_and_more.py @@ -0,0 +1,46 @@ +# Generated by Django 4.2.16 on 2025-02-25 18:52 + +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='Specifies the OPA policy rule path in the format / (e.g., job_template/response) or . (e.g., job_template.response). The is optional and can also be nested (e.g., job_template/response/allowed). Set to NULL if FEATURE_POLICY_AS_CODE_ENABLED is False.', + max_length=128, + null=True, + ), + ), + migrations.AddField( + model_name='jobtemplate', + name='opa_query_path', + field=models.CharField( + blank=True, + default=None, + help_text='Specifies the OPA policy rule path in the format / (e.g., job_template/response) or . (e.g., job_template.response). The is optional and can also be nested (e.g., job_template/response/allowed). Set to NULL if FEATURE_POLICY_AS_CODE_ENABLED is False.', + max_length=128, + null=True, + ), + ), + migrations.AddField( + model_name='organization', + name='opa_query_path', + field=models.CharField( + blank=True, + default=None, + help_text='Specifies the OPA policy rule path in the format / (e.g., job_template/response) or . (e.g., job_template.response). The is optional and can also be nested (e.g., job_template/response/allowed). Set to NULL if FEATURE_POLICY_AS_CODE_ENABLED is False.', + 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 74% rename from awx/main/migrations/0197_delete_profile.py rename to awx/main/migrations/0198_delete_profile.py index 0dd8d8fc5ca4..c937e4bfb725 100644 --- a/awx/main/migrations/0197_delete_profile.py +++ b/awx/main/migrations/0198_delete_profile.py @@ -5,7 +5,7 @@ class Migration(migrations.Migration): dependencies = [ - ('main', '0196_indirect_managed_node_audit'), + ('main', '0197_inventory_opa_query_path_jobtemplate_opa_query_path_and_more'), ] 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 7c05bc2fb613..9ae0ecdf8e02 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 @@ 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 b7d0cb3e1a23..be224358d5cd 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 @@ 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 aaf89b440c12..8912c81d0cbe 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 @@ 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 f09b4f6bf012..5df8edca6575 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 @@ 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 7c8758f40b4f..0b61f981fc2a 100644 --- a/awx/main/models/inventory.py +++ b/awx/main/models/inventory.py @@ -43,6 +43,7 @@ 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 c6b8b0988301..6fde8d159e6f 100644 --- a/awx/main/models/jobs.py +++ b/awx/main/models/jobs.py @@ -51,6 +51,7 @@ RelatedJobsMixin, WebhookMixin, WebhookTemplateMixin, + OpaQueryPathMixin, ) from awx.main.constants import JOB_VARIABLE_PREFIXES @@ -192,7 +193,9 @@ def passwords_needed_to_start(self): 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 5df78e15b6d6..1b31a3a6a23c 100644 --- a/awx/main/models/mixins.py +++ b/awx/main/models/mixins.py @@ -42,6 +42,7 @@ 'TaskManagerInventoryUpdateMixin', 'ExecutionEnvironmentMixin', 'CustomVirtualEnvMixin', + 'OpaQueryPathMixin', ] @@ -692,3 +693,21 @@ def update_webhook_status(self, status): 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=_( + "Specifies the OPA policy rule path in the format / (e.g., job_template/response)" + " or . (e.g., job_template.response)." + " The is optional and can also be nested (e.g., job_template/response/allowed)." + " Set to NULL if FEATURE_POLICY_AS_CODE_ENABLED is False." + ), + ) diff --git a/awx/main/models/organization.py b/awx/main/models/organization.py index 23ce7598a296..49929307f866 100644 --- a/awx/main/models/organization.py +++ b/awx/main/models/organization.py @@ -22,12 +22,12 @@ 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 """