Middleware to explode inline policy

main
William Beuil 2021-01-27 23:47:39 +01:00
parent c77d6018fe
commit 54a7bb211d
No known key found for this signature in database
GPG Key ID: BED2072C5C2BF537
3 changed files with 193 additions and 0 deletions

View File

@ -46,6 +46,7 @@ func (d DriftCTL) Run() *analyser.Analysis {
middlewares.NewAwsDefaultRouteTable(),
middlewares.NewAwsDefaultRoute(),
middlewares.NewAwsNatGatewayEipAssoc(),
middlewares.NewAwsBucketPolicyExpander(),
)
logrus.Debug("Ready to run middlewares")

View File

@ -0,0 +1,77 @@
package middlewares
import (
"github.com/cloudskiff/driftctl/pkg/resource"
"github.com/cloudskiff/driftctl/pkg/resource/aws"
"github.com/sirupsen/logrus"
)
// Explodes policy found in aws_s3_bucket.policy from state resources to dedicated resources
type AwsBucketPolicyExpander struct{}
func NewAwsBucketPolicyExpander() AwsBucketPolicyExpander {
return AwsBucketPolicyExpander{}
}
func (m AwsBucketPolicyExpander) Execute(_, resourcesFromState *[]resource.Resource) error {
newList := make([]resource.Resource, 0)
for _, res := range *resourcesFromState {
// Ignore all resources other than s3_bucket
if res.TerraformType() != aws.AwsS3BucketResourceType {
newList = append(newList, res)
continue
}
bucket, _ := res.(*aws.AwsS3Bucket)
newList = append(newList, res)
if hasPolicyAttached(bucket, resourcesFromState) {
bucket.Policy = nil
continue
}
err := m.handlePolicy(bucket, &newList)
if err != nil {
return err
}
}
*resourcesFromState = newList
return nil
}
func (m *AwsBucketPolicyExpander) handlePolicy(bucket *aws.AwsS3Bucket, results *[]resource.Resource) error {
if bucket.Policy == nil || *bucket.Policy == "" {
return nil
}
newPolicy := &aws.AwsS3BucketPolicy{
Id: bucket.Id,
Bucket: bucket.Bucket,
Policy: bucket.Policy,
}
normalizedRes, err := newPolicy.NormalizeForState()
if err != nil {
return err
}
*results = append(*results, normalizedRes)
logrus.WithFields(logrus.Fields{
"id": newPolicy.TerraformId(),
}).Debug("Created new policy from bucket")
bucket.Policy = nil
return nil
}
// Return true if the bucket has a aws_bucket_policy resource attached to itself.
// It is mandatory since it's possible to have a aws_bucket with an inline policy
// AND a aws_bucket_policy resource at the same time. At the end, on the AWS console,
// the aws_bucket_policy will be used.
func hasPolicyAttached(bucket *aws.AwsS3Bucket, resourcesFromState *[]resource.Resource) bool {
for _, res := range *resourcesFromState {
if res.TerraformType() == aws.AwsS3BucketPolicyResourceType &&
res.TerraformId() == bucket.Id {
return true
}
}
return false
}

View File

@ -0,0 +1,115 @@
package middlewares
import (
"strings"
"testing"
awssdk "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awsutil"
"github.com/cloudskiff/driftctl/pkg/resource"
"github.com/cloudskiff/driftctl/pkg/resource/aws"
"github.com/r3labs/diff/v2"
)
func TestAwsBucketPolicyExpander_Execute(t *testing.T) {
tests := []struct {
name string
resourcesFromState []resource.Resource
expected []resource.Resource
}{
{
"Inline policy, no aws_s3_bucket_policy attached",
[]resource.Resource{
&aws.AwsS3Bucket{
Id: "foo",
Bucket: awssdk.String("foo"),
Policy: awssdk.String("{\"Id\":\"MYINLINEBUCKETPOLICY\",\"Statement\":[{\"Action\":\"s3:*\",\"Condition\":{\"IpAddress\":{\"aws:SourceIp\":\"8.8.8.8/32\"}},\"Effect\":\"Deny\",\"Principal\":\"*\",\"Resource\":\"arn:aws:s3:::bucket-test-policy-like-sqs/*\",\"Sid\":\"IPAllow\"}],\"Version\":\"2012-10-17\"}"),
},
},
[]resource.Resource{
&aws.AwsS3Bucket{
Id: "foo",
Bucket: awssdk.String("foo"),
Policy: nil,
},
&aws.AwsS3BucketPolicy{
Id: "foo",
Bucket: awssdk.String("foo"),
Policy: awssdk.String("{\"Id\":\"MYINLINEBUCKETPOLICY\",\"Statement\":[{\"Action\":\"s3:*\",\"Condition\":{\"IpAddress\":{\"aws:SourceIp\":\"8.8.8.8/32\"}},\"Effect\":\"Deny\",\"Principal\":\"*\",\"Resource\":\"arn:aws:s3:::bucket-test-policy-like-sqs/*\",\"Sid\":\"IPAllow\"}],\"Version\":\"2012-10-17\"}"),
},
},
},
{
"No inline policy, aws_s3_bucket_policy attached",
[]resource.Resource{
&aws.AwsS3Bucket{
Id: "foo",
Bucket: awssdk.String("foo"),
Policy: nil,
},
&aws.AwsS3BucketPolicy{
Id: "foo",
Bucket: awssdk.String("foo"),
Policy: awssdk.String("{\"Id\":\"MYBUCKETPOLICY\",\"Statement\":[{\"Action\":\"s3:*\",\"Condition\":{\"IpAddress\":{\"aws:SourceIp\":\"8.8.8.8/32\"}},\"Effect\":\"Deny\",\"Principal\":\"*\",\"Resource\":\"arn:aws:s3:::bucket-test-policy-like-sqs/*\",\"Sid\":\"IPAllow\"}],\"Version\":\"2012-10-17\"}"),
},
},
[]resource.Resource{
&aws.AwsS3Bucket{
Id: "foo",
Bucket: awssdk.String("foo"),
Policy: nil,
},
&aws.AwsS3BucketPolicy{
Id: "foo",
Bucket: awssdk.String("foo"),
Policy: awssdk.String("{\"Id\":\"MYBUCKETPOLICY\",\"Statement\":[{\"Action\":\"s3:*\",\"Condition\":{\"IpAddress\":{\"aws:SourceIp\":\"8.8.8.8/32\"}},\"Effect\":\"Deny\",\"Principal\":\"*\",\"Resource\":\"arn:aws:s3:::bucket-test-policy-like-sqs/*\",\"Sid\":\"IPAllow\"}],\"Version\":\"2012-10-17\"}"),
},
},
},
{
"Inline policy and aws_s3_bucket_policy",
[]resource.Resource{
&aws.AwsS3Bucket{
Id: "foo",
Bucket: awssdk.String("foo"),
Policy: awssdk.String("{\"Id\":\"MYINLINEBUCKETPOLICY\",\"Statement\":[{\"Action\":\"s3:*\",\"Condition\":{\"IpAddress\":{\"aws:SourceIp\":\"8.8.8.8/32\"}},\"Effect\":\"Deny\",\"Principal\":\"*\",\"Resource\":\"arn:aws:s3:::bucket-test-policy-like-sqs/*\",\"Sid\":\"IPAllow\"}],\"Version\":\"2012-10-17\"}"),
},
&aws.AwsS3BucketPolicy{
Id: "foo",
Bucket: awssdk.String("foo"),
Policy: awssdk.String("{\"Id\":\"MYBUCKETPOLICY\",\"Statement\":[{\"Action\":\"s3:*\",\"Condition\":{\"IpAddress\":{\"aws:SourceIp\":\"8.8.8.8/32\"}},\"Effect\":\"Deny\",\"Principal\":\"*\",\"Resource\":\"arn:aws:s3:::bucket-test-policy-like-sqs/*\",\"Sid\":\"IPAllow\"}],\"Version\":\"2012-10-17\"}"),
},
},
[]resource.Resource{
&aws.AwsS3Bucket{
Id: "foo",
Bucket: awssdk.String("foo"),
Policy: nil,
},
&aws.AwsS3BucketPolicy{
Id: "foo",
Bucket: awssdk.String("foo"),
Policy: awssdk.String("{\"Id\":\"MYBUCKETPOLICY\",\"Statement\":[{\"Action\":\"s3:*\",\"Condition\":{\"IpAddress\":{\"aws:SourceIp\":\"8.8.8.8/32\"}},\"Effect\":\"Deny\",\"Principal\":\"*\",\"Resource\":\"arn:aws:s3:::bucket-test-policy-like-sqs/*\",\"Sid\":\"IPAllow\"}],\"Version\":\"2012-10-17\"}"),
},
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
m := NewAwsBucketPolicyExpander()
err := m.Execute(&[]resource.Resource{}, &tt.resourcesFromState)
if err != nil {
t.Fatal(err)
}
changelog, err := diff.Diff(tt.expected, tt.resourcesFromState)
if err != nil {
t.Fatal(err)
}
if len(changelog) > 0 {
for _, change := range changelog {
t.Errorf("%s got = %v, want %v", strings.Join(change.Path, "."), awsutil.Prettify(change.From), awsutil.Prettify(change.To))
}
}
})
}
}