diff --git a/policies/ecc-aws-560-unused_sns_topic.yml b/policies/ecc-aws-560-unused_sns_topic.yml new file mode 100644 index 000000000..e77ab1bc8 --- /dev/null +++ b/policies/ecc-aws-560-unused_sns_topic.yml @@ -0,0 +1,26 @@ +# Copyright (c) 2023 EPAM Systems, Inc. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + + +policies: + - name: ecc-aws-560-unused_sns_topic + comment: '010002142000' + description: | + Amazon SNS topics unused + resource: aws.sns + filters: + - or: + - type: value + key: SubscriptionsConfirmed + value: "0" + - type: metrics + name: NumberOfMessagesPublished + statistics: Sum + missing-value: 0 + days: 30 + value: 0 + op: eq + period: 2592000 \ No newline at end of file diff --git a/terraform/ecc-aws-560-unused_sns_topic/green/provider.tf b/terraform/ecc-aws-560-unused_sns_topic/green/provider.tf new file mode 100644 index 000000000..386308dea --- /dev/null +++ b/terraform/ecc-aws-560-unused_sns_topic/green/provider.tf @@ -0,0 +1,20 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4" + } + } +} + +provider "aws" { + profile = var.profile + region = var.default-region + + default_tags { + tags = { + CustodianRule = "ecc-aws-560-unused_sns_topic" + ComplianceStatus = "Green" + } + } +} diff --git a/terraform/ecc-aws-560-unused_sns_topic/green/sns.tf b/terraform/ecc-aws-560-unused_sns_topic/green/sns.tf new file mode 100644 index 000000000..233efe5b6 --- /dev/null +++ b/terraform/ecc-aws-560-unused_sns_topic/green/sns.tf @@ -0,0 +1,28 @@ +resource "aws_sns_topic" "this" { + name = "560-sns-green" +} + +resource "aws_sqs_queue" "this" { + name = "560-sqs-green" +} + +resource "aws_sns_topic_subscription" "this" { + topic_arn = aws_sns_topic.this.arn + protocol = "sqs" + endpoint = aws_sqs_queue.this.arn +} + +resource "null_resource" "this" { + provisioner "local-exec" { + command = join(" ", [ + "aws sns publish ", + "--topic-arn ${aws_sns_topic.this.arn}", + "--message 'Hello World!'", + "--profile ${var.profile}", + "--region ${var.default-region}" + ] + ) + } + + depends_on = [aws_sns_topic_subscription.this] +} \ No newline at end of file diff --git a/terraform/ecc-aws-560-unused_sns_topic/green/terraform.tfvars b/terraform/ecc-aws-560-unused_sns_topic/green/terraform.tfvars new file mode 100644 index 000000000..368bc468f --- /dev/null +++ b/terraform/ecc-aws-560-unused_sns_topic/green/terraform.tfvars @@ -0,0 +1,2 @@ +profile = "c7n" +default-region = "us-east-1" \ No newline at end of file diff --git a/terraform/ecc-aws-560-unused_sns_topic/green/variables.tf b/terraform/ecc-aws-560-unused_sns_topic/green/variables.tf new file mode 100644 index 000000000..c8b410c24 --- /dev/null +++ b/terraform/ecc-aws-560-unused_sns_topic/green/variables.tf @@ -0,0 +1,9 @@ +variable "default-region" { + type = string + description = "Default region for resources will be created" +} + +variable "profile" { + type = string + description = "Profile name configured before running apply" +} diff --git a/terraform/ecc-aws-560-unused_sns_topic/iam/560-policy.json b/terraform/ecc-aws-560-unused_sns_topic/iam/560-policy.json new file mode 100644 index 000000000..edb7e6068 --- /dev/null +++ b/terraform/ecc-aws-560-unused_sns_topic/iam/560-policy.json @@ -0,0 +1,15 @@ +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "sns:ListTopics", + "sns:GetTopicAttributes", + "tag:GetResources", + "cloudwatch:GetMetricStatistics" + ], + "Resource": "*" + } + ] +} \ No newline at end of file diff --git a/terraform/ecc-aws-560-unused_sns_topic/red/provider.tf b/terraform/ecc-aws-560-unused_sns_topic/red/provider.tf new file mode 100644 index 000000000..8a434e4ab --- /dev/null +++ b/terraform/ecc-aws-560-unused_sns_topic/red/provider.tf @@ -0,0 +1,20 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 4" + } + } +} + +provider "aws" { + profile = var.profile + region = var.default-region + + default_tags { + tags = { + CustodianRule = "ecc-aws-560-unused_sns_topic" + ComplianceStatus = "Red" + } + } +} diff --git a/terraform/ecc-aws-560-unused_sns_topic/red/sns.tf b/terraform/ecc-aws-560-unused_sns_topic/red/sns.tf new file mode 100644 index 000000000..17043457d --- /dev/null +++ b/terraform/ecc-aws-560-unused_sns_topic/red/sns.tf @@ -0,0 +1,3 @@ +resource "aws_sns_topic" "this" { + name = "560-sns-red" +} \ No newline at end of file diff --git a/terraform/ecc-aws-560-unused_sns_topic/red/terraform.tfvars b/terraform/ecc-aws-560-unused_sns_topic/red/terraform.tfvars new file mode 100644 index 000000000..e1e2d2fa8 --- /dev/null +++ b/terraform/ecc-aws-560-unused_sns_topic/red/terraform.tfvars @@ -0,0 +1,2 @@ +profile = "c7n" +default-region = "us-east-1" diff --git a/terraform/ecc-aws-560-unused_sns_topic/red/variables.tf b/terraform/ecc-aws-560-unused_sns_topic/red/variables.tf new file mode 100644 index 000000000..c8b410c24 --- /dev/null +++ b/terraform/ecc-aws-560-unused_sns_topic/red/variables.tf @@ -0,0 +1,9 @@ +variable "default-region" { + type = string + description = "Default region for resources will be created" +} + +variable "profile" { + type = string + description = "Profile name configured before running apply" +} diff --git a/tests/ecc-aws-560-unused_sns_topic/placebo-green/monitoring.GetMetricStatistics_1.json b/tests/ecc-aws-560-unused_sns_topic/placebo-green/monitoring.GetMetricStatistics_1.json new file mode 100644 index 000000000..5857d87f7 --- /dev/null +++ b/tests/ecc-aws-560-unused_sns_topic/placebo-green/monitoring.GetMetricStatistics_1.json @@ -0,0 +1,23 @@ +{ + "status_code": 200, + "data": { + "Label": "NumberOfMessagesPublished", + "Datapoints": [ + { + "Timestamp": { + "__class__": "datetime", + "year": 2023, + "month": 8, + "day": 20, + "hour": 18, + "minute": 55, + "second": 0, + "microsecond": 0 + }, + "Sum": 1.0, + "Unit": "Count" + } + ], + "ResponseMetadata": {} + } +} \ No newline at end of file diff --git a/tests/ecc-aws-560-unused_sns_topic/placebo-green/sns.GetTopicAttributes_1.json b/tests/ecc-aws-560-unused_sns_topic/placebo-green/sns.GetTopicAttributes_1.json new file mode 100644 index 000000000..7700375cd --- /dev/null +++ b/tests/ecc-aws-560-unused_sns_topic/placebo-green/sns.GetTopicAttributes_1.json @@ -0,0 +1,21 @@ +{ + "status_code": 200, + "data": { + "Attributes": { + "Policy": "{\"Version\":\"2008-10-17\",\"Id\":\"__default_policy_ID\",\"Statement\":[{\"Sid\":\"__default_statement_ID\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Action\":[\"SNS:GetTopicAttributes\",\"SNS:SetTopicAttributes\",\"SNS:AddPermission\",\"SNS:RemovePermission\",\"SNS:DeleteTopic\",\"SNS:Subscribe\",\"SNS:ListSubscriptionsByTopic\",\"SNS:Publish\"],\"Resource\":\"arn:aws:sns:us-east-1:111111111111:560-sns-green\",\"Condition\":{\"StringEquals\":{\"AWS:SourceOwner\":\"111111111111\"}}}]}", + "LambdaSuccessFeedbackSampleRate": "0", + "Owner": "111111111111", + "SubscriptionsPending": "0", + "TopicArn": "arn:aws:sns:us-east-1:111111111111:560-sns-green", + "EffectiveDeliveryPolicy": "{\"http\":{\"defaultHealthyRetryPolicy\":{\"minDelayTarget\":20,\"maxDelayTarget\":20,\"numRetries\":3,\"numMaxDelayRetries\":0,\"numNoDelayRetries\":0,\"numMinDelayRetries\":0,\"backoffFunction\":\"linear\"},\"disableSubscriptionOverrides\":false,\"defaultRequestPolicy\":{\"headerContentType\":\"text/plain; charset=UTF-8\"}}}", + "FirehoseSuccessFeedbackSampleRate": "0", + "SubscriptionsConfirmed": "1", + "SQSSuccessFeedbackSampleRate": "0", + "HTTPSuccessFeedbackSampleRate": "0", + "ApplicationSuccessFeedbackSampleRate": "0", + "DisplayName": "", + "SubscriptionsDeleted": "0" + }, + "ResponseMetadata": {} + } +} \ No newline at end of file diff --git a/tests/ecc-aws-560-unused_sns_topic/placebo-green/sns.ListTopics_1.json b/tests/ecc-aws-560-unused_sns_topic/placebo-green/sns.ListTopics_1.json new file mode 100644 index 000000000..fc96fb1fe --- /dev/null +++ b/tests/ecc-aws-560-unused_sns_topic/placebo-green/sns.ListTopics_1.json @@ -0,0 +1,11 @@ +{ + "status_code": 200, + "data": { + "Topics": [ + { + "TopicArn": "arn:aws:sns:us-east-1:111111111111:560-sns-green" + } + ], + "ResponseMetadata": {} + } +} \ No newline at end of file diff --git a/tests/ecc-aws-560-unused_sns_topic/placebo-green/tagging.GetResources_1.json b/tests/ecc-aws-560-unused_sns_topic/placebo-green/tagging.GetResources_1.json new file mode 100644 index 000000000..17f8976bf --- /dev/null +++ b/tests/ecc-aws-560-unused_sns_topic/placebo-green/tagging.GetResources_1.json @@ -0,0 +1,22 @@ +{ + "status_code": 200, + "data": { + "PaginationToken": "", + "ResourceTagMappingList": [ + { + "ResourceARN": "arn:aws:sns:us-east-1:111111111111:560-sns-green", + "Tags": [ + { + "Key": "CustodianRule", + "Value": "ecc-aws-560-unused_sns_topic" + }, + { + "Key": "ComplianceStatus", + "Value": "Green" + } + ] + } + ], + "ResponseMetadata": {} + } +} \ No newline at end of file diff --git a/tests/ecc-aws-560-unused_sns_topic/placebo-red/monitoring.GetMetricStatistics_1.json b/tests/ecc-aws-560-unused_sns_topic/placebo-red/monitoring.GetMetricStatistics_1.json new file mode 100644 index 000000000..b3702766d --- /dev/null +++ b/tests/ecc-aws-560-unused_sns_topic/placebo-red/monitoring.GetMetricStatistics_1.json @@ -0,0 +1,8 @@ +{ + "status_code": 200, + "data": { + "Label": "NumberOfMessagesPublished", + "Datapoints": [], + "ResponseMetadata": {} + } +} \ No newline at end of file diff --git a/tests/ecc-aws-560-unused_sns_topic/placebo-red/sns.GetTopicAttributes_1.json b/tests/ecc-aws-560-unused_sns_topic/placebo-red/sns.GetTopicAttributes_1.json new file mode 100644 index 000000000..e17c13112 --- /dev/null +++ b/tests/ecc-aws-560-unused_sns_topic/placebo-red/sns.GetTopicAttributes_1.json @@ -0,0 +1,21 @@ +{ + "status_code": 200, + "data": { + "Attributes": { + "Policy": "{\"Version\":\"2008-10-17\",\"Id\":\"__default_policy_ID\",\"Statement\":[{\"Sid\":\"__default_statement_ID\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Action\":[\"SNS:GetTopicAttributes\",\"SNS:SetTopicAttributes\",\"SNS:AddPermission\",\"SNS:RemovePermission\",\"SNS:DeleteTopic\",\"SNS:Subscribe\",\"SNS:ListSubscriptionsByTopic\",\"SNS:Publish\"],\"Resource\":\"arn:aws:sns:us-east-1:111111111111:560-sns-red\",\"Condition\":{\"StringEquals\":{\"AWS:SourceOwner\":\"111111111111\"}}}]}", + "LambdaSuccessFeedbackSampleRate": "0", + "Owner": "111111111111", + "SubscriptionsPending": "0", + "TopicArn": "arn:aws:sns:us-east-1:111111111111:560-sns-red", + "EffectiveDeliveryPolicy": "{\"http\":{\"defaultHealthyRetryPolicy\":{\"minDelayTarget\":20,\"maxDelayTarget\":20,\"numRetries\":3,\"numMaxDelayRetries\":0,\"numNoDelayRetries\":0,\"numMinDelayRetries\":0,\"backoffFunction\":\"linear\"},\"disableSubscriptionOverrides\":false,\"defaultRequestPolicy\":{\"headerContentType\":\"text/plain; charset=UTF-8\"}}}", + "FirehoseSuccessFeedbackSampleRate": "0", + "SubscriptionsConfirmed": "0", + "SQSSuccessFeedbackSampleRate": "0", + "HTTPSuccessFeedbackSampleRate": "0", + "ApplicationSuccessFeedbackSampleRate": "0", + "DisplayName": "", + "SubscriptionsDeleted": "0" + }, + "ResponseMetadata": {} + } +} \ No newline at end of file diff --git a/tests/ecc-aws-560-unused_sns_topic/placebo-red/sns.ListTopics_1.json b/tests/ecc-aws-560-unused_sns_topic/placebo-red/sns.ListTopics_1.json new file mode 100644 index 000000000..7175aeec6 --- /dev/null +++ b/tests/ecc-aws-560-unused_sns_topic/placebo-red/sns.ListTopics_1.json @@ -0,0 +1,11 @@ +{ + "status_code": 200, + "data": { + "Topics": [ + { + "TopicArn": "arn:aws:sns:us-east-1:111111111111:560-sns-red" + } + ], + "ResponseMetadata": {} + } +} \ No newline at end of file diff --git a/tests/ecc-aws-560-unused_sns_topic/placebo-red/tagging.GetResources_1.json b/tests/ecc-aws-560-unused_sns_topic/placebo-red/tagging.GetResources_1.json new file mode 100644 index 000000000..7707638e6 --- /dev/null +++ b/tests/ecc-aws-560-unused_sns_topic/placebo-red/tagging.GetResources_1.json @@ -0,0 +1,22 @@ +{ + "status_code": 200, + "data": { + "PaginationToken": "", + "ResourceTagMappingList": [ + { + "ResourceARN": "arn:aws:sns:us-east-1:111111111111:560-sns-red", + "Tags": [ + { + "Key": "CustodianRule", + "Value": "ecc-aws-560-unused_sns_topic" + }, + { + "Key": "ComplianceStatus", + "Value": "Red" + } + ] + } + ], + "ResponseMetadata": {} + } +} \ No newline at end of file diff --git a/tests/ecc-aws-560-unused_sns_topic/red_policy_test.py b/tests/ecc-aws-560-unused_sns_topic/red_policy_test.py new file mode 100644 index 000000000..7130c1fb2 --- /dev/null +++ b/tests/ecc-aws-560-unused_sns_topic/red_policy_test.py @@ -0,0 +1,6 @@ +class PolicyTest(object): + + def test_resources(self, base_test, resources): + base_test.assertEqual(len(resources), 1) + base_test.assertEqual(resources[0]["SubscriptionsConfirmed"], "0") + base_test.assertEqual(resources[0]["c7n.metrics"]["AWS/SNS.NumberOfMessagesPublished.Sum.30"][0]["Sum"], 0)