add support for sns_topic_policy
modify sns_topic support so that we create sns_topic_policy for inline policymain
parent
e4c03fe17c
commit
7041cf12e5
|
@ -251,7 +251,7 @@ As AWS documentation recommends, the below policy is granting only the permissio
|
|||
|
||||
## SNS
|
||||
- [x] aws_sns_topic
|
||||
- [ ] aws_sns_topic_policy
|
||||
- [x] aws_sns_topic_policy
|
||||
- [ ] aws_sns_topic_subscription
|
||||
- [ ] aws_sns_platform_application
|
||||
- [ ] aws_sns_sms_preferences
|
||||
|
|
|
@ -50,6 +50,7 @@ func (d DriftCTL) Run() *analyser.Analysis {
|
|||
middlewares.NewAwsBucketPolicyExpander(),
|
||||
middlewares.NewAwsSqsQueuePolicyExpander(),
|
||||
middlewares.NewAwsDefaultSqsQueuePolicy(),
|
||||
middlewares.NewAwsSNSTopicPolicyExpander(),
|
||||
)
|
||||
|
||||
logrus.Debug("Ready to run middlewares")
|
||||
|
|
|
@ -50,5 +50,6 @@ func Deserializers() []deserializer.CTYDeserializer {
|
|||
awsdeserializer.NewSqsQueueDeserializer(),
|
||||
awsdeserializer.NewSqsQueuePolicyDeserializer(),
|
||||
awsdeserializer.NewSNSTopicDeserializer(),
|
||||
awsdeserializer.NewSNSTopicPolicyDeserializer(),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,6 +77,7 @@ func TestTerraformStateReader_Resources(t *testing.T) {
|
|||
{name: "SQS queue", dirName: "sqs_queue", wantErr: false},
|
||||
{name: "SQS queue policy", dirName: "sqs_queue_policy", wantErr: false},
|
||||
{name: "SNS Topic", dirName: "sns_topic", wantErr: false},
|
||||
{name: "SNS Topic Policy", dirName: "sns_topic_policy", wantErr: false},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
[
|
||||
{
|
||||
"Arn": "arn:aws:sns:us-east-1:526954929923:my-topic-with-policy2",
|
||||
"Id": "arn:aws:sns:us-east-1:526954929923:my-topic-with-policy2",
|
||||
"Policy": "{\"Id\":\"__default_policy_ID\",\"Statement\":[{\"Action\":[\"SNS:Subscribe\",\"SNS:SetTopicAttributes\",\"SNS:RemovePermission\",\"SNS:Receive\",\"SNS:Publish\",\"SNS:ListSubscriptionsByTopic\",\"SNS:GetTopicAttributes\",\"SNS:DeleteTopic\",\"SNS:AddPermission\"],\"Condition\":{\"StringEquals\":{\"AWS:SourceOwner\":[]}},\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Resource\":\"arn:aws:sns:us-east-1:526954929923:my-topic-with-policy\",\"Sid\":\"__default_statement_ID\"}],\"Version\":\"2012-10-17\"}"
|
||||
},
|
||||
{
|
||||
"Arn": "arn:aws:sns:us-east-1:526954929923:my-topic-with-policy",
|
||||
"Id": "arn:aws:sns:us-east-1:526954929923:my-topic-with-policy",
|
||||
"Policy": "{\"Id\":\"__default_policy_ID\",\"Statement\":[{\"Action\":[\"SNS:Subscribe\",\"SNS:SetTopicAttributes\",\"SNS:RemovePermission\",\"SNS:Receive\",\"SNS:Publish\",\"SNS:ListSubscriptionsByTopic\",\"SNS:GetTopicAttributes\",\"SNS:DeleteTopic\",\"SNS:AddPermission\"],\"Condition\":{\"StringEquals\":{\"AWS:SourceOwner\":[]}},\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Resource\":\"arn:aws:sns:us-east-1:526954929923:my-topic-with-policy\",\"Sid\":\"__default_statement_ID\"}],\"Version\":\"2012-10-17\"}"
|
||||
}
|
||||
]
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,111 @@
|
|||
{
|
||||
"version": 4,
|
||||
"terraform_version": "0.14.5",
|
||||
"serial": 20,
|
||||
"lineage": "30081725-54a2-ce02-6ff5-45c4d961c652",
|
||||
"outputs": {},
|
||||
"resources": [
|
||||
{
|
||||
"mode": "data",
|
||||
"type": "aws_iam_policy_document",
|
||||
"name": "sns_topic_policy",
|
||||
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
|
||||
"instances": [
|
||||
{
|
||||
"schema_version": 0,
|
||||
"attributes": {
|
||||
"id": "3435591602",
|
||||
"json": "{\n \"Version\": \"2012-10-17\",\n \"Id\": \"__default_policy_ID\",\n \"Statement\": [\n {\n \"Sid\": \"__default_statement_ID\",\n \"Effect\": \"Allow\",\n \"Action\": [\n \"SNS:Subscribe\",\n \"SNS:SetTopicAttributes\",\n \"SNS:RemovePermission\",\n \"SNS:Receive\",\n \"SNS:Publish\",\n \"SNS:ListSubscriptionsByTopic\",\n \"SNS:GetTopicAttributes\",\n \"SNS:DeleteTopic\",\n \"SNS:AddPermission\"\n ],\n \"Resource\": \"arn:aws:sns:us-east-1:526954929923:my-topic-with-policy\",\n \"Principal\": {\n \"AWS\": \"*\"\n },\n \"Condition\": {\n \"StringEquals\": {\n \"AWS:SourceOwner\": []\n }\n }\n }\n ]\n}",
|
||||
"override_json": null,
|
||||
"policy_id": "__default_policy_ID",
|
||||
"source_json": null,
|
||||
"statement": [
|
||||
{
|
||||
"actions": [
|
||||
"SNS:AddPermission",
|
||||
"SNS:DeleteTopic",
|
||||
"SNS:GetTopicAttributes",
|
||||
"SNS:ListSubscriptionsByTopic",
|
||||
"SNS:Publish",
|
||||
"SNS:Receive",
|
||||
"SNS:RemovePermission",
|
||||
"SNS:SetTopicAttributes",
|
||||
"SNS:Subscribe"
|
||||
],
|
||||
"condition": [
|
||||
{
|
||||
"test": "StringEquals",
|
||||
"values": [],
|
||||
"variable": "AWS:SourceOwner"
|
||||
}
|
||||
],
|
||||
"effect": "Allow",
|
||||
"not_actions": [],
|
||||
"not_principals": [],
|
||||
"not_resources": [],
|
||||
"principals": [
|
||||
{
|
||||
"identifiers": [
|
||||
"*"
|
||||
],
|
||||
"type": "AWS"
|
||||
}
|
||||
],
|
||||
"resources": [
|
||||
"arn:aws:sns:us-east-1:526954929923:my-topic-with-policy"
|
||||
],
|
||||
"sid": "__default_statement_ID"
|
||||
}
|
||||
],
|
||||
"version": "2012-10-17"
|
||||
},
|
||||
"sensitive_attributes": []
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"mode": "managed",
|
||||
"type": "aws_sns_topic_policy",
|
||||
"name": "default",
|
||||
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
|
||||
"instances": [
|
||||
{
|
||||
"schema_version": 0,
|
||||
"attributes": {
|
||||
"arn": "arn:aws:sns:us-east-1:526954929923:my-topic-with-policy",
|
||||
"id": "arn:aws:sns:us-east-1:526954929923:my-topic-with-policy",
|
||||
"policy": "{\"Version\":\"2012-10-17\",\"Id\":\"__default_policy_ID\",\"Statement\":[{\"Sid\":\"__default_statement_ID\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Action\":[\"SNS:Subscribe\",\"SNS:SetTopicAttributes\",\"SNS:RemovePermission\",\"SNS:Receive\",\"SNS:Publish\",\"SNS:ListSubscriptionsByTopic\",\"SNS:GetTopicAttributes\",\"SNS:DeleteTopic\",\"SNS:AddPermission\"],\"Resource\":\"arn:aws:sns:us-east-1:526954929923:my-topic-with-policy\",\"Condition\":{\"StringEquals\":{\"AWS:SourceOwner\":[]}}}]}"
|
||||
},
|
||||
"sensitive_attributes": [],
|
||||
"private": "bnVsbA==",
|
||||
"dependencies": [
|
||||
"aws_sns_topic.test",
|
||||
"data.aws_iam_policy_document.sns_topic_policy"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"mode": "managed",
|
||||
"type": "aws_sns_topic_policy",
|
||||
"name": "default2",
|
||||
"provider": "provider[\"registry.terraform.io/hashicorp/aws\"]",
|
||||
"instances": [
|
||||
{
|
||||
"schema_version": 0,
|
||||
"attributes": {
|
||||
"arn": "arn:aws:sns:us-east-1:526954929923:my-topic-with-policy2",
|
||||
"id": "arn:aws:sns:us-east-1:526954929923:my-topic-with-policy2",
|
||||
"policy": "{\"Version\":\"2012-10-17\",\"Id\":\"__default_policy_ID\",\"Statement\":[{\"Sid\":\"__default_statement_ID\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Action\":[\"SNS:Subscribe\",\"SNS:SetTopicAttributes\",\"SNS:RemovePermission\",\"SNS:Receive\",\"SNS:Publish\",\"SNS:ListSubscriptionsByTopic\",\"SNS:GetTopicAttributes\",\"SNS:DeleteTopic\",\"SNS:AddPermission\"],\"Resource\":\"arn:aws:sns:us-east-1:526954929923:my-topic-with-policy\",\"Condition\":{\"StringEquals\":{\"AWS:SourceOwner\":[]}}}]}"
|
||||
},
|
||||
"sensitive_attributes": [],
|
||||
"private": "bnVsbA==",
|
||||
"dependencies": [
|
||||
"aws_sns_topic.test2",
|
||||
"data.aws_iam_policy_document.sns_topic_policy"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
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_sns_topic from state resources to aws_sns_topic_policy resources
|
||||
type AwsSNSTopicPolicyExpander struct{}
|
||||
|
||||
func NewAwsSNSTopicPolicyExpander() AwsSNSTopicPolicyExpander {
|
||||
return AwsSNSTopicPolicyExpander{}
|
||||
}
|
||||
|
||||
func (m AwsSNSTopicPolicyExpander) Execute(_, resourcesFromState *[]resource.Resource) error {
|
||||
newList := make([]resource.Resource, 0)
|
||||
for _, res := range *resourcesFromState {
|
||||
// Ignore all resources other than sns_topic
|
||||
if res.TerraformType() != aws.AwsSnsTopicResourceType {
|
||||
newList = append(newList, res)
|
||||
continue
|
||||
}
|
||||
|
||||
topic, _ := res.(*aws.AwsSnsTopic)
|
||||
newList = append(newList, res)
|
||||
|
||||
if m.hasPolicyAttached(topic, resourcesFromState) {
|
||||
topic.Policy = nil
|
||||
continue
|
||||
}
|
||||
|
||||
err := m.splitPolicy(topic, &newList)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
*resourcesFromState = newList
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AwsSNSTopicPolicyExpander) splitPolicy(topic *aws.AwsSnsTopic, results *[]resource.Resource) error {
|
||||
if topic.Policy == nil || *topic.Policy == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
newPolicy := &aws.AwsSnsTopicPolicy{
|
||||
Id: topic.Id,
|
||||
Arn: topic.Arn,
|
||||
Policy: topic.Policy,
|
||||
}
|
||||
|
||||
normalized, err := newPolicy.NormalizeForState()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*results = append(*results, normalized)
|
||||
logrus.WithFields(logrus.Fields{
|
||||
"id": newPolicy.TerraformId(),
|
||||
}).Debug("Created new policy from sns_topic")
|
||||
|
||||
topic.Policy = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *AwsSNSTopicPolicyExpander) hasPolicyAttached(topic *aws.AwsSnsTopic, resourcesFromState *[]resource.Resource) bool {
|
||||
for _, res := range *resourcesFromState {
|
||||
if res.TerraformType() == aws.AwsSnsTopicPolicyResourceType &&
|
||||
res.TerraformId() == topic.Id {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
package middlewares
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
|
||||
awsresource "github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||
"github.com/r3labs/diff/v2"
|
||||
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
)
|
||||
|
||||
func TestAwsSNSTopicPolicyExpander_Execute(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
resourcesFromState *[]resource.Resource
|
||||
expected *[]resource.Resource
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "Inline policy no attached policy",
|
||||
resourcesFromState: &[]resource.Resource{
|
||||
&awsresource.AwsSnsTopic{
|
||||
Arn: aws.String("arn"),
|
||||
Policy: aws.String("{\"policy\": \"coucou\"}"),
|
||||
Id: "ID",
|
||||
},
|
||||
},
|
||||
expected: &[]resource.Resource{
|
||||
&awsresource.AwsSnsTopic{
|
||||
Arn: aws.String("arn"),
|
||||
Policy: nil,
|
||||
Id: "ID",
|
||||
},
|
||||
&awsresource.AwsSnsTopicPolicy{
|
||||
Arn: aws.String("arn"),
|
||||
Policy: aws.String("{\"policy\":\"coucou\"}"),
|
||||
Id: "ID",
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "No inline policy, attached policy",
|
||||
resourcesFromState: &[]resource.Resource{
|
||||
&awsresource.AwsSnsTopic{
|
||||
Arn: aws.String("arn"),
|
||||
Policy: nil,
|
||||
Id: "ID",
|
||||
},
|
||||
&awsresource.AwsSnsTopicPolicy{
|
||||
Arn: aws.String("arn"),
|
||||
Policy: aws.String("{\"policy\": \"coucou\"}"),
|
||||
Id: "ID",
|
||||
},
|
||||
},
|
||||
expected: &[]resource.Resource{
|
||||
&awsresource.AwsSnsTopic{
|
||||
Arn: aws.String("arn"),
|
||||
Policy: nil,
|
||||
Id: "ID",
|
||||
},
|
||||
&awsresource.AwsSnsTopicPolicy{
|
||||
Arn: aws.String("arn"),
|
||||
Policy: aws.String("{\"policy\": \"coucou\"}"),
|
||||
Id: "ID",
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "inline policy and attached policy",
|
||||
resourcesFromState: &[]resource.Resource{
|
||||
&awsresource.AwsSnsTopic{
|
||||
Arn: aws.String("arn"),
|
||||
Policy: aws.String("{\"policy\": \"coucou\"}"),
|
||||
Id: "ID",
|
||||
},
|
||||
&awsresource.AwsSnsTopicPolicy{
|
||||
Arn: aws.String("arn"),
|
||||
Policy: aws.String("{\"policy\": \"coucou\"}"),
|
||||
Id: "ID",
|
||||
},
|
||||
},
|
||||
expected: &[]resource.Resource{
|
||||
&awsresource.AwsSnsTopic{
|
||||
Arn: aws.String("arn"),
|
||||
Policy: nil,
|
||||
Id: "ID",
|
||||
},
|
||||
&awsresource.AwsSnsTopicPolicy{
|
||||
Arn: aws.String("arn"),
|
||||
Policy: aws.String("{\"policy\": \"coucou\"}"),
|
||||
Id: "ID",
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
m := AwsSNSTopicPolicyExpander{}
|
||||
if err := m.Execute(&[]resource.Resource{}, tt.resourcesFromState); (err != nil) != tt.wantErr {
|
||||
t.Errorf("Execute() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -60,6 +60,7 @@ func Init(alerter *alerter.Alerter, providerLibrary *terraform.ProviderLibrary,
|
|||
supplierLibrary.AddSupplier(NewSqsQueueSupplier(provider))
|
||||
supplierLibrary.AddSupplier(NewSqsQueuePolicySupplier(provider))
|
||||
supplierLibrary.AddSupplier(NewSNSTopicSupplier(provider))
|
||||
supplierLibrary.AddSupplier(NewSNSTopicPolicySupplier(provider))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/service/sns"
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/aws/repository"
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
|
||||
"github.com/cloudskiff/driftctl/pkg/remote/deserializer"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
"github.com/cloudskiff/driftctl/pkg/terraform"
|
||||
)
|
||||
|
||||
type SNSTopicPolicySupplier struct {
|
||||
reader terraform.ResourceReader
|
||||
deserializer deserializer.CTYDeserializer
|
||||
client repository.SNSRepository
|
||||
runner *terraform.ParallelResourceReader
|
||||
}
|
||||
|
||||
func NewSNSTopicPolicySupplier(provider *TerraformProvider) *SNSTopicPolicySupplier {
|
||||
return &SNSTopicPolicySupplier{
|
||||
provider,
|
||||
awsdeserializer.NewSNSTopicPolicyDeserializer(),
|
||||
repository.NewSNSClient(provider.session),
|
||||
terraform.NewParallelResourceReader(provider.Runner().SubRunner()),
|
||||
}
|
||||
}
|
||||
|
||||
func (s SNSTopicPolicySupplier) Resources() ([]resource.Resource, error) {
|
||||
topics, err := s.client.ListAllTopics()
|
||||
if err != nil {
|
||||
return nil, remoteerror.NewResourceEnumerationErrorWithType(err, aws.AwsSnsTopicPolicyResourceType, aws.AwsSnsTopicResourceType)
|
||||
}
|
||||
|
||||
for _, topic := range topics {
|
||||
topic := *topic
|
||||
s.runner.Run(func() (cty.Value, error) {
|
||||
return s.readTopicPolicy(topic)
|
||||
})
|
||||
}
|
||||
|
||||
retrieve, err := s.runner.Wait()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return s.deserializer.Deserialize(retrieve)
|
||||
}
|
||||
|
||||
func (s SNSTopicPolicySupplier) readTopicPolicy(topic sns.Topic) (cty.Value, error) {
|
||||
val, err := s.reader.ReadResource(terraform.ReadResourceArgs{
|
||||
ID: *topic.TopicArn,
|
||||
Ty: aws.AwsSnsTopicPolicyResourceType,
|
||||
Attributes: map[string]string{
|
||||
"topic_arn": *topic.TopicArn,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
logrus.Error(err)
|
||||
return cty.NilVal, err
|
||||
}
|
||||
return *val, nil
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/sns"
|
||||
|
||||
remoteerror "github.com/cloudskiff/driftctl/pkg/remote/error"
|
||||
|
||||
resourceaws "github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awserr"
|
||||
|
||||
"github.com/cloudskiff/driftctl/pkg/parallel"
|
||||
|
||||
awsdeserializer "github.com/cloudskiff/driftctl/pkg/resource/aws/deserializer"
|
||||
|
||||
"github.com/cloudskiff/driftctl/test/goldenfile"
|
||||
mocks2 "github.com/cloudskiff/driftctl/test/mocks"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/mock"
|
||||
|
||||
"github.com/cloudskiff/driftctl/mocks"
|
||||
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
"github.com/cloudskiff/driftctl/pkg/terraform"
|
||||
"github.com/cloudskiff/driftctl/test"
|
||||
)
|
||||
|
||||
func TestSNSTopicPolicySupplier_Resources(t *testing.T) {
|
||||
cases := []struct {
|
||||
test string
|
||||
dirName string
|
||||
mocks func(client *mocks.SNSRepository)
|
||||
err error
|
||||
}{
|
||||
{
|
||||
test: "no SNS Topic policy",
|
||||
dirName: "sns_topic_policy_empty",
|
||||
mocks: func(client *mocks.SNSRepository) {
|
||||
client.On("ListAllTopics").Return([]*sns.Topic{}, nil)
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
test: "Multiple SNSTopicPolicy",
|
||||
dirName: "sns_topic_policy_multiple",
|
||||
mocks: func(client *mocks.SNSRepository) {
|
||||
client.On("ListAllTopics").Return([]*sns.Topic{
|
||||
{TopicArn: aws.String("arn:aws:sns:us-east-1:526954929923:my-topic-with-policy")},
|
||||
{TopicArn: aws.String("arn:aws:sns:us-east-1:526954929923:my-topic-with-policy2")},
|
||||
}, nil)
|
||||
},
|
||||
err: nil,
|
||||
},
|
||||
{
|
||||
test: "cannot list SNSTopic",
|
||||
dirName: "sns_topic_policy_topic_list",
|
||||
mocks: func(client *mocks.SNSRepository) {
|
||||
client.On("ListAllTopics").Return(nil, awserr.NewRequestFailure(nil, 403, ""))
|
||||
},
|
||||
err: remoteerror.NewResourceEnumerationErrorWithType(awserr.NewRequestFailure(nil, 403, ""), resourceaws.AwsSnsTopicPolicyResourceType, resourceaws.AwsSnsTopicResourceType),
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
shouldUpdate := c.dirName == *goldenfile.Update
|
||||
|
||||
providerLibrary := terraform.NewProviderLibrary()
|
||||
supplierLibrary := resource.NewSupplierLibrary()
|
||||
|
||||
if shouldUpdate {
|
||||
provider, err := NewTerraFormProvider()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
providerLibrary.AddProvider(terraform.AWS, provider)
|
||||
supplierLibrary.AddSupplier(NewSNSTopicSupplier(provider))
|
||||
}
|
||||
|
||||
t.Run(c.test, func(tt *testing.T) {
|
||||
fakeClient := mocks.SNSRepository{}
|
||||
c.mocks(&fakeClient)
|
||||
provider := mocks2.NewMockedGoldenTFProvider(c.dirName, providerLibrary.Provider(terraform.AWS), shouldUpdate)
|
||||
SNSTopicPolicyDeserializer := awsdeserializer.NewSNSTopicPolicyDeserializer()
|
||||
s := &SNSTopicPolicySupplier{
|
||||
provider,
|
||||
SNSTopicPolicyDeserializer,
|
||||
&fakeClient,
|
||||
terraform.NewParallelResourceReader(parallel.NewParallelRunner(context.TODO(), 10)),
|
||||
}
|
||||
got, err := s.Resources()
|
||||
assert.Equal(tt, c.err, err)
|
||||
|
||||
mock.AssertExpectationsForObjects(tt)
|
||||
test.CtyTestDiff(got, c.dirName, provider, SNSTopicPolicyDeserializer, shouldUpdate, tt)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
provider "aws" {
|
||||
region = "us-east-1"
|
||||
}
|
||||
|
||||
resource "aws_sns_topic" "test" {
|
||||
name = "my-topic-with-policy"
|
||||
}
|
||||
|
||||
resource "aws_sns_topic_policy" "default" {
|
||||
arn = aws_sns_topic.test.arn
|
||||
|
||||
policy = data.aws_iam_policy_document.sns_topic_policy.json
|
||||
}
|
||||
|
||||
resource "aws_sns_topic" "test2" {
|
||||
name = "my-topic-with-policy2"
|
||||
}
|
||||
|
||||
resource "aws_sns_topic_policy" "default2" {
|
||||
arn = aws_sns_topic.test2.arn
|
||||
|
||||
policy = data.aws_iam_policy_document.sns_topic_policy.json
|
||||
}
|
||||
|
||||
data "aws_iam_policy_document" "sns_topic_policy" {
|
||||
policy_id = "__default_policy_ID"
|
||||
|
||||
statement {
|
||||
actions = [
|
||||
"SNS:Subscribe",
|
||||
"SNS:SetTopicAttributes",
|
||||
"SNS:RemovePermission",
|
||||
"SNS:Receive",
|
||||
"SNS:Publish",
|
||||
"SNS:ListSubscriptionsByTopic",
|
||||
"SNS:GetTopicAttributes",
|
||||
"SNS:DeleteTopic",
|
||||
"SNS:AddPermission",
|
||||
]
|
||||
|
||||
condition {
|
||||
test = "StringEquals"
|
||||
variable = "AWS:SourceOwner"
|
||||
values = []
|
||||
}
|
||||
|
||||
effect = "Allow"
|
||||
|
||||
principals {
|
||||
type = "AWS"
|
||||
identifiers = ["*"]
|
||||
}
|
||||
|
||||
resources = [
|
||||
aws_sns_topic.test.arn,
|
||||
]
|
||||
|
||||
sid = "__default_statement_ID"
|
||||
}
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
[]
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"Typ": "WyJvYmplY3QiLHsiYXJuIjoic3RyaW5nIiwiaWQiOiJzdHJpbmciLCJwb2xpY3kiOiJzdHJpbmcifV0=",
|
||||
"Val": "eyJhcm4iOiJhcm46YXdzOnNuczp1cy1lYXN0LTE6NTI2OTU0OTI5OTIzOm15LXRvcGljLXdpdGgtcG9saWN5IiwiaWQiOiJhcm46YXdzOnNuczp1cy1lYXN0LTE6NTI2OTU0OTI5OTIzOm15LXRvcGljLXdpdGgtcG9saWN5IiwicG9saWN5Ijoie1wiVmVyc2lvblwiOlwiMjAxMi0xMC0xN1wiLFwiSWRcIjpcIl9fZGVmYXVsdF9wb2xpY3lfSURcIixcIlN0YXRlbWVudFwiOlt7XCJTaWRcIjpcIl9fZGVmYXVsdF9zdGF0ZW1lbnRfSURcIixcIkVmZmVjdFwiOlwiQWxsb3dcIixcIlByaW5jaXBhbFwiOntcIkFXU1wiOlwiKlwifSxcIkFjdGlvblwiOltcIlNOUzpTdWJzY3JpYmVcIixcIlNOUzpTZXRUb3BpY0F0dHJpYnV0ZXNcIixcIlNOUzpSZW1vdmVQZXJtaXNzaW9uXCIsXCJTTlM6UmVjZWl2ZVwiLFwiU05TOlB1Ymxpc2hcIixcIlNOUzpMaXN0U3Vic2NyaXB0aW9uc0J5VG9waWNcIixcIlNOUzpHZXRUb3BpY0F0dHJpYnV0ZXNcIixcIlNOUzpEZWxldGVUb3BpY1wiLFwiU05TOkFkZFBlcm1pc3Npb25cIl0sXCJSZXNvdXJjZVwiOlwiYXJuOmF3czpzbnM6dXMtZWFzdC0xOjUyNjk1NDkyOTkyMzpteS10b3BpYy13aXRoLXBvbGljeVwiLFwiQ29uZGl0aW9uXCI6e1wiU3RyaW5nRXF1YWxzXCI6e1wiQVdTOlNvdXJjZU93bmVyXCI6W119fX1dfSJ9",
|
||||
"Err": null
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"Typ": "WyJvYmplY3QiLHsiYXJuIjoic3RyaW5nIiwiaWQiOiJzdHJpbmciLCJwb2xpY3kiOiJzdHJpbmcifV0=",
|
||||
"Val": "eyJhcm4iOiJhcm46YXdzOnNuczp1cy1lYXN0LTE6NTI2OTU0OTI5OTIzOm15LXRvcGljLXdpdGgtcG9saWN5MiIsImlkIjoiYXJuOmF3czpzbnM6dXMtZWFzdC0xOjUyNjk1NDkyOTkyMzpteS10b3BpYy13aXRoLXBvbGljeTIiLCJwb2xpY3kiOiJ7XCJWZXJzaW9uXCI6XCIyMDEyLTEwLTE3XCIsXCJJZFwiOlwiX19kZWZhdWx0X3BvbGljeV9JRFwiLFwiU3RhdGVtZW50XCI6W3tcIlNpZFwiOlwiX19kZWZhdWx0X3N0YXRlbWVudF9JRFwiLFwiRWZmZWN0XCI6XCJBbGxvd1wiLFwiUHJpbmNpcGFsXCI6e1wiQVdTXCI6XCIqXCJ9LFwiQWN0aW9uXCI6W1wiU05TOlN1YnNjcmliZVwiLFwiU05TOlNldFRvcGljQXR0cmlidXRlc1wiLFwiU05TOlJlbW92ZVBlcm1pc3Npb25cIixcIlNOUzpSZWNlaXZlXCIsXCJTTlM6UHVibGlzaFwiLFwiU05TOkxpc3RTdWJzY3JpcHRpb25zQnlUb3BpY1wiLFwiU05TOkdldFRvcGljQXR0cmlidXRlc1wiLFwiU05TOkRlbGV0ZVRvcGljXCIsXCJTTlM6QWRkUGVybWlzc2lvblwiXSxcIlJlc291cmNlXCI6XCJhcm46YXdzOnNuczp1cy1lYXN0LTE6NTI2OTU0OTI5OTIzOm15LXRvcGljLXdpdGgtcG9saWN5XCIsXCJDb25kaXRpb25cIjp7XCJTdHJpbmdFcXVhbHNcIjp7XCJBV1M6U291cmNlT3duZXJcIjpbXX19fV19In0=",
|
||||
"Err": null
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
[
|
||||
{
|
||||
"arn": "arn:aws:sns:us-east-1:526954929923:my-topic-with-policy2",
|
||||
"id": "arn:aws:sns:us-east-1:526954929923:my-topic-with-policy2",
|
||||
"policy": "{\"Version\":\"2012-10-17\",\"Id\":\"__default_policy_ID\",\"Statement\":[{\"Sid\":\"__default_statement_ID\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Action\":[\"SNS:Subscribe\",\"SNS:SetTopicAttributes\",\"SNS:RemovePermission\",\"SNS:Receive\",\"SNS:Publish\",\"SNS:ListSubscriptionsByTopic\",\"SNS:GetTopicAttributes\",\"SNS:DeleteTopic\",\"SNS:AddPermission\"],\"Resource\":\"arn:aws:sns:us-east-1:526954929923:my-topic-with-policy\",\"Condition\":{\"StringEquals\":{\"AWS:SourceOwner\":[]}}}]}"
|
||||
},
|
||||
{
|
||||
"arn": "arn:aws:sns:us-east-1:526954929923:my-topic-with-policy",
|
||||
"id": "arn:aws:sns:us-east-1:526954929923:my-topic-with-policy",
|
||||
"policy": "{\"Version\":\"2012-10-17\",\"Id\":\"__default_policy_ID\",\"Statement\":[{\"Sid\":\"__default_statement_ID\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Action\":[\"SNS:Subscribe\",\"SNS:SetTopicAttributes\",\"SNS:RemovePermission\",\"SNS:Receive\",\"SNS:Publish\",\"SNS:ListSubscriptionsByTopic\",\"SNS:GetTopicAttributes\",\"SNS:DeleteTopic\",\"SNS:AddPermission\"],\"Resource\":\"arn:aws:sns:us-east-1:526954929923:my-topic-with-policy\",\"Condition\":{\"StringEquals\":{\"AWS:SourceOwner\":[]}}}]}"
|
||||
}
|
||||
]
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1 @@
|
|||
[]
|
File diff suppressed because it is too large
Load Diff
|
@ -2,8 +2,22 @@ package aws
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
)
|
||||
|
||||
func (r *AwsSnsTopic) NormalizeForState() (resource.Resource, error) {
|
||||
if r.Policy != nil && *r.Policy == "" {
|
||||
r.Policy = nil
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (r *AwsSnsTopic) NormalizeForProvider() (resource.Resource, error) {
|
||||
r.Policy = nil
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (r *AwsSnsTopic) String() string {
|
||||
if r.DisplayName != nil && *r.DisplayName != "" && r.Name != nil && *r.Name != "" {
|
||||
return fmt.Sprintf("%s (%s)", *r.DisplayName, *r.Name)
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// GENERATED, DO NOT EDIT THIS FILE
|
||||
package aws
|
||||
|
||||
const AwsSnsTopicPolicyResourceType = "aws_sns_topic_policy"
|
||||
|
||||
type AwsSnsTopicPolicy struct {
|
||||
Arn *string `cty:"arn"`
|
||||
Id string `cty:"id" computed:"true"`
|
||||
Policy *string `cty:"policy"`
|
||||
}
|
||||
|
||||
func (r *AwsSnsTopicPolicy) TerraformId() string {
|
||||
return r.Id
|
||||
}
|
||||
|
||||
func (r *AwsSnsTopicPolicy) TerraformType() string {
|
||||
return AwsSnsTopicPolicyResourceType
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
package aws
|
||||
|
||||
import (
|
||||
"github.com/cloudskiff/driftctl/pkg/helpers"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
)
|
||||
|
||||
func (r AwsSnsTopicPolicy) NormalizeForState() (resource.Resource, error) {
|
||||
err := r.normalizePolicy()
|
||||
return &r, err
|
||||
}
|
||||
|
||||
func (r AwsSnsTopicPolicy) NormalizeForProvider() (resource.Resource, error) {
|
||||
err := r.normalizePolicy()
|
||||
return &r, err
|
||||
}
|
||||
|
||||
func (r *AwsSnsTopicPolicy) normalizePolicy() error {
|
||||
if r.Policy != nil {
|
||||
jsonString, err := helpers.NormalizeJsonString(*r.Policy)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.Policy = &jsonString
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package aws_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/cloudskiff/driftctl/test/acceptance"
|
||||
)
|
||||
|
||||
func TestAcc_AwsSNSTopicPolicy(t *testing.T) {
|
||||
acceptance.Run(t, acceptance.AccTestCase{
|
||||
Path: "./testdata/acc/aws_sns_topic_policy",
|
||||
Args: []string{"scan", "--filter", "Type=='aws_sns_topic' || Type=='aws_sns_topic_policy'"},
|
||||
Checks: []acceptance.AccCheck{
|
||||
{
|
||||
Env: map[string]string{
|
||||
"AWS_REGION": "us-east-1",
|
||||
},
|
||||
Check: func(result *acceptance.ScanResult, stdout string, err error) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
result.AssertDriftCountTotal(0)
|
||||
result.AssertDeletedCount(0)
|
||||
result.AssertManagedCount(6)
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package deserializer
|
||||
|
||||
import (
|
||||
"github.com/cloudskiff/driftctl/pkg/resource"
|
||||
"github.com/cloudskiff/driftctl/pkg/resource/aws"
|
||||
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
"github.com/zclconf/go-cty/cty/gocty"
|
||||
)
|
||||
|
||||
type SNSTopicPolicyDeserializer struct {
|
||||
}
|
||||
|
||||
func NewSNSTopicPolicyDeserializer() *SNSTopicPolicyDeserializer {
|
||||
return &SNSTopicPolicyDeserializer{}
|
||||
}
|
||||
|
||||
func (s *SNSTopicPolicyDeserializer) HandledType() resource.ResourceType {
|
||||
return aws.AwsSnsTopicPolicyResourceType
|
||||
}
|
||||
|
||||
func (s SNSTopicPolicyDeserializer) Deserialize(topicList []cty.Value) ([]resource.Resource, error) {
|
||||
policies := make([]resource.Resource, 0)
|
||||
|
||||
for _, value := range topicList {
|
||||
value := value
|
||||
policy, err := decodeSNSTopicPolicy(value)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
policies = append(policies, policy)
|
||||
}
|
||||
return policies, nil
|
||||
}
|
||||
|
||||
func decodeSNSTopicPolicy(value cty.Value) (resource.Resource, error) {
|
||||
var topicPolicy aws.AwsSnsTopicPolicy
|
||||
err := gocty.FromCtyValue(value, &topicPolicy)
|
||||
return &topicPolicy, err
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
# This file is maintained automatically by "terraform init".
|
||||
# Manual edits may be lost in future updates.
|
||||
|
||||
provider "registry.terraform.io/hashicorp/aws" {
|
||||
version = "3.26.0"
|
||||
hashes = [
|
||||
"h1:0i78FItlPeiomd+4ThZrtm56P5K33k7/6dnEe4ZePI0=",
|
||||
"zh:26043eed36d070ca032cf04bc980c654a25821a8abc0c85e1e570e3935bbfcbb",
|
||||
"zh:2fe68f3f78d23830a04d7fac3eda550eef1f627dfc130486f70a65dc5c254300",
|
||||
"zh:3d66484c608c64678e639db25d63872783ce60363a1246e30317f21c9c23b84b",
|
||||
"zh:46ffd755cfd4cf94fe66342797b5afdcef010a24e126c67fee141b357d393535",
|
||||
"zh:5e96f24357e945c9067cf5e032ad1d003609629c956c2f9f642fefe714e74587",
|
||||
"zh:60c27aca36bb63bf3e865c2193be80ca83b376581d00f9c220af4b013e163c4d",
|
||||
"zh:896f0f22d19d41e71b22f9240b261714c3915b165ddefeb771e7734d69dc47ea",
|
||||
"zh:90de9966cb2fd3e2f326df291595e55d2dd2d90e7d6dd085c2c8691dce82bdb4",
|
||||
"zh:ad05a91a88ceb1d6de5a568f7cc0b0e5bc0a79f3da70bc28c1e7f3750e362d58",
|
||||
"zh:e8c63f59c6465329e1f3357498face3dd7ef10a033df3c366a33aa9e94b46c01",
|
||||
]
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
provider "aws" {
|
||||
region = "us-east-1"
|
||||
}
|
||||
|
||||
resource "aws_sns_topic" "test" {
|
||||
name = "my-topic-with-policy"
|
||||
}
|
||||
|
||||
resource "aws_sns_topic_policy" "default" {
|
||||
arn = aws_sns_topic.test.arn
|
||||
|
||||
policy = data.aws_iam_policy_document.sns_topic_policy.json
|
||||
}
|
||||
|
||||
resource "aws_sns_topic" "test2" {
|
||||
name = "my-topic-with-policy2"
|
||||
}
|
||||
|
||||
resource "aws_sns_topic_policy" "default2" {
|
||||
arn = aws_sns_topic.test2.arn
|
||||
|
||||
policy = data.aws_iam_policy_document.sns_topic_policy.json
|
||||
}
|
||||
|
||||
data "aws_iam_policy_document" "sns_topic_policy" {
|
||||
policy_id = "__default_policy_ID"
|
||||
|
||||
statement {
|
||||
actions = [
|
||||
"SNS:Subscribe",
|
||||
"SNS:SetTopicAttributes",
|
||||
"SNS:RemovePermission",
|
||||
"SNS:Receive",
|
||||
"SNS:Publish",
|
||||
"SNS:ListSubscriptionsByTopic",
|
||||
"SNS:GetTopicAttributes",
|
||||
"SNS:DeleteTopic",
|
||||
"SNS:AddPermission",
|
||||
]
|
||||
|
||||
condition {
|
||||
test = "StringEquals"
|
||||
variable = "AWS:SourceOwner"
|
||||
values = []
|
||||
}
|
||||
|
||||
effect = "Allow"
|
||||
|
||||
principals {
|
||||
type = "AWS"
|
||||
identifiers = ["*"]
|
||||
}
|
||||
|
||||
resources = [
|
||||
aws_sns_topic.test.arn,
|
||||
]
|
||||
|
||||
sid = "__default_statement_ID"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_sns_topic" "user_updates" {
|
||||
name = "user-updates-topic"
|
||||
delivery_policy = <<EOF
|
||||
{
|
||||
"http": {
|
||||
"defaultHealthyRetryPolicy": {
|
||||
"minDelayTarget": 20,
|
||||
"maxDelayTarget": 20,
|
||||
"numRetries": 3,
|
||||
"numMaxDelayRetries": 0,
|
||||
"numNoDelayRetries": 0,
|
||||
"numMinDelayRetries": 0,
|
||||
"backoffFunction": "linear"
|
||||
},
|
||||
"disableSubscriptionOverrides": false,
|
||||
"defaultThrottlePolicy": {
|
||||
"maxReceivesPerSecond": 1
|
||||
}
|
||||
}
|
||||
}
|
||||
EOF
|
||||
}
|
Loading…
Reference in New Issue