Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ When AWS omits `KmsKeyId` for the AWS-managed default key, `config.kms_key_id` i

CONFIG evidence supports rotation, vendor credential, confidentiality, and privacy policy bundles through `DescribeSecret`, `GetResourcePolicy`, `ListSecretVersionIds`, and tags from `DescribeSecret`. Fields include rotation state, rotation rules, KMS key ID string, owning service, replication status, version stages, resource policy principals, and hashed name/description.

For secrets marked for deletion, the collector records `DescribeSecret` metadata, `deleted_date`, and any matched CloudTrail deletion context, but skips per-secret subresource calls such as `GetResourcePolicy` and `ListSecretVersionIds` because AWS rejects those operations for pending-deletion secrets.

DYNAMIC evidence uses a 90-day default CloudTrail lookback. Secrets Manager events are filtered to `RotateSecret`, `PutSecretValue`, `UpdateSecret`, `UpdateSecretVersionStage`, `DeleteSecret`, `RestoreSecret`, `PutResourcePolicy`, `DeleteResourcePolicy`, `TagResource`, `UntagResource`, `CreateSecret`, and `GetSecretValue`. IAM credential-removal events are filtered to `DeleteUser`, `DeleteAccessKey`, `DetachUserPolicy`, `RemoveUserFromGroup`, `DeleteRole`, `DetachRolePolicy`, and `RemoveRoleFromInstanceProfile`.

## CloudTrail Attribution
Expand Down
9 changes: 8 additions & 1 deletion collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -348,9 +348,16 @@ func (c *Collector) collectSecret(ctx context.Context, client SecretsManagerAPI,
}
d.config = describeConfig(arn, describe)

policyOut, policyErr := client.GetResourcePolicy(ctx, &sm.GetResourcePolicyInput{SecretId: aws.String(arn)})
policyPresent := false
policyInfo := map[string]interface{}{"hash": "", "document": nil, "principals": []map[string]interface{}{}}
d.config["resource_policy"] = policyInfo
d.config["resource_policy_present"] = policyPresent
d.config["versions"] = []map[string]interface{}{}
d.config["deprecated_version_count"] = 0
if describe.DeletedDate != nil {
return d, nil
}
policyOut, policyErr := client.GetResourcePolicy(ctx, &sm.GetResourcePolicyInput{SecretId: aws.String(arn)})
if policyErr != nil {
var notFound *smtypes.ResourceNotFoundException
if !errors.As(policyErr, &notFound) {
Expand Down
9 changes: 9 additions & 0 deletions collector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,15 @@ func TestCollectorIncludesPlannedDeletionAndRecoveryWindow(t *testing.T) {
if got := rec.Input.Config["recovery_window_days"]; got != 14 {
t.Fatalf("recovery_window_days = %v", got)
}
if smFake.policyCalls[arn] != 0 || smFake.versionCalls[arn] != 0 {
t.Fatalf("deleted secret should not fetch policy or versions: policy=%d versions=%d", smFake.policyCalls[arn], smFake.versionCalls[arn])
}
if rec.Input.Config["resource_policy_present"] != false {
t.Fatalf("resource_policy_present = %v", rec.Input.Config["resource_policy_present"])
}
if versions, ok := rec.Input.Config["versions"].([]map[string]interface{}); !ok || len(versions) != 0 {
t.Fatalf("versions = %#v", rec.Input.Config["versions"])
}
}

func TestCollectorUsesGlobalCloudTrailForIAMEvents(t *testing.T) {
Expand Down
6 changes: 5 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/cloudtrail v1.51.0
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.39.12
github.com/aws/aws-sdk-go-v2/service/sts v1.41.9
github.com/compliance-framework/agent v0.7.0
github.com/compliance-framework/agent v0.7.1
github.com/hashicorp/go-hclog v1.6.3
github.com/hashicorp/go-plugin v1.7.0
)
Expand All @@ -28,15 +28,18 @@ require (
github.com/aws/smithy-go v1.25.1 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/compliance-framework/api v0.16.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.1 // indirect
github.com/defenseunicorns/go-oscal v0.7.0 // indirect
github.com/fatih/color v1.18.0 // indirect
github.com/go-viper/mapstructure/v2 v2.5.0 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/goccy/go-json v0.10.5 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/hashicorp/yamux v0.1.2 // indirect
github.com/lestrrat-go/blackmagic v1.0.4 // indirect
github.com/lestrrat-go/dsig v1.0.0 // indirect
github.com/lestrrat-go/dsig-secp256k1 v1.0.0 // indirect
github.com/lestrrat-go/httpcc v1.0.1 // indirect
github.com/lestrrat-go/httprc/v3 v3.0.4 // indirect
github.com/lestrrat-go/jwx/v3 v3.0.13 // indirect
Expand All @@ -46,6 +49,7 @@ require (
github.com/oklog/run v1.2.0 // indirect
github.com/open-policy-agent/opa v1.14.1 // indirect
github.com/rcrowley/go-metrics v0.0.0-20250401214520-65e299d6c5c9 // indirect
github.com/segmentio/asm v1.2.1 // indirect
github.com/sirupsen/logrus v1.9.4 // indirect
github.com/tchap/go-patricia/v2 v2.3.3 // indirect
github.com/valyala/fastjson v1.6.10 // indirect
Expand Down
Loading
Loading