From 9a873cfb718584a504cbfd57ac8509496b9d353a Mon Sep 17 00:00:00 2001 From: Jeroen Soeters Date: Sat, 22 Aug 2026 22:00:40 -0700 Subject: [PATCH 1/2] fix(discovery): drop SecretTargetAttachment discovery and the $LATEST version pseudo-entry CloudControl's SecretTargetAttachment list returns every secret in the account rather than actual attachments: the type is an action performed on a secret rather than a cloud object with its own inventory, so there is nothing to enumerate and reads of the listed ids fail. In any account with secrets that failed a discovery sync command on every cycle. The type goes back to discoverable = false, with the reason recorded inline; it remains fully declarable and manageable. CloudControl's Lambda version list includes the $LATEST pseudo-version, which is not a published version and whose read always fails. This was masked while the list post-filter dropped ARN-form results and surfaced once that was fixed. The generic list path now skips it, the same way AWS-managed policies and reserved aliases are skipped. --- CHANGELOG.md | 10 ++++++++++ aws.go | 5 +++++ aws_test.go | 6 ++++++ schema/pkl/secretsmanager/secrettargetattachment.pkl | 1 + 4 files changed, 22 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49cc335..bd9ea98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -398,6 +398,16 @@ Requires formae >= 0.89.0. ### Fixed +- `AWS::SecretsManager::SecretTargetAttachment` is no longer discoverable. + CloudControl's list handler returns every secret in the account rather than + actual attachments, so in any account with secrets, discovery produced a + stream of failing reads on ids that are not attachments. The type remains + fully declarable and manageable. +- `AWS::Lambda::Version` discovery no longer surfaces the `$LATEST` + pseudo-version. CloudControl's version list includes it, but it is not a + published version and reading it always fails, which failed a sync cycle + for every function once version listing started working. + - `AWS::Lambda::Permission` discovery now finds permissions attached to a published version or an alias, not only those on the bare function. Lambda keeps a separate resource policy per qualifier and the CloudControl list diff --git a/aws.go b/aws.go index 2fc0003..615ead6 100644 --- a/aws.go +++ b/aws.go @@ -139,6 +139,11 @@ var discoveryListExclusions = map[string]func(nativeID string) bool{ "AWS::KMS::Alias": func(id string) bool { return strings.HasPrefix(id, "alias/aws/") }, + // CloudControl's version list includes the $LATEST pseudo-version, which + // is not a published version and whose read always fails. + "AWS::Lambda::Version": func(id string) bool { + return strings.HasSuffix(id, ":$LATEST") + }, } // LabelConfig returns the label extraction configuration for discovered AWS resources. diff --git a/aws_test.go b/aws_test.go index 526ca05..913eb79 100644 --- a/aws_test.go +++ b/aws_test.go @@ -166,6 +166,12 @@ func TestDiscoveryListExclusions(t *testing.T) { assert.False(t, excluded("alias/awsome-key")) }) + t.Run("excludes the $LATEST pseudo-version and keeps published versions", func(t *testing.T) { + excluded := discoveryListExclusions["AWS::Lambda::Version"] + assert.True(t, excluded("arn:aws:lambda:us-east-1:111122223333:function:my-function:$LATEST")) + assert.False(t, excluded("arn:aws:lambda:us-east-1:111122223333:function:my-function:3")) + }) + t.Run("has no exclusion for other types", func(t *testing.T) { assert.Nil(t, discoveryListExclusions["AWS::S3::Bucket"]) }) diff --git a/schema/pkl/secretsmanager/secrettargetattachment.pkl b/schema/pkl/secretsmanager/secrettargetattachment.pkl index 81e5ee5..eb59ea7 100644 --- a/schema/pkl/secretsmanager/secrettargetattachment.pkl +++ b/schema/pkl/secretsmanager/secrettargetattachment.pkl @@ -14,6 +14,7 @@ const type = "AWS::SecretsManager::SecretTargetAttachment" @aws.ResourceHint { type = module.type identifier = "Id" + discoverable = false // CloudControl's list returns every secret in the account rather than actual attachments, and reads of those ids fail extractable = true } open class SecretTargetAttachment extends formae.Resource { From 95e0399452c41e7b94844428630eac959240369e Mon Sep 17 00:00:00 2001 From: Jeroen Soeters Date: Sat, 22 Aug 2026 22:23:01 -0700 Subject: [PATCH 2/2] docs(changelog): keep the unreleased discovery story coherent Neither SecretTargetAttachment discovery nor working Lambda version listing ever shipped in a release, so the attachment type simply leaves the unreleased enablement list and the version pseudo-entry needs no fix note. What was released broken is version discovery silently finding nothing, which gets the honest entry. --- CHANGELOG.md | 23 +++++++++-------------- 1 file changed, 9 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bd9ea98..a8eb44f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -134,14 +134,14 @@ Requires formae >= 0.89.0. operation, so it retries them instead of failing the resource. Faults that will not clear — access denied, an unusable secret, a rejected statement — stay terminal, keep their diagnosis, and never start a wait. -- Discovery for eight more resource types whose CloudControl list support was +- Discovery for seven more resource types whose CloudControl list support was verified against the type registry and a live account: `AWS::IAM::User`, `AWS::IAM::VirtualMFADevice`, `AWS::ECS::CapacityProvider`, `AWS::RDS::CustomDBEngineVersion`, `AWS::S3::AccessGrantsInstance`, - `AWS::SecretsManager::SecretTargetAttachment`, `AWS::Lambda::Permission` - (scoped per function), and `AWS::ElasticLoadBalancingV2::ListenerRule` - (scoped per listener). Live resources of these types now appear in - inventory and can be brought under management. + `AWS::Lambda::Permission` (scoped per function), and + `AWS::ElasticLoadBalancingV2::ListenerRule` (scoped per listener). Live + resources of these types now appear in inventory and can be brought under + management. - Discovery for `AWS::ApiGateway::Resource`, `AWS::ApiGateway::Method`, and `AWS::CloudFront::Distribution`, and extract for `AWS::CloudFront::Distribution`. Live API Gateway resources and methods and @@ -398,15 +398,10 @@ Requires formae >= 0.89.0. ### Fixed -- `AWS::SecretsManager::SecretTargetAttachment` is no longer discoverable. - CloudControl's list handler returns every secret in the account rather than - actual attachments, so in any account with secrets, discovery produced a - stream of failing reads on ids that are not attachments. The type remains - fully declarable and manageable. -- `AWS::Lambda::Version` discovery no longer surfaces the `$LATEST` - pseudo-version. CloudControl's version list includes it, but it is not a - published version and reading it always fails, which failed a sync cycle - for every function once version listing started working. +- `AWS::Lambda::Version` discovery now surfaces published versions. The list + post-filter compared the parent function's name against the ARN form + CloudControl echoes back, dropping every listed version, so version + discovery silently found nothing. - `AWS::Lambda::Permission` discovery now finds permissions attached to a published version or an alias, not only those on the bare function. Lambda