From af756810f6a3808c6b43ff0f259628a44d6b8566 Mon Sep 17 00:00:00 2001 From: Erik Kristensen Date: Mon, 23 Dec 2024 13:29:45 -0700 Subject: [PATCH 1/3] feat(kms-alias): pass key tags through to alias with key: prefix --- resources/kms-alias.go | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/resources/kms-alias.go b/resources/kms-alias.go index f8669f18..f32efc04 100644 --- a/resources/kms-alias.go +++ b/resources/kms-alias.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "strings" + "time" "github.com/aws/aws-sdk-go/service/kms" "github.com/aws/aws-sdk-go/service/kms/kmsiface" @@ -43,9 +44,21 @@ func (l *KMSAliasLister) List(_ context.Context, o interface{}) ([]resource.Reso err := svc.ListAliasesPages(nil, func(page *kms.ListAliasesOutput, lastPage bool) bool { for _, alias := range page.Aliases { + var tags []*kms.Tag + if alias.TargetKeyId != nil { + keyTags, err := svc.ListResourceTags(&kms.ListResourceTagsInput{ + KeyId: alias.TargetKeyId, + }) + if err != nil { + opts.Logger.WithError(err).Error("failed to list tags for key") + } + tags = keyTags.Tags + } + resources = append(resources, &KMSAlias{ svc: svc, Name: alias.AliasName, + Tags: tags, }) } return true @@ -58,8 +71,11 @@ func (l *KMSAliasLister) List(_ context.Context, o interface{}) ([]resource.Reso } type KMSAlias struct { - svc kmsiface.KMSAPI - Name *string + svc kmsiface.KMSAPI + Name *string `description:"The name of the KMS alias"` + CreationDate *time.Time `description:"The creation date of the KMS alias"` + TargetKeyID *string `description:"The KMS Key ID that the alias points to"` + Tags []*kms.Tag `property:"tagPrefix=key:tag"` } func (r *KMSAlias) Filter() error { From 15c88324adbad236eadcb44a804e362e4ed3aabc Mon Sep 17 00:00:00 2001 From: Erik Kristensen Date: Mon, 23 Dec 2024 13:31:06 -0700 Subject: [PATCH 2/3] docs(kms-alias): auto-generated --- docs/resources/kms-alias.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/resources/kms-alias.md b/docs/resources/kms-alias.md index aebe4705..c59fff3e 100644 --- a/docs/resources/kms-alias.md +++ b/docs/resources/kms-alias.md @@ -14,7 +14,11 @@ KMSAlias ## Properties -- `Name`: No Description +- `CreationDate`: The creation date of the KMS alias +- `Name`: The name of the KMS alias +- `TargetKeyID`: The KMS Key ID that the alias points to +- `tag::`: This resource has tags with property `Tags`. These are key/value pairs that are + added as their own property with the prefix of `tag:` (e.g. [tag:example: "value"]) !!! note - Using Properties Properties are what [Filters](../config-filtering.md) are written against in your configuration. You use the property From 74753efe792bf303fb1322b15f1e06f4b6b72b4d Mon Sep 17 00:00:00 2001 From: Erik Kristensen Date: Mon, 23 Dec 2024 13:48:24 -0700 Subject: [PATCH 3/3] feat(route53-resource-record): pass hosted zone tags to resource record set with zone:tag prefix --- ...-records.go => route53-resource-record.go} | 44 +++++++++-------- resources/route53-resource-record_test.go | 49 +++++++++++++++++++ 2 files changed, 73 insertions(+), 20 deletions(-) rename resources/{route53-resource-records.go => route53-resource-record.go} (72%) create mode 100644 resources/route53-resource-record_test.go diff --git a/resources/route53-resource-records.go b/resources/route53-resource-record.go similarity index 72% rename from resources/route53-resource-records.go rename to resources/route53-resource-record.go index 70bab19d..610e5f89 100644 --- a/resources/route53-resource-records.go +++ b/resources/route53-resource-record.go @@ -44,7 +44,7 @@ func (l *Route53ResourceRecordSetLister) List(ctx context.Context, o interface{} for _, r := range sub { zone := r.(*Route53HostedZone) - rrs, err := ListResourceRecordsForZone(svc, zone.id, zone.name) + rrs, err := ListResourceRecordsForZone(svc, zone.id, zone.name, zone.tags) if err != nil { return nil, err } @@ -55,13 +55,13 @@ func (l *Route53ResourceRecordSetLister) List(ctx context.Context, o interface{} return resources, nil } -func ListResourceRecordsForZone(svc *route53.Route53, zoneID, zoneName *string) ([]resource.Resource, error) { +func ListResourceRecordsForZone(svc *route53.Route53, zoneID, zoneName *string, zoneTags []*route53.Tag) ([]resource.Resource, error) { + resources := make([]resource.Resource, 0) + params := &route53.ListResourceRecordSetsInput{ HostedZoneId: zoneID, } - resources := make([]resource.Resource, 0) - for { resp, err := svc.ListResourceRecordSets(params) if err != nil { @@ -70,10 +70,13 @@ func ListResourceRecordsForZone(svc *route53.Route53, zoneID, zoneName *string) for _, rrs := range resp.ResourceRecordSets { resources = append(resources, &Route53ResourceRecordSet{ - svc: svc, - hostedZoneID: zoneID, - hostedZoneName: zoneName, - data: rrs, + svc: svc, + hostedZoneID: zoneID, + HostedZoneName: zoneName, + resourceRecordSet: rrs, + Name: rrs.Name, + Type: rrs.Type, + Tags: zoneTags, }) } @@ -90,19 +93,22 @@ func ListResourceRecordsForZone(svc *route53.Route53, zoneID, zoneName *string) } type Route53ResourceRecordSet struct { - svc *route53.Route53 - hostedZoneID *string - hostedZoneName *string - data *route53.ResourceRecordSet - changeID *string + svc *route53.Route53 + resourceRecordSet *route53.ResourceRecordSet // Note: this is required for the deletion + changeID *string + hostedZoneID *string + HostedZoneName *string `description:"The name of the zone to which the record belongs"` + Name *string `description:"The name of the record"` + Type *string `description:"The type of the record"` + Tags []*route53.Tag `property:"tagPrefix=zone:tag"` } func (r *Route53ResourceRecordSet) Filter() error { - if *r.data.Type == "NS" && *r.hostedZoneName == *r.data.Name { + if *r.Type == "NS" && *r.HostedZoneName == *r.Name { return fmt.Errorf("cannot delete NS record") } - if *r.data.Type == "SOA" { + if *r.Type == "SOA" { return fmt.Errorf("cannot delete SOA record") } @@ -116,7 +122,7 @@ func (r *Route53ResourceRecordSet) Remove(_ context.Context) error { Changes: []*route53.Change{ { Action: aws.String("DELETE"), - ResourceRecordSet: r.data, + ResourceRecordSet: r.resourceRecordSet, }, }, }, @@ -133,11 +139,9 @@ func (r *Route53ResourceRecordSet) Remove(_ context.Context) error { } func (r *Route53ResourceRecordSet) Properties() types.Properties { - return types.NewProperties(). - Set("Name", r.data.Name). - Set("Type", r.data.Type) + return types.NewPropertiesFromStruct(r) } func (r *Route53ResourceRecordSet) String() string { - return ptr.ToString(r.data.Name) + return ptr.ToString(r.Name) } diff --git a/resources/route53-resource-record_test.go b/resources/route53-resource-record_test.go new file mode 100644 index 00000000..e8fc6d7e --- /dev/null +++ b/resources/route53-resource-record_test.go @@ -0,0 +1,49 @@ +package resources + +import ( + "testing" + + "github.com/gotidy/ptr" + "github.com/stretchr/testify/assert" + + "github.com/aws/aws-sdk-go/service/route53" +) + +func TestRoute53ResourceRecordSet_Properties(t *testing.T) { + cases := []struct { + name string + recordType string + }{ + { + name: "example.com", + recordType: "NS", + }, + { + name: "example.com", + recordType: "SOA", + }, + { + name: "subdomain.example.com", + recordType: "A", + }, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + r := &Route53ResourceRecordSet{ + resourceRecordSet: &route53.ResourceRecordSet{ + Name: ptr.String(tc.name), + Type: ptr.String(tc.recordType), + }, + Name: ptr.String(tc.name), + Type: ptr.String(tc.recordType), + } + + got := r.Properties() + assert.Equal(t, tc.name, got.Get("Name")) + assert.Equal(t, tc.recordType, got.Get("Type")) + + assert.Equal(t, tc.name, r.String()) + }) + } +}