Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: pass tags to related resources for kms and route53 #473

Merged
merged 3 commits into from
Dec 24, 2024
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
6 changes: 5 additions & 1 deletion docs/resources/kms-alias.md
Original file line number Diff line number Diff line change
Expand Up @@ -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:<key>:`: 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
Expand Down
20 changes: 18 additions & 2 deletions resources/kms-alias.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand All @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand All @@ -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 {
Expand All @@ -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,
})
}

Expand All @@ -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")
}

Expand All @@ -116,7 +122,7 @@ func (r *Route53ResourceRecordSet) Remove(_ context.Context) error {
Changes: []*route53.Change{
{
Action: aws.String("DELETE"),
ResourceRecordSet: r.data,
ResourceRecordSet: r.resourceRecordSet,
},
},
},
Expand All @@ -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)
}
49 changes: 49 additions & 0 deletions resources/route53-resource-record_test.go
Original file line number Diff line number Diff line change
@@ -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())
})
}
}
Loading