[AAP-86051] Wire DAB validation bypass observability for Controller - #16672
vidyanambiar wants to merge 5 commits into
Conversation
Register ORM bypass signals and AWX caller prefixes at startup, and audit bulk host create before bulk_create. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Important Draft PR not reviewedDraft PRs are not automatically reviewed by default.
To automatically review draft PRs, update your CodeRabbit configuration: reviews:
auto_review:
drafts: trueComment |
Log Tier 1/2 bypass violations for WorkflowJobNode prompt fields stored in char_prompts, which post_save and bulk CharField scans do not cover alone. Co-authored-by: Cursor <cursoragent@cursor.com>
Add field-scoped audit_bulk_update_instances for bulk_update_sorted_by_id and scheduler job_explanation batches. Expand functional and unit tests for bulk host/workflow create and bulk update bypass logging. Co-authored-by: Cursor <cursoragent@cursor.com>
|
Two P2 findings from reviewing the AWX integration against the companion DAB PR:
AI-generated. Review for accuracy. |
SUMMARY
Wire django-ansible-base#1147 validation bypass observability into Controller: log Tier 1/Tier 2 violations when registered models are written outside
CleanTextMixinserializers (warnings only; ORM writes are not blocked).Depends on: DAB #1147 (
register_validation_signals,audit_bulk_model_instances, callerextend_*APIs). Pin DAB branchAAP-86051(Controller does not import queryset helpers; EDA and other services may need4d68525+foraudited_queryset_update).DAB (after serializers load):
post_saveon registered models for.save()/.create().Controller hooks (
post_savedoes not run for bulk):BulkHostCreateSerializer.create→audit_bulk_model_instancesbeforeHost.objects.bulk_createBulkJobLaunchSerializer.create→audit_workflow_job_nodes_for_bulk_createbeforeWorkflowJobNode.objects.bulk_createchar_promptspseudo-fields (limit,job_tags,skip_tags,scm_branch)bulk_update_sorted_by_idinawx/main/utils/db.pyfields=that are registered Char/Texttask_manager.pybeforeUnifiedJob.objects.bulk_update(..., ['job_explanation'])job_explanationonJobawx/main/utils/validation_bypass_observability.py— AWX-specific wiring on top of DAB (keeps bulk audit call sites thin):configure_validation_bypass_observability()(fromMainConfig.ready()): calls DABregister_validation_signals(); extends caller allowlist (awx.api.views,awx.api.serializers,awx.main.tasks,awx.main.management,awx.main.utils) and internal denylist (awx.main.models,awx.main.signals,awx.main.dispatch) so[caller: module:line]in logs points at product code, not Django ORM plumbing.MainConfig.ready()also importsawx.api.serializerssoCleanTextMixinserializers populate DAB_protected_models.audit_workflow_job_nodes_for_bulk_create()— used fromBulkJobLaunchSerializer.createbeforeWorkflowJobNode.objects.bulk_create. Delegates to DABaudit_bulk_model_instancesfor real Char/Text columns, then auditschar_promptspseudo-fields (limit,job_tags,skip_tags,scm_branch) viagetattr(not visible to_get_text_fields). Caller for prompt violations is resolved at this helper (_get_caller_info()); logs may showvalidation_bypass_observability.audit_workflow_job_nodes_for_bulk_create:…becauseawx.main.utilsis allowlisted beforeawx.api.serializerson the stack.audit_bulk_update_instances()— field-scoped bulk-update audit used frombulk_update_sorted_by_idandtask_manager.py; only columns infields=that are registered Char/Text are checked (avoids noise when bulk-updating JSON such as Hostansible_facts).Intentionally not hooked: Host
ansible_factsbulk-only updates (JSON); productionQuerySet.update()on registered user text (none triaged); job-event/metrics bulk on non-registry models.API enforcement unchanged: invalid serializer input still returns 400 when
ENHANCED_INPUT_VALIDATION_ENABLEDis on.related AAP-86051
ISSUE TYPE
COMPONENT NAME
STEPS TO REPRODUCE AND EXTRA INFO
Prerequisites: Install DAB from #1147 (
AAP-86051). Deploy or run AWX from this branch.Verify:
awx-manage shell: createOrganizationwith baddescription→ORM bypass:in logs (ansible_base.lib.utils.validation_signals); row still saved.BulkHostCreateSerializer.create()without serializer validation →ORM bypass (bulk_create):for bad hostdescription.BulkJobLaunchSerializer.create()with badlimiton a node →ORM bypass (bulk_create):forlimit/WorkflowJobNode(viaaudit_workflow_job_nodes_for_bulk_create;[caller: …]often names that helper).bulk_update_sorted_by_id(Job, [job], fields=['job_explanation'])with badjob_explanation→ORM bypass (bulk_update):.POST /api/v2/bulk/host_create/(or gateway/api/controller/v2/bulk/host_create/) with baddescriptionand enforcement on → 400; noORM bypass.CleanTextMixinserializer → noORM bypass(DAB context var).Regression / new tests:
awx/main/tests/functional/test_bulk.py— bulk host and bulk job launch bypass logging (enforcement mocked off).awx/main/tests/unit/utils/test_validation_bypass_observability.py— workflow pseudo-fields,audit_bulk_update_instances, hook order indb.py/task_manager.py.Optional demo: kind-devel walkthrough in
controller-validation-bypass-demo.md(local doc).