v1.6.5 — Bootstrap fix + decoupled AWS converters with refresh UI
v1.6.5 — Bootstrap fix + decoupled AWS converters with refresh UI
Two coordinated improvements:
- Cleanup of the v1.6.4 AWS Labs bootstrap initializer (#492) — fixes the
ApplicationRecordautoloadNameErrorand the 3× firing per container
boot that surfaced during thesparc-iacv1.6.4 deploy. - Decoupled AWS converters with operator-facing refresh UI (#494) —
splits v1.6.4's composite into two first-class converters that operators
can refresh independently from the converter management page.
🐛 Fixes — Issue #492
- Defect 1: ApplicationRecord autoload
NameErrorduring the
sparc:bootstrap_adminrake task. The v1.6.4 initializer referenced
CdefDocumentinsideafter_initialize, racing with the autoload chain.
Fix: extracted tolib/aws_labs_cdef_bootstrap.rband invoked from
Rails.application.config.to_prepare, which runs after the application is
fully loaded. - Defect 2: bootstrap fired 3× per container boot (rake task, seed
task, and Puma each re-loaded Rails). Fix:Rails.cachelock
(aws_labs_cdef_bootstrap:fired, 1-hour TTL). In production, Solid Cache
is Postgres-backed so the lock is shared across all three processes.
Lock-held subsequent calls return:skipped_lock_heldinstead of
double-enqueueing.
✨ Features — Issue #494
Two-converter architecture replaces the v1.6.4 composite:
| Converter | Source | Refresh button | Rows |
|---|---|---|---|
aws_config_to_nist (NEW) |
mitre/heimdall2 (Apache-2.0, vendored) |
"Refresh from MITRE" | 432 / 106 Config Rules |
aws_security_hub_to_nist |
AWS Security Hub User Guide (scraped) | "Refresh from AWS docs" | 2 168 / 303 SecHub controls |
Runtime two-hop chain in AwsLabsCdefImportService (replaces the
seed-time composite logic):
- Direct lookup in
aws_security_hub_to_nist(AWS-published) →
source = "aws_direct" - If unmapped, pull
aws_config_rulefrom the SecHub → Config Rule
bridge file - Look up that Config Rule in
aws_config_to_nist→
source = "via_config_rule" - Else: leave unmapped (surfaced in
mappings:coverage_report)
Operator UX parity with DISA CCI refresh:
- Refresh buttons on
/converters/:idfor both AWS converter types
(RBAC:converters.write) - Bootstrap-5 confirmation modal
- Background job (
ConverterRefreshJobdispatcher) with stage stamps
(fetching→parsing→loading→complete) - Auto-refresh status banner via
<meta http-equiv="refresh">while
processing - Operator hand-edits preserved: refresh services only delete rows
with their owncategoryvalue - Audit log:
converter_refresh_started
Coverage report rewritten (bundle exec rake mappings:coverage_report)
to surface both converters and the chain — reports direct matches,
chained matches, and unmapped controls with up to 30 sample IDs.
Type badge colors added for both converters (AWS orange / Sec Hub
burnt orange) on /converters.
🗃️ Database migration
db/migrate/20260519000000_cleanup_v164_mitre_fallback_rows.rb — one-time
cleanup: removes v1.6.4 stale category=mitre_fallback rows from the
existing aws_security_hub_to_nist Converter so the seed loader creates
the clean split. aws_direct rows preserved; operator hand-edits with
other category values preserved.
Testing
- 24 new examples; full suite 2 290 / 0 / 2 pending (pre-existing pending)
- Rubocop clean
- Real-data sanity on dev DB: migration removed 80 stale rows; seeds
producedaws_config_to_nist(432 / 106) +aws_security_hub_to_nist
(2 168 / 303)
Upgrade Notes
No env-var changes. On deploy:
bin/rails db:migrate— applies the cleanup migrationbin/rails db:seed— createsaws_config_to_nistand rebuilds
aws_security_hub_to_nist(idempotent)- Existing AWS Labs CDEFs keep their v1.6.4
nist_mapping_sourcetags
until the next AWS Labs refresh. Trigger via the "Refresh from AWS
Labs" button on/cdef_documentsor
AwsLabsCdefRefreshJob.perform_now(force: true)to upgrade tags to
the newaws_direct/via_config_rulevocabulary.
Full Changelog: v1.6.4...v1.6.5