Skip to content

Commit

Permalink
Add support for tagging WAFV2 WebACLs (#224)
Browse files Browse the repository at this point in the history
  • Loading branch information
jaemokhong authored Nov 4, 2024
1 parent 5d8424d commit 161b3f8
Show file tree
Hide file tree
Showing 4 changed files with 436 additions and 0 deletions.
34 changes: 34 additions & 0 deletions README.MD
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ Tags are critical to managing AWS resources at scale. Awstaghelper provides a co
* [ECR](#ecr)
* [AutoScaling groups](#autoscaling-groups)
* [EBS Volumes](#ebs-volumes)
* [WAFV2 CloudFront WebACL](#wafv2-cloudfront-webacl)
* [WAFV2 Regional WebACL](#wafv2-regional-webacl)
* [Global parameters](#global-parameters)
* [Contributing](#contributing)
* [License](#license)
Expand Down Expand Up @@ -340,6 +342,38 @@ Read csv and tag EBS volumes - `awstaghelper ebs tag-ebs`
Example:
`awstaghelper ebs tag-ebs --filename ebsTags.csv --profile main`

### WAFV2 CloudFront WebACL

#### Get wafv2 cloudfront webacl tags

Get list of wafv2 cloudfront webacl with required tags - `awstaghelper wafv2 get-cfwebacl-tags`

Example:
`awstaghelper wafv2 get-cfwebacl-tags --filename cfwebaclTags.csv --tags Name,Owner --profile main`

#### Tag wafv2 cloudfront webacl

Read csv and tag wafv2 cloudfront webacl - `awstaghelper wafv2 tag-cfwebacl`

Example:
`awstaghelper wafv2 tag-cfwebacl --filename cfwebaclTags.csv --profile main`

### WAFV2 Regional WebACL

#### Get wafv2 regional webacl tags

Get list of wafv2 regional webacl with required tags - `awstaghelper wafv2 get-webacl-tags`

Example:
`awstaghelper wafv2 get-webacl-tags --filename webaclTags.csv --tags Name,Owner --profile main`

#### Tag wafv2 regional webacl

Read csv and tag wafv2 regional webacl - `awstaghelper wafv2 tag-webacl`

Example:
`awstaghelper wafv2 tag-webacl --filename webaclTags.csv --profile main`

## Global parameters

`filename` - path where to write or read data. Supported by every option. Default `awsTags.csv`
Expand Down
107 changes: 107 additions & 0 deletions cmd/wafv2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/*
Copyright © 2024 Jaemok Hong [email protected]
Copyright © 2020 Maksym Postument [email protected]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Package cmd is the package for the CLI of awstaghelper
package cmd

import (
"github.com/mpostument/awstaghelper/pkg"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/wafv2"
"github.com/spf13/cobra"
)

// wafv2Cmd represents the wafv2 command
var wafv2Cmd = &cobra.Command{
Use: "wafv2",
Short: "Root command for interaction with AWS wafv2 services(cloudfront, regional)",
Long: `Root command for interaction with AWS wafv2 services(cloudfront, regional),`,
}

var getWebACLCmd = &cobra.Command{
Use: "get-webacl-tags",
Short: "Write regional webacl arn and required tags to csv",
Long: `Write to csv data with regional webacl arn and required tags to csv.
This csv can be used with tag-webacl command to tag aws environment.
Specify list of tags which should be read using tags flag: --tags Name,Env,Project.
Csv filename can be specified with flag filename.`,
Run: func(cmd *cobra.Command, args []string) {
tags, _ := cmd.Flags().GetString("tags")
filename, _ := cmd.Flags().GetString("filename")
profile, _ := cmd.Flags().GetString("profile")
region, _ := cmd.Flags().GetString("region")
sess := pkg.GetSession(region, profile)
client := wafv2.New(sess)
pkg.WriteCsv(pkg.ParseWebACLTags(tags, "REGIONAL", client), filename)
},
}

var tagWebACLCmd = &cobra.Command{
Use: "tag-webacl",
Short: "Read csv and tag regional webacl with csv data",
Long: `Read csv generated with get-webacl-tags command and tag regional webacl with tags from csv.`,
Run: func(cmd *cobra.Command, args []string) {
filename, _ := cmd.Flags().GetString("filename")
profile, _ := cmd.Flags().GetString("profile")
region, _ := cmd.Flags().GetString("region")
sess := pkg.GetSession(region, profile)
client := wafv2.New(sess, aws.NewConfig().WithRegion(region))
csvData := pkg.ReadCsv(filename)
pkg.TagWebACL(csvData, client)
},
}

var getCFWebACLCmd = &cobra.Command{
Use: "get-cfwebacl-tags",
Short: "Write cloudfront webacl arn and required tags to csv",
Long: `Write to csv data with cloudfront webacl arn and required tags to csv.
This csv can be used with tag-cfwebacl command to tag aws environment.
Specify list of tags which should be read using tags flag: --tags Name,Env,Project.
Csv filename can be specified with flag filename.`,
Run: func(cmd *cobra.Command, args []string) {
tags, _ := cmd.Flags().GetString("tags")
filename, _ := cmd.Flags().GetString("filename")
profile, _ := cmd.Flags().GetString("profile")
sess := pkg.GetSession("us-east-1", profile)
client := wafv2.New(sess)
pkg.WriteCsv(pkg.ParseWebACLTags(tags, "CLOUDFRONT", client), filename)
},
}

var tagCFWebACLCmd = &cobra.Command{
Use: "tag-cfwebacl",
Short: "Read csv and tag cloudfront webacl with csv data",
Long: `Read csv generated with get-cfwebacl-tags command and tag cloudfront webacl with tags from csv.`,
Run: func(cmd *cobra.Command, args []string) {
filename, _ := cmd.Flags().GetString("filename")
profile, _ := cmd.Flags().GetString("profile")
region, _ := cmd.Flags().GetString("region")
sess := pkg.GetSession(region, profile)
client := wafv2.New(sess, aws.NewConfig().WithRegion("us-east-1"))
csvData := pkg.ReadCsv(filename)
pkg.TagWebACL(csvData, client)
},
}

func init() {
rootCmd.AddCommand(wafv2Cmd)
wafv2Cmd.AddCommand(getWebACLCmd)
wafv2Cmd.AddCommand(tagWebACLCmd)
wafv2Cmd.AddCommand(getCFWebACLCmd)
wafv2Cmd.AddCommand(tagCFWebACLCmd)
}
110 changes: 110 additions & 0 deletions pkg/wafv2.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
Copyright © 2024 Jaemok Hong [email protected]
Copyright © 2020 Maksym Postument [email protected]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package pkg

import (
"fmt"
"log"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/wafv2"
"github.com/aws/aws-sdk-go/service/wafv2/wafv2iface"
)

// getWebACL return all webacls(regional, cloudfront) from specified region
func getWebACL(scope string, client wafv2iface.WAFV2API) *wafv2.ListWebACLsOutput {
input := &wafv2.ListWebACLsInput{
Scope: aws.String(scope),
}

var allWebACLs []*wafv2.WebACLSummary
var nextMarker *string

for {
result, err := client.ListWebACLs(input)
if err != nil {
log.Fatal("Not able to get webacls ", err)
return nil
}
allWebACLs = append(allWebACLs, result.WebACLs...)
nextMarker = result.NextMarker
if nextMarker == nil || *nextMarker == "" {
break
}
input.NextMarker = nextMarker
}
return &wafv2.ListWebACLsOutput{WebACLs: allWebACLs}
}

// ParseWebACLTags parse output from getWebACL and return webacl arn and specified tags.
func ParseWebACLTags(tagsToRead string, scope string, client wafv2iface.WAFV2API) [][]string {
wafv2Output := getWebACL(scope, client)
rows := addHeadersToCsv(tagsToRead, "Arn")

for _, webACL := range wafv2Output.WebACLs {
var nextMarker *string

for {
input := &wafv2.ListTagsForResourceInput{
ResourceARN: webACL.ARN,
Limit: aws.Int64(5),
}
if nextMarker != nil {
input.NextMarker = nextMarker
}
webACLTags, err := client.ListTagsForResource(input)
if err != nil {
fmt.Println("Not able to get webACL tags ", err)
break
}
tags := map[string]string{}
for _, tag := range webACLTags.TagInfoForResource.TagList {
tags[*tag.Key] = *tag.Value
}
rows = addTagsToCsv(tagsToRead, tags, rows, *webACL.ARN)
nextMarker = webACLTags.NextMarker
if nextMarker == nil || *nextMarker == "" {
break
}
}
}
return rows
}

// TagWebACL tag webacl. Take as input data from csv file. Where first column Arn
func TagWebACL(csvData [][]string, client wafv2iface.WAFV2API) {
for r := 1; r < len(csvData); r++ {
var tags []*wafv2.Tag
for c := 1; c < len(csvData[0]); c++ {
tags = append(tags, &wafv2.Tag{
Key: &csvData[0][c],
Value: &csvData[r][c],
})
}

input := &wafv2.TagResourceInput{
ResourceARN: aws.String(csvData[r][0]),
Tags: tags,
}

_, err := client.TagResource(input)
if awsErrorHandle(err) {
return
}
}
}
Loading

0 comments on commit 161b3f8

Please sign in to comment.