fix(CAD-1836): target the caller's tenant when generating AWS org Config - #1860
Merged
Merged
Conversation
A user running `generate cloud-account aws` with an API key belonging to sub-account TECH_ALLY, leaving the sub-account prompt blank, got their CloudTrail integration in TECH_ALLY but their AWS Config integrations in the parent account customerdemo. The two take different routes. CloudTrail is created by lacework_integration_aws_ct through the Terraform Lacework provider, which picks up the sub-account from ~/.lacework.toml or LW_*. AWS-organization Config is not: createConfig diverts it to lacework/org-configuration/aws, a CloudFormation StackSet whose Lambda calls the Lacework API itself with the target tenant passed in as module attributes. It never sees the ambient profile or environment, so the only thing pointing it at a tenant is lacework_subaccount. That value came from a prompt labelled "Lacework subaccount (optional):" with no Required flag and a default of its own zero value -- it was never seeded from the account the CLI had already authenticated as. Pressing Enter, the frictionless path, meant "parent tenant", and the Lambda then registered one Config integration per AWS member account there. Default both the account and sub-account from the CLI's own state, leaving any explicitly supplied value alone. Seeding happens before the prompts so the values appear as their defaults and can still be cleared to deliberately target the parent, and outside the interactive branch because promptAwsGenerate only runs interactively -- otherwise --noninteractive would stay broken. Note the server is not at fault: with no Account-Name header the API leaves custGuid as the key's own account, the integration write uses it verbatim, and AwsCfg is not an org subtype so the one org-access path would 400 rather than write to the parent. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
PengyuanZhao
enabled auto-merge (squash)
September 3, 2026 20:38
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/CAD-1836
Note the ticket title — "AWS Config integration POST endpoint not respect subaccount API key" — is a misdiagnosis. The API is correct; see Summary. The ticket covers two independent client-side defects; the other is fixed in lacework/services#34638.
Summary
A user ran
lacework generate cloud-account awswith an API key belonging to sub-accountTECH_ALLY, leaving the sub-account prompt blank. Their CloudTrail integration landed inTECH_ALLY(correct), but their AWS Config integrations landed in the parent accountcustomerdemo(wrong), one per AWS member account.The two take different routes. CloudTrail is created by
lacework_integration_aws_ctthrough the Terraform Lacework provider, which picks up the sub-account from~/.lacework.tomlorLW_*. AWS-organization Config is not —createConfigdiverts it tolacework/org-configuration/aws, a CloudFormation StackSet whose Lambda calls the Lacework API itself with the target tenant passed in as module attributes, then early-returns without emitting alacework_integration_aws_cfgresource at all:It never sees the ambient profile or environment, so
lacework_subaccountis the only thing pointing it at a tenant. That value came from a prompt labelled"Lacework subaccount (optional):", with noRequiredflag and a default of its own zero value — never seeded from the account the CLI had already authenticated as (greppinggenerate_aws.goforcli.Subaccount/cli.Accountreturned nothing). Pressing Enter, the frictionless path, meant "parent tenant".The fix defaults both the account and sub-account from the CLI's own state, leaving any explicitly supplied value alone. Placement matters in two ways:
cli.InteractiveMode()branch, becausepromptAwsGenerateonly runs interactively — seeding inside it would leave--noninteractivebroken.The server is not at fault. With no
Account-Nameheader,TokenAuthenticatorleavescustGuidas the key's own account; the integration write usessessionProps.getCustGuid()verbatim with no primary-account substitution on create (that exists only on read); andAwsCfgis not inCloudAccounts.orgSubType, so the one org-access swap path returns 400 rather than writing to the parent.How did you test this change?
go build ./...clean;go test ./cli/cmd/(full package) passes.RunEclosure on review, which isn't unit-testable without driving the whole command. Suggested follow-up: assert on generated HCL inlwgenerate/aws— that package already compares emitted Terraform, so a case there could assertlacework_subaccountappears in theaws_org_configurationblock.go vetreports pre-existing non-constant-format-string findings across ~20 unrelated files (includinggenerate_aws.go:276, which this PR does not touch — zeroOutputHumanlines in the diff). Tests were run with-vet=offfor that reason.Manual verification for QA: with a sub-account API key configured and the sub-account prompt left at its default, run
generate cloud-account awswith--aws_organizationand Config enabled; confirm the generatedmain.tfcarrieslacework_subaccount = "<sub-account>"in theaws_org_configurationmodule and that the resulting Config integrations land in that sub-account.Existing remediation:
lacework cloud-account repair(v2.15.0) covers org-onboarded AwsCfg accounts already in the wrong tenant, but it reads only theLaceworkAccountstack parameter and neverLaceworkSubaccount— worth a follow-up so affected customers can fully self-remediate.🤖 Generated with Claude Code