mirror of
https://github.com/inspec/inspec
synced 2024-11-23 13:13:22 +00:00
New Skeletal Resource aws_sns_subscription (#2697)
* Initial commit of skeletal resource aws_sns_subscription * Fixes errors in documentation * Clarifies documentation * Wraps calls to aws api in catch_aws_errors metho * Fixes integration tests Signed-off-by: Matthew Dromazos <dromazmj@dukes.jmu.edu>
This commit is contained in:
parent
eb5302074a
commit
9077a7b17b
6 changed files with 419 additions and 1 deletions
125
docs/resources/aws_sns_subscription.md.erb
Normal file
125
docs/resources/aws_sns_subscription.md.erb
Normal file
|
@ -0,0 +1,125 @@
|
|||
---
|
||||
title: About the aws_sns_subscription Resource
|
||||
---
|
||||
|
||||
# aws\_sns\_subscription
|
||||
|
||||
Use the `aws_sns_subscription` InSpec audit resource to test detailed properties of a AWS SNS Subscription.
|
||||
|
||||
<br>
|
||||
|
||||
## Syntax
|
||||
|
||||
An `aws_sns_subscription` resource block uses resource parameters to search for a SNS Subscription, and then tests that subscriptions properties. If no Subscriptions match, no error is raised, but the `exists` matcher will return `false` and all properties will be `nil`.
|
||||
|
||||
describe aws_sns_subscription('arn:aws:sns:us-east-1::test-topic-01:b214aff5-a2c7-438f-a753-8494493f2ff6') do
|
||||
it { should exist }
|
||||
end
|
||||
|
||||
<br>
|
||||
|
||||
## Examples
|
||||
|
||||
The following examples show how to use this InSpec audit resource.
|
||||
|
||||
As this is the initial release of `aws_sns_subscription`, its limited functionality precludes examples.
|
||||
|
||||
<br>
|
||||
|
||||
## Resource Parameters
|
||||
|
||||
This InSpec resource accepts the following parameters, which are used to search for the Security Group.
|
||||
|
||||
### subscription\_arn
|
||||
|
||||
The ARN (Amazon Resource Name) of the AWS SNS Subscription.
|
||||
|
||||
# Using Hash syntax
|
||||
describe aws_sns_subscription(subscription_arn: 'arn:aws:sns:us-east-1::test-topic-01:b214aff5-a2c7-438f-a753-8494493f2ff6') do
|
||||
it { should exist }
|
||||
end
|
||||
|
||||
# Or omit hash syntax, rely on it being the default parameter
|
||||
describe aws_sns_subscription('arn:aws:sns:us-east-1::test-topic-01:b214aff5-a2c7-438f-a753-8494493f2ff6') do
|
||||
it { should exist }
|
||||
end
|
||||
|
||||
<br>
|
||||
|
||||
## Matchers
|
||||
|
||||
### exists
|
||||
|
||||
The control will pass if the specified Aws Subscription was found. Use should_not if you want to verify that the specified Subscription does not exist.
|
||||
|
||||
# Test that a specific subscription exists.
|
||||
describe aws_sns_subscription(subscription_arn: 'arn:aws:sns:us-east-1::test-topic-01:b214aff5-a2c7-438f-a753-8494493f2ff6')
|
||||
it { should exist }
|
||||
end
|
||||
|
||||
# Test that a Subscription does not exist.
|
||||
describe aws_sns_subscription(subscription_arn: 'arn:aws:sns:us-east-1::NOGOOD:b214aff5-a2c7-438f-a753-8494493f2ff6')
|
||||
it { should_not exist }
|
||||
end
|
||||
|
||||
### be\_confirmation\_authenticated
|
||||
|
||||
Provides whether or not the subscription confirmation request was authenticated.
|
||||
|
||||
describe aws_sns_subscription(subscription_arn: 'arn:aws:sns:us-east-1::NOGOOD:b214aff5-a2c7-438f-a753-8494493f2ff6')
|
||||
it { should be_confirmation_authenticated }
|
||||
end
|
||||
|
||||
### have\_raw\_message\_delivery
|
||||
|
||||
Provides whether or not the original message is passed as is, not formatted as a json or yaml.
|
||||
|
||||
describe aws_sns_subscription(subscription_arn: 'arn:aws:sns:us-east-1::NOGOOD:b214aff5-a2c7-438f-a753-8494493f2ff6')
|
||||
it { should have_raw_message_delivery }
|
||||
end
|
||||
|
||||
## Properties
|
||||
|
||||
### endpoint
|
||||
|
||||
Provides the destination that the SNS Topic will send notifications to.
|
||||
|
||||
# Inspect the endpoint
|
||||
describe aws_sns_subscription(subscription_arn: 'arn:aws:sns:us-east-1::test-topic-01:b214aff5-a2c7-438f-a753-8494493f2ff6' ) do
|
||||
# If protocol is 'sms', this should be a phone number:
|
||||
its('endpoint') { should cmp '+16105551234' }
|
||||
# If protocol is 'email' or 'email-json', endpoint should be an email address
|
||||
its('endpoint') { should cmp 'myemail@example.com' }
|
||||
# If protocal is 'http', endpoint should be a URL beginning with 'https://'
|
||||
its('endpoint') { should cmp 'https://www.exampleurl.com' }
|
||||
# If the protocol is 'lambda', its endpoint should be the ARN of a AWS Lambda function
|
||||
its('endpoint') { should cmp 'rn:aws:lambda:us-east-1:account-id:function:myfunction' }
|
||||
end
|
||||
|
||||
### owner
|
||||
|
||||
Provides the AWS Owners ID.
|
||||
|
||||
# Inspect the owners ID
|
||||
describe aws_sns_subscription(subscription_arn: 'arn:aws:sns:us-east-1::test-topic-01:b214aff5-a2c7-438f-a753-8494493f2ff6' ) do
|
||||
its('owner') { should cmp '12345678' }
|
||||
end
|
||||
|
||||
### protocol
|
||||
|
||||
Provides the Subscriptions protocol used. For example http, https, email, email-json, sqs, etc. For more information about protocols please visit https://docs.aws.amazon.com/sns/latest/api/API_Subscribe.html
|
||||
|
||||
# Inspect the endpoint
|
||||
describe aws_sns_subscription(subscription_arn: 'arn:aws:sns:us-east-1::test-topic-01:b214aff5-a2c7-438f-a753-8494493f2ff6' ) do
|
||||
its('protocol') { should cmp 'sqs' }
|
||||
end
|
||||
|
||||
### topic\_arn
|
||||
|
||||
Provides the SNS Topic arn that the Subscription is associated with.
|
||||
|
||||
# Inspect the topic arn
|
||||
describe aws_sns_subscription(subscription_arn: 'arn:aws:sns:us-east-1::test-topic-01:b214aff5-a2c7-438f-a753-8494493f2ff6' ) do
|
||||
its('topic_arn') { should cmp 'arn:aws:sns:us-east-1::test-topic-01' }
|
||||
end
|
||||
|
|
@ -35,6 +35,7 @@ require 'resources/aws/aws_s3_bucket'
|
|||
require 'resources/aws/aws_s3_bucket_object'
|
||||
require 'resources/aws/aws_security_group'
|
||||
require 'resources/aws/aws_security_groups'
|
||||
require 'resources/aws/aws_sns_subscription'
|
||||
require 'resources/aws/aws_sns_topic'
|
||||
require 'resources/aws/aws_sns_topics'
|
||||
require 'resources/aws/aws_subnet'
|
||||
|
|
78
lib/resources/aws/aws_sns_subscription.rb
Normal file
78
lib/resources/aws/aws_sns_subscription.rb
Normal file
|
@ -0,0 +1,78 @@
|
|||
class AwsSnsSubscription < Inspec.resource(1)
|
||||
name 'aws_sns_subscription'
|
||||
desc 'Verifies settings for an SNS Subscription'
|
||||
example "
|
||||
describe aws_sns_subscription('arn:aws:sns:us-east-1::test-topic-01:b214aff5-a2c7-438f-a753-8494493f2ff6') do
|
||||
it { should_not have_raw_message_delivery }
|
||||
it { should be_confirmation_authenticated }
|
||||
its('owner') { should cmp '12345678' }
|
||||
its('topic_arn') { should cmp 'arn:aws:sns:us-east-1::test-topic-01' }
|
||||
its('endpoint') { should cmp 'arn:aws:sqs:us-east-1::test-queue-01' }
|
||||
its('protocol') { should cmp 'sqs' }
|
||||
end
|
||||
"
|
||||
|
||||
supports platform: 'aws'
|
||||
|
||||
include AwsSingularResourceMixin
|
||||
attr_reader :arn, :owner, :raw_message_delivery, :topic_arn, :endpoint, :protocol,
|
||||
:confirmation_was_authenticated, :aws_response
|
||||
|
||||
alias confirmation_authenticated? confirmation_was_authenticated
|
||||
alias raw_message_delivery? raw_message_delivery
|
||||
|
||||
def has_raw_message_delivery?
|
||||
raw_message_delivery
|
||||
end
|
||||
|
||||
def to_s
|
||||
"SNS Subscription #{@arn}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate_params(raw_params)
|
||||
validated_params = check_resource_param_names(
|
||||
raw_params: raw_params,
|
||||
allowed_params: [:subscription_arn],
|
||||
allowed_scalar_name: :subscription_arn,
|
||||
allowed_scalar_type: String,
|
||||
)
|
||||
|
||||
if validated_params.empty?
|
||||
raise ArgumentError, 'You must provide a subscription_arn to aws_sns_subscription.'
|
||||
end
|
||||
|
||||
validated_params
|
||||
end
|
||||
|
||||
def fetch_from_api
|
||||
backend = BackendFactory.create(inspec_runner)
|
||||
catch_aws_errors do
|
||||
begin
|
||||
aws_response = backend.get_subscription_attributes(subscription_arn: @subscription_arn).attributes
|
||||
@exists = true
|
||||
@owner = aws_response['Owner']
|
||||
@raw_message_delivery = aws_response['RawMessageDelivery'].eql?('true')
|
||||
@topic_arn = aws_response['TopicArn']
|
||||
@endpoint = aws_response['Endpoint']
|
||||
@protocol = aws_response['Protocol']
|
||||
@confirmation_was_authenticated = aws_response['ConfirmationWasAuthenticated'].eql?('true')
|
||||
rescue Aws::SNS::Errors::NotFound
|
||||
@exists = false
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class Backend
|
||||
class AwsClientApi < AwsBackendBase
|
||||
BackendFactory.set_default_backend self
|
||||
self.aws_client_class = Aws::SNS::Client
|
||||
|
||||
def get_subscription_attributes(criteria)
|
||||
aws_service_client.get_subscription_attributes(criteria)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -34,4 +34,30 @@ resource "aws_sns_topic" "sns_test_topic_2" {
|
|||
|
||||
output "sns_topic_no_subscription_arn" {
|
||||
value = "${aws_sns_topic.sns_test_topic_2.arn}"
|
||||
}
|
||||
}
|
||||
|
||||
resource "aws_sns_topic" "topic_for_sub_03" {
|
||||
name = "${terraform.env}-topic_for_sub_3_test"
|
||||
}
|
||||
|
||||
resource "aws_sqs_queue" "sqs_for_sub_03" {
|
||||
name = "${terraform.env}-sqs_for_sub_03"
|
||||
}
|
||||
|
||||
resource "aws_sns_topic_subscription" "subscription_3" {
|
||||
topic_arn = "${aws_sns_topic.topic_for_sub_03.arn}"
|
||||
protocol = "sqs"
|
||||
endpoint = "${aws_sqs_queue.sqs_for_sub_03.arn}"
|
||||
}
|
||||
|
||||
output "sns_subscription_03_arn" {
|
||||
value = "${aws_sns_topic_subscription.subscription_3.arn}"
|
||||
}
|
||||
|
||||
output "sns_topic_3_arn" {
|
||||
value = "${aws_sns_topic.topic_for_sub_03.arn}"
|
||||
}
|
||||
|
||||
output "sqs_for_sub_03_arn" {
|
||||
value = "${aws_sqs_queue.sqs_for_sub_03.arn}"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
fixtures = {}
|
||||
[
|
||||
'sns_subscription_03_arn',
|
||||
'sns_topic_3_arn',
|
||||
'sqs_for_sub_03_arn',
|
||||
'aws_account_id',
|
||||
].each do |fixture_name|
|
||||
fixtures[fixture_name] = attribute(
|
||||
fixture_name,
|
||||
default: "default.#{fixture_name}",
|
||||
description: 'See ../build/sns.tf',
|
||||
)
|
||||
end
|
||||
|
||||
control "aws_sns_subscription recall of default VPC" do
|
||||
# Test constructor scalar hit
|
||||
describe aws_sns_subscription(fixtures['sns_subscription_03_arn']) do
|
||||
it { should exist }
|
||||
end
|
||||
# Test constructor hash hit
|
||||
describe aws_sns_subscription(subscription_arn: fixtures['sns_subscription_03_arn']) do
|
||||
it { should exist }
|
||||
end
|
||||
|
||||
describe aws_sns_subscription(subscription_arn: 'arn:aws:sns:us-east-1:721741954427:NonExistentSubscrtiption:bf007420-6-45-96-9c2bf144') do
|
||||
it { should_not exist }
|
||||
end
|
||||
end
|
||||
|
||||
control "aws_sns_subscription properties" do
|
||||
describe aws_sns_subscription(fixtures['sns_subscription_03_arn']) do
|
||||
its('topic_arn') { should eq fixtures['sns_topic_3_arn'] }
|
||||
its('endpoint') { should eq fixtures['sqs_for_sub_03_arn'] }
|
||||
its('protocol') { should eq 'sqs' }
|
||||
its('owner') { should cmp fixtures['aws_account_id'] }
|
||||
end
|
||||
end
|
||||
|
||||
control "aws_sns_subscription matchers" do
|
||||
describe aws_sns_subscription(fixtures['sns_subscription_03_arn']) do
|
||||
it { should_not have_raw_message_delivery }
|
||||
it { should be_confirmation_authenticated }
|
||||
end
|
||||
end
|
144
test/unit/resources/aws_sns_subscription_test.rb
Normal file
144
test/unit/resources/aws_sns_subscription_test.rb
Normal file
|
@ -0,0 +1,144 @@
|
|||
require 'helper'
|
||||
|
||||
# MASSSB = MockAwsSNSSubscriptionSingularBackend
|
||||
# Abbreviation not used outside this file
|
||||
|
||||
#=============================================================================#
|
||||
# Constructor Tests
|
||||
#=============================================================================#
|
||||
class AwsSnsSubscriptionConstructorTest < Minitest::Test
|
||||
|
||||
def setup
|
||||
AwsSnsSubscription::BackendFactory.select(AwsMASSSB::Basic)
|
||||
end
|
||||
|
||||
def test_empty_params_not_ok
|
||||
assert_raises(ArgumentError) { AwsSnsSubscription.new }
|
||||
end
|
||||
|
||||
def test_accepts_subscription_arn_as_scalar
|
||||
AwsSnsSubscription.new('arn:aws:sns:us-west-2:0123456789012:my-topic2:8a21d249-4329-4871-acc6-7be709c6ea7f')
|
||||
end
|
||||
|
||||
def test_accepts_subscription_arn_as_hash
|
||||
AwsSnsSubscription.new(subscription_arn: 'arn:aws:sns:us-west-2:0123456789012:my-topic2:8a21d249-4329-4871-acc6-7be709c6ea7f')
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#=============================================================================#
|
||||
# Search / Recall
|
||||
#=============================================================================#
|
||||
class AwsSnsSubscriptionRecallTest < Minitest::Test
|
||||
|
||||
def setup
|
||||
AwsSnsSubscription::BackendFactory.select(AwsMASSSB::Basic)
|
||||
end
|
||||
|
||||
def test_search_hit_via_scalar_works
|
||||
assert AwsSnsSubscription.new('arn:aws:sns:us-west-2:0123456789012:my-topic2:8a21d249-4329-4871-acc6-7be709c6ea7f').exists?
|
||||
end
|
||||
|
||||
def test_search_hit_via_hash_works
|
||||
assert AwsSnsSubscription.new(subscription_arn: 'arn:aws:sns:us-west-2:0123456789012:my-topic2:8a21d249-4329-4871-acc6-7be709c6ea7f').exists?
|
||||
end
|
||||
|
||||
def test_search_miss_is_not_an_exception
|
||||
refute AwsSnsSubscription.new(subscription_arn: 'arn:aws:sns:us-west-2:0123456789012:my-topic_non_existent:8a21d249-4329-4871-00000-00000000').exists?
|
||||
end
|
||||
end
|
||||
|
||||
#=============================================================================#
|
||||
# Properties
|
||||
#=============================================================================#
|
||||
class AwsSnsSubscriptionPropertiesTest < Minitest::Test
|
||||
|
||||
def setup
|
||||
AwsSnsSubscription::BackendFactory.select(AwsMASSSB::Basic)
|
||||
end
|
||||
|
||||
def test_property_topic_arn
|
||||
assert_equal('arn:aws:sns:us-west-2:0123456789012:my-topic2', AwsSnsSubscription.new('arn:aws:sns:us-west-2:0123456789012:my-topic2:8a21d249-4329-4871-acc6-7be709c6ea7f').topic_arn)
|
||||
assert_nil(AwsSnsSubscription.new('arn:aws:sns:us-west-2:0123456789012:my-topic2:00000-0000-0000-0000-000000').topic_arn)
|
||||
end
|
||||
|
||||
def test_property_endpoint
|
||||
assert_equal('my-email2@example.com', AwsSnsSubscription.new('arn:aws:sns:us-west-2:0123456789012:my-topic2:8a21d249-4329-4871-acc6-7be709c6ea7f').endpoint)
|
||||
assert_nil(AwsSnsSubscription.new('arn:aws:sns:us-west-2:0123456789012:my-topic2:00000-0000-0000-0000-000000').endpoint)
|
||||
end
|
||||
|
||||
def test_property_protocol
|
||||
assert_equal('https', AwsSnsSubscription.new('arn:aws:sns:us-west-2:0123456789012:my-topic2:8a21d249-4329-4871-acc6-7be709c6ea7f').protocol)
|
||||
assert_equal('email', AwsSnsSubscription.new('arn:aws:sns:us-west-2:0123456789012:my-topic:8a21d249-4329-4871-acc6-7be709c6ea7f').protocol)
|
||||
assert_nil(AwsSnsSubscription.new('arn:aws:sns:us-west-2:0123456789012:my-topic2:00000-0000-0000-0000-000000').protocol)
|
||||
end
|
||||
|
||||
def test_property_owner
|
||||
assert_equal('0123456789012', AwsSnsSubscription.new('arn:aws:sns:us-west-2:0123456789012:my-topic2:8a21d249-4329-4871-acc6-7be709c6ea7f').owner)
|
||||
assert_nil(AwsSnsSubscription.new('arn:aws:sns:us-west-2:0123456789012:my-topic2:00000-0000-0000-0000-000000').owner)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#=============================================================================#
|
||||
# Matchers
|
||||
#=============================================================================#
|
||||
class AwsSnsSubscriptionMatchersTest < Minitest::Test
|
||||
|
||||
def setup
|
||||
AwsSnsSubscription::BackendFactory.select(AwsMASSSB::Basic)
|
||||
end
|
||||
|
||||
def test_matcher_raw_message_delivery_positive
|
||||
assert AwsSnsSubscription.new('arn:aws:sns:us-west-2:0123456789012:my-topic2:8a21d249-4329-4871-acc6-7be709c6ea7f').raw_message_delivery?
|
||||
end
|
||||
|
||||
def test_matcher_raw_message_delivery_negative
|
||||
refute AwsSnsSubscription.new('arn:aws:sns:us-west-2:0123456789012:my-topic:8a21d249-4329-4871-acc6-7be709c6ea7f').raw_message_delivery?
|
||||
end
|
||||
|
||||
def test_matcher_confirmation_authenticated_positive
|
||||
assert AwsSnsSubscription.new('arn:aws:sns:us-west-2:0123456789012:my-topic2:8a21d249-4329-4871-acc6-7be709c6ea7f').confirmation_authenticated?
|
||||
end
|
||||
|
||||
def test_matcher_confirmation_authenticated_negative
|
||||
refute AwsSnsSubscription.new('arn:aws:sns:us-west-2:0123456789012:my-topic:8a21d249-4329-4871-acc6-7be709c6ea7f').confirmation_authenticated?
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
#=============================================================================#
|
||||
# Test Fixtures
|
||||
#=============================================================================#
|
||||
module AwsMASSSB
|
||||
class Basic < AwsBackendBase
|
||||
def get_subscription_attributes(query)
|
||||
fixtures = OpenStruct.new({
|
||||
'arn:aws:sns:us-west-2:0123456789012:my-topic:8a21d249-4329-4871-acc6-7be709c6ea7f' => OpenStruct.new({
|
||||
"attributes" => OpenStruct.new({
|
||||
"Endpoint": "my-email@example.com",
|
||||
"Protocol": "email",
|
||||
"RawMessageDelivery": "false",
|
||||
"ConfirmationWasAuthenticated": "false",
|
||||
"Owner": "0123456789012",
|
||||
"SubscriptionArn": "arn:aws:sns:us-west-2:0123456789012:my-topic:8a21d249-4329-4871-acc6-7be709c6ea7f",
|
||||
"TopicArn": "arn:aws:sns:us-west-2:0123456789012:my-topic"
|
||||
}),
|
||||
}),
|
||||
'arn:aws:sns:us-west-2:0123456789012:my-topic2:8a21d249-4329-4871-acc6-7be709c6ea7f' => OpenStruct.new({
|
||||
"attributes" => OpenStruct.new({
|
||||
"Endpoint": "my-email2@example.com",
|
||||
"Protocol": "https",
|
||||
"RawMessageDelivery": "true",
|
||||
"ConfirmationWasAuthenticated": "true",
|
||||
"Owner": "0123456789012",
|
||||
"SubscriptionArn": "arn:aws:sns:us-west-2:0123456789012:my-topic2:8a21d249-4329-4871-acc6-7be709c6ea7f",
|
||||
"TopicArn": "arn:aws:sns:us-west-2:0123456789012:my-topic2"
|
||||
}),
|
||||
}),
|
||||
})
|
||||
return OpenStruct.new(fixtures[query[:subscription_arn]] ) unless fixtures[query[:subscription_arn]].nil?
|
||||
raise Aws::SNS::Errors::NotFound.new(Seahorse::Client::Http::Request, "Key does not exist")
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue