mirror of
https://github.com/gmfricke/cmmc_audit.git
synced 2026-07-02 13:23:04 -06:00
92 lines
5.9 KiB
Markdown
92 lines
5.9 KiB
Markdown
# CMMC Audit Plugin
|
|
|
|
The in-tree package is named `coldfront.plugins.cmmc_audit`, the Django app label remains `cmmc_audit` for migration compatibility, and the user-facing Django admin label is **CMMC Audit**.
|
|
|
|
This plugin records append-only operational evidence for ColdFront workflows. It keeps raw forensic data such as `old_values`, `new_values`, target type/id, request path, IP address, source, and source id while adding CMMC-oriented admin columns for reviewers.
|
|
|
|
## Evidence Coverage
|
|
|
|
AC evidence:
|
|
|
|
- Project membership changes: users added, removed, activated, and role changes.
|
|
- Project archival, deletion, status changes, and PI changes.
|
|
- PI and admin privilege changes.
|
|
- Allocation requests, approvals/status changes, renewals, and disable/revoke outcomes.
|
|
- Direct allocation renewal requests from `AllocationRenewView.post()`.
|
|
|
|
AU evidence:
|
|
|
|
- Append-only audit events with event time, actor, request path, IP address, and target.
|
|
- Generic Django admin add/change/delete actions.
|
|
- Project review submission/completion/status changes.
|
|
- Best-effort historical reconstruction from Django admin logs and selected ColdFront history tables.
|
|
|
|
CM evidence:
|
|
|
|
- Resource creation, update, and deletion.
|
|
- Resource changes preserve raw old/new values for configuration review.
|
|
|
|
## Project Review Workflow Coverage
|
|
|
|
Discovered ColdFront project review hooks:
|
|
|
|
- `Project.force_review` and `Project.requires_review` are fields on `coldfront.core.project.models.Project`. `Project.needs_review` is computed; it returns true when the project is forced, when annual review is enabled and required, and when the project is older than the review interval.
|
|
- PI/manager submission is handled directly by `ProjectReviewView.post()` at `/project/<pk>/review/`. It creates a `ProjectReview` with status `Pending` and clears `Project.force_review`.
|
|
- Staff completion is handled directly by `ProjectReviewCompleteView.get()` at `/project/project-review-complete/<project_review_pk>/`. It changes the `ProjectReview` status to `Completed`.
|
|
- Staff request-for-updates is implemented as `ProjectReviewEmailView`; it sends email but does not change `ProjectReview` status.
|
|
- There are no custom ColdFront project-review signals in this checkout.
|
|
|
|
Implemented semantic audit events:
|
|
|
|
- `project_review_forced`: emitted when `Project.force_review` changes from false to true.
|
|
- `project_review_submitted`: emitted from the PI/manager review submission view after a `ProjectReview` is created.
|
|
- `project_review_completed`: emitted from the staff completion view after status changes to `Completed`.
|
|
- `project_review_status_changed`: emitted for non-workflow `ProjectReview.status` changes, such as admin/manual edits.
|
|
|
|
Allocation workflow hooks:
|
|
|
|
- Allocation request/approval/disable events use ColdFront allocation signals where available.
|
|
- Direct allocation renewal requests are captured by wrapping `AllocationRenewView.post()` because that view changes status to `Renewal Requested` without emitting an allocation change request signal.
|
|
|
|
## Limitations
|
|
|
|
- Historical reconstruction is best effort. It cannot perfectly reconstruct user intent, free-form comments, IP addresses, request paths, or actions that were not stored in existing Django admin logs or ColdFront history tables.
|
|
- Django admin log reconstruction does not invent old/new values. When direction is unknown, messages say so explicitly.
|
|
- Annual review due state is computed by `Project.needs_review`; no database write or signal is emitted when a project merely becomes due by age.
|
|
- Request-for-updates email does not alter review state, so it is not logged as a review status event.
|
|
- Slurm partition restrictions and external account-disable actions are only captured if represented by ColdFront resource/allocation changes in this first pass.
|
|
- The plugin wraps selected review view methods at runtime to avoid modifying ColdFront core.
|
|
|
|
## Historical Reconstruction
|
|
|
|
Historical reconstruction is implemented as an explicit management command. It is never run at startup or from `AppConfig.ready()`.
|
|
|
|
Recommended sequence:
|
|
|
|
```bash
|
|
python manage.py backfill_cmmc_audit --dry-run
|
|
python manage.py backfill_cmmc_audit --commit
|
|
```
|
|
|
|
The command records a `BackfillRun` named `initial_historical_backfill` when committed. A second `--commit` exits cleanly after a completed run. Use `--commit --force` to rerun; duplicate protection checks `source`, `source_id`, and `action`, so previously reconstructed events are skipped.
|
|
|
|
Reconstructed entries are marked with `is_reconstructed=True`, keep the original event time when available, and include `source`/`source_id` for forensic traceability. Django admin log entries use `source='django_admin_log'`. ColdFront history entries use `source='coldfront_history'`.
|
|
|
|
Audit rows are append-only and the backfill command does not rewrite existing reconstructed rows. During development testing, reset only the reconstructed rows and run marker before backfilling again if you need to validate changed reconstruction output:
|
|
|
|
```python
|
|
from coldfront.plugins.cmmc_audit.models import AuditEvent, BackfillRun
|
|
|
|
AuditEvent.objects.filter(is_reconstructed=True).delete()
|
|
BackfillRun.objects.filter(name="initial_historical_backfill").delete()
|
|
```
|
|
|
|
The command reconstructs:
|
|
|
|
- Generic admin add/change/delete events from `django.contrib.admin.models.LogEntry`.
|
|
- Conservative semantic admin-log events for PI status changes with unknown direction, project deletion, project user role changes, and resource create/change/delete.
|
|
- Selected ColdFront history events when adjacent records expose clear old/new state: project archival/status/PI changes, allocation status changes, allocation end-date increases, project user role changes, and resource create/change/delete.
|
|
|
|
## Development Validation
|
|
|
|
Smoke tests should use Django's test database or an explicit rollback/cleanup block. Do not leave fixture users, projects, resources, allocations, or audit rows in a normal development database; those rows appear in the same evidence table as real operational events.
|