feat(cli): add cloud-account repair command for org-onboarded AwsCfg accounts - #1845
Merged
Merged
Conversation
lokesh-vadlamudi
force-pushed
the
lvadlamudi/link-4430-config-repair
branch
5 times, most recently
from
July 15, 2026 20:30
e023c55 to
990b3f6
Compare
Re-registers a missing AwsCfg cloud-account integration for an AWS account onboarded through the AWS Config organization CloudFormation template. State-aware: re-registers when the member stack is healthy, or rebuilds the member StackSet instance first when the IAM role was dropped. The onboarding method is selected with --method (aws-cfg-org today; more templates and clouds planned). Supports --dry-run and --json.
lokesh-vadlamudi
force-pushed
the
lvadlamudi/link-4430-config-repair
branch
from
July 15, 2026 20:40
990b3f6 to
5b3489f
Compare
With --all instead of --account-id, repair enumerates every ACTIVE account under the StackSet's targeted OUs (recursively, excluding the org management account), diffs them against existing stack instances and AwsCfg integrations, rebuilds all missing member instances in one StackSet operation, and registers every unregistered account. Per-account registration failures are reported and exit non-zero instead of aborting the sweep. --dry-run reports the classified diff; --json emits it structured.
Single-account and --all modes now report already-onboarded with the
same {accountId, action} shape, and --all emits one JSON envelope for
every outcome (healthy, dry-run, repaired) with stable keys and
non-null arrays. stackParameter gained a found flag so targetOUsParam
can distinguish an absent OrganizationalUnits parameter from a
DescribeStacks API failure instead of swallowing the error.
lokesh-vadlamudi
marked this pull request as ready for review
July 16, 2026 20:04
lokesh-vadlamudi
enabled auto-merge (squash)
July 16, 2026 20:44
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Jira/Github ticket
https://lacework.atlassian.net/browse/LINK-4430
Summary
Adds
lacework cloud-account repairto re-register a missing cloud-account integration for an account onboarded through a Lacework onboarding template — one account with--account-id, or every broken account in the fleet with--all.The onboarding template is selected with
--method, named<cloud>-<template>. Onlyaws-cfg-org(AWS Config organization onboarding) is implemented today; more AWS templates and other clouds (gcp, azure) are planned as additional--methodvalues. The code is modular: each method lives in its own file (cloud_account_repair_aws_cfg_org.go) behind a small dispatch registry incloud_account_repair.go, so adding a method is a new file plus one registry entry.For
aws-cfg-org: the org-config setup Lambda registers each member account with Lacework but does not reconcile — if a registration (or the member stack) is dropped, replaying is the only recovery. This command does the recovery synchronously and is state-aware:It derives the member role ARN and external id from the StackSet instance's stack id (matching how the config-org member template builds them), so it registers directly against the Lacework API. Supports
--dry-runand--json.With
--all(mutually exclusive with--account-id), the command sweeps the whole fleet instead: it enumerates every ACTIVE account under the StackSet's targeted OUs (recursively, via AWS Organizations; the org management account is excluded since service-managed StackSets never deploy to it), diffs them against the existing stack instances and AwsCfg integrations, rebuilds all missing member instances in a single StackSet operation, then registers every unregistered account. Per-account registration failures are reported in the summary and exit non-zero rather than aborting the sweep.--dry-runreports the classified diff without changing anything.Output contract (
--json)Per-account results use one shape in both modes:
{"accountId", "action"}plusname/roleArn/externalId/intgGuidwhen a registration happened, orerrorwhen it failed.actionis one ofregister(dry-run),registered,already-onboarded,create-stack-instance-and-register(dry-run, rebuild pending),error.--allalways emits a single envelope regardless of outcome — healthy, dry-run, or repaired — so consumers parse one shape:{ "targetOUs": ["..."], "expectedAccounts": 2, "missingStackInstance": ["..."], "missingIntegration": [], "repaired": [ { "accountId": "...", "action": "registered", "intgGuid": "..." } ], "dryRun": true }(
dryRunpresent only on dry-runs;repairedempty on dry-run and healthy outcomes.)lacework cloud-account repair --help(byte-exact, from the committed help fixture CI verifies)How did you test this change?
Unit tests (
TestStackUID,TestRepairDerivationMatchesTemplate,TestRepairRegisterResult,TestDiffRepairTargets) plus flag/dispatch checks —--methoddefaults toaws-cfg-org, and unsupported values fail fast listing what's supported:Verified end-to-end against a real AWS Config organization onboarding (twice — before and after the modular refactor, identical behavior): deployed the config-org template into an AWS Organizations management account, onboarding two member accounts to a Lacework tenant, then exercised both recovery paths.
Scenario 1 — instance present, integration missing (deleted the integration, left the IAM role):
Derived role/external id matched the original onboarding exactly; integration came back
state: Ok. Re-running is idempotent (action: already-onboarded).Scenario 2 — member stack instance + role gone (deleted the StackSet instance with
--no-retain-stacks; this also deregisters the integration via the member stack's custom resource):The real run rebuilt the member StackSet instance and the account recovered healthy (stack instance CURRENT, integration
state: Ok). Note: re-creating the instance fires the template's own setup Lambda, which registers first — sorepairreportsalready-onboardedin this path (the account is still fully recovered, just registered by the Lambda rather than directly). This is documented in the command help.--allsweep modeVerified end-to-end against a fresh config-org deployment (management account, two member accounts under the targeted OUs — one targeted OU intentionally left empty to exercise the recursive enumeration — onboarding to a Lacework tenant). Unit test
TestDiffRepairTargetscovers the diff classification.Healthy baseline — enumeration, management-account exclusion, and diff report nothing to fix; the
--jsonenvelope carries the same keys as every other outcome, and the single-account mode reports the shared already-onboarded shape:Register-only path — deleted one integration (instances left intact); the diff classifies it and the sweep registers it directly, synchronously:
The integration came up
Enabled/Ok— the role ARN and external id derived from the existing stack instance matched what the member template built.Broken fleet / batch rebuild — deleted both member stack instances (
--no-retain-stacks, which also deregisters both integrations via the member stacks' custom resource), then:Both instances were created in one StackSet operation and came back CURRENT; both integrations recovered
Enabled/Ok("already onboarded" because re-creating the member stacks fires the template's setup Lambda, which registers first — the documented race). A follow-up--allrun converged to "All 2 accounts in the targeted OUs are onboarded; nothing to do" (idempotent). Note the rebuild is a long operation (~10+ minutes for two accounts — each member deploy provisions the role and blocks on the Lambda registration round-trip, serialized byMaxConcurrentCount: 1).Field note: the config-org template ships its StackSet with
AutoDeployment: Enabled, so an instance deleted while the account is still in a targeted OU is re-created by AWS reconciliation within minutes (and the Lambda re-registers it). The--allrebuild path matters for the cases auto-deployment can't see: integration deleted on the Lacework side only, the account was outside the OU when the instance was lost, or the StackSet/management stack was replaced. (For the E2E rebuild test above, auto-deployment was temporarily disabled on the test StackSet to keep it from racing the repair.)