mirror of
https://github.com/inspec/inspec
synced 2024-11-26 22:50:36 +00:00
New Skeletal Resource aws_config_delivery_channel (#2641)
* Initial commit of new skeletal resource aws_config_delivery_channel * Changes delivery_frequency to be an integer and names delivery_frequency_in_hours * Adds more documentation and clarifies descriptions * Wraps API call in the aws_catch_errors function * Changes config bucket name to use dashes instead of underscores * Updates on master and changes directory location of build and integration files * Fix integration tests to only create one ConfigRecorder Signed-off-by: Matthew Dromazos <dromazmj@dukes.jmu.edu>
This commit is contained in:
parent
afbb366e16
commit
0cbe5b60e5
5 changed files with 282 additions and 1 deletions
79
docs/resources/aws_config_delivery_channel.md
Normal file
79
docs/resources/aws_config_delivery_channel.md
Normal file
|
@ -0,0 +1,79 @@
|
|||
---
|
||||
title: About the aws_config_delivery_channel Resource
|
||||
---
|
||||
|
||||
# aws_config_delivery_channel
|
||||
|
||||
The AWS Config service can monitor and record changes to your AWS resource configurations. A Delivery Channel can record the changes
|
||||
to an S3 Bucket, an SNS or both.
|
||||
|
||||
Use the `aws_config_delivery_channel` InSpec audit resource to examine how the AWS Config service delivers those change notifications.
|
||||
|
||||
<br>
|
||||
|
||||
## Syntax
|
||||
|
||||
An `aws_config_delivery_channel` resource block declares the tests for a single AWS Config delivery channel.
|
||||
|
||||
describe aws_config_delivery_channel('my_channel') do
|
||||
it { should exist }
|
||||
end
|
||||
|
||||
describe aws_config_delivery_channel(channel_name: 'my-channel') do
|
||||
it { should exist }
|
||||
end
|
||||
|
||||
<br>
|
||||
|
||||
## Examples
|
||||
|
||||
The following examples show how to use this InSpec audit resource.
|
||||
|
||||
### Test how frequent the channel writes configuration changes to the s3 bucket.
|
||||
|
||||
describe aws_config_delivery_channel(channel_name: 'my-recorder') do
|
||||
its(delivery_frequency_in_hours) { should be > 3 }
|
||||
end
|
||||
|
||||
## Properties
|
||||
|
||||
### s3_bucket_name
|
||||
|
||||
Provides the name of the s3 bucket that the channel sends configuration changes to. This is an optional value since a Delivery Channel can also talk to an SNS.
|
||||
|
||||
describe aws_config_delivery_channel(channel_name: 'my_channel')
|
||||
its('s3_bucket_name') { should eq 'my_bucket' }
|
||||
end
|
||||
|
||||
### s3_key_prefix
|
||||
|
||||
Provides the s3 object key prefix (or "path") under which configuration data will be recorded.
|
||||
|
||||
describe aws_config_delivery_channel(channel_name: 'my_channel')
|
||||
its('s3_key_prefix') { should eq 'log/' }
|
||||
end
|
||||
|
||||
### sns_topic_arn
|
||||
|
||||
Provides the ARN of the SNS topic for which the channel sends notifications about configuration changes.
|
||||
|
||||
describe aws_config_delivery_channel(channel_name: 'my_channel')
|
||||
its('sns_topic_arn') { should eq 'arn:aws:sns:us-east-1:721741954427:sns_topic' }
|
||||
end
|
||||
|
||||
### delivery_frequency_in_hours
|
||||
|
||||
Provides how often the AWS Config sends configuration changes to the s3 bucket in the delivery channel.
|
||||
|
||||
describe aws_config_delivery_channel(channel_name: 'my_channel')
|
||||
its('delivery_frequency_in_hours') { should eq 24 }
|
||||
its('delivery_frequency_in_hours') { should be > 24 }
|
||||
end
|
||||
|
||||
|
||||
<br>
|
||||
|
||||
## Matchers
|
||||
|
||||
This resource provides no matchers, aside from the standard exists matcher.
|
||||
|
|
@ -16,6 +16,7 @@ require 'resources/aws/aws_cloudtrail_trail'
|
|||
require 'resources/aws/aws_cloudtrail_trails'
|
||||
require 'resources/aws/aws_cloudwatch_alarm'
|
||||
require 'resources/aws/aws_cloudwatch_log_metric_filter'
|
||||
require 'resources/aws/aws_config_delivery_channel'
|
||||
require 'resources/aws/aws_config_recorder'
|
||||
require 'resources/aws/aws_ec2_instance'
|
||||
require 'resources/aws/aws_iam_access_key'
|
||||
|
|
76
lib/resources/aws/aws_config_delivery_channel.rb
Normal file
76
lib/resources/aws/aws_config_delivery_channel.rb
Normal file
|
@ -0,0 +1,76 @@
|
|||
class AwsConfigDeliveryChannel < Inspec.resource(1)
|
||||
name 'aws_config_delivery_channel'
|
||||
desc 'Verifies settings for AWS Config Delivery Channel'
|
||||
example "
|
||||
describe aws_config_delivery_channel do
|
||||
it { should exist }
|
||||
its('s3_bucket_name') { should eq 'my_bucket' }
|
||||
its('sns_topic_arn') { should eq arn:aws:sns:us-east-1:721741954427:sns_topic' }
|
||||
end
|
||||
"
|
||||
supports platform: 'aws'
|
||||
|
||||
include AwsSingularResourceMixin
|
||||
attr_reader :channel_name, :s3_bucket_name, :s3_key_prefix, :sns_topic_arn,
|
||||
:delivery_frequency_in_hours
|
||||
|
||||
def to_s
|
||||
"Config_Delivery_Channel: #{@channel_name}"
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def validate_params(raw_params)
|
||||
validated_params = check_resource_param_names(
|
||||
raw_params: raw_params,
|
||||
allowed_params: [:channel_name],
|
||||
allowed_scalar_name: :channel_name,
|
||||
allowed_scalar_type: String,
|
||||
)
|
||||
|
||||
# Make sure channel_name is given as param
|
||||
if validated_params[:channel_name].nil?
|
||||
raise ArgumentError, 'You must provide a channel_name to aws_config_delivery_channel'
|
||||
end
|
||||
|
||||
validated_params
|
||||
end
|
||||
|
||||
def fetch_from_api
|
||||
backend = BackendFactory.create(inspec_runner)
|
||||
query = { delivery_channel_names: [@channel_name] }
|
||||
catch_aws_errors do
|
||||
@resp = backend.describe_delivery_channels(query)
|
||||
end
|
||||
@exists = !@resp.empty?
|
||||
return unless @exists
|
||||
|
||||
@channel = @resp.delivery_channels.first.to_h
|
||||
@channel_name = @channel[:name]
|
||||
@s3_bucket_name = @channel[:s3_bucket_name]
|
||||
@s3_key_prefix = @channel[:s3_key_prefix]
|
||||
@sns_topic_arn = @channel[:sns_topic_arn]
|
||||
@delivery_frequency_in_hours = @channel[:config_snapshot_delivery_properties][:delivery_frequency] unless @channel[:config_snapshot_delivery_properties].nil?
|
||||
frequencies = {
|
||||
'One_Hour' => 1,
|
||||
'TwentyFour_Hours' => 24,
|
||||
'Three_Hours' => 3,
|
||||
'Six_Hours' => 6,
|
||||
'Twelve_Hours' => 12,
|
||||
}
|
||||
@delivery_frequency_in_hours = frequencies[@delivery_frequency_in_hours]
|
||||
end
|
||||
|
||||
class Backend
|
||||
class AwsClientApi < AwsBackendBase
|
||||
BackendFactory.set_default_backend(self)
|
||||
self.aws_client_class = Aws::ConfigService::Client
|
||||
|
||||
def describe_delivery_channels(query)
|
||||
aws_service_client.describe_delivery_channels(query)
|
||||
rescue Aws::ConfigService::Errors::NoSuchDeliveryChannelException
|
||||
return {}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -33,4 +33,81 @@ output "role_for_config_recorder_arn" {
|
|||
|
||||
output "config_recorder_name" {
|
||||
value = "${aws_config_configuration_recorder.config_recorder.name}"
|
||||
}
|
||||
}
|
||||
|
||||
#======================================================#
|
||||
# Configuration Delivery Channel
|
||||
#======================================================#
|
||||
|
||||
# Note that since AWS accounts can only have one Config Recorder,
|
||||
# we have to re-use it here (as well as its role).
|
||||
|
||||
resource "aws_config_delivery_channel" "delivery_channel_01" {
|
||||
name = "delivery_channel_01"
|
||||
s3_bucket_name = "${aws_s3_bucket.bucket_for_delivery_channel.bucket}"
|
||||
depends_on = ["aws_config_configuration_recorder.config_recorder"]
|
||||
sns_topic_arn = "${aws_sns_topic.sns_topic_for_delivery_channel.arn}"
|
||||
snapshot_delivery_properties = {
|
||||
delivery_frequency = "TwentyFour_Hours"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
output "delivery_channel_01" {
|
||||
value = "${aws_config_delivery_channel.delivery_channel_01.id}"
|
||||
}
|
||||
|
||||
output "config_recorder_for_delivery_channel_role_arn" {
|
||||
value = "${aws_iam_role.role_for_config_recorder.arn}"
|
||||
}
|
||||
|
||||
#======================================================#
|
||||
# IAM Roles
|
||||
#======================================================#
|
||||
|
||||
resource "aws_iam_role_policy" "policy_for_delivery_channel" {
|
||||
name = "policy_for_delivery_channel"
|
||||
role = "${aws_iam_role.role_for_config_recorder.id}"
|
||||
|
||||
policy = <<POLICY
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Action": [
|
||||
"s3:*"
|
||||
],
|
||||
"Effect": "Allow",
|
||||
"Resource": [
|
||||
"${aws_s3_bucket.bucket_for_delivery_channel.arn}",
|
||||
"${aws_s3_bucket.bucket_for_delivery_channel.arn}/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
POLICY
|
||||
}
|
||||
|
||||
#=================================================================#
|
||||
# Config S3 Buckets
|
||||
#=================================================================#
|
||||
resource "aws_s3_bucket" "bucket_for_delivery_channel" {
|
||||
bucket = "inspec-bucket-for-delivery-channel-${terraform.env}.chef.io"
|
||||
acl = "public-read"
|
||||
force_destroy = true
|
||||
}
|
||||
|
||||
output "s3_bucket_for_delivery_channel" {
|
||||
value = "${aws_s3_bucket.bucket_for_delivery_channel.id}"
|
||||
}
|
||||
|
||||
#===========================================================================#
|
||||
# SNS Topic
|
||||
#===========================================================================#
|
||||
resource "aws_sns_topic" "sns_topic_for_delivery_channel" {
|
||||
name = "${terraform.env}-sns_topic_for_delivery_channel"
|
||||
}
|
||||
|
||||
output "sns_topic_for_delivery_channel_arn" {
|
||||
value = "${aws_sns_topic.sns_topic_for_delivery_channel.arn}"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
fixtures = {}
|
||||
[
|
||||
'delivery_channel_01',
|
||||
'config_recorder_for_delivery_channel_role_arn',
|
||||
's3_bucket_for_delivery_channel',
|
||||
'delivery_channel_01_bucket_prefix',
|
||||
'sns_topic_for_delivery_channel_arn'
|
||||
].each do |fixture_name|
|
||||
fixtures[fixture_name] = attribute(
|
||||
fixture_name,
|
||||
default: "default.#{fixture_name}",
|
||||
description: 'See ../build/iam.tf',
|
||||
)
|
||||
end
|
||||
|
||||
#======================================================#
|
||||
# aws_config_delivery_channel - Singular
|
||||
#======================================================#
|
||||
|
||||
#------------------- Recall / Miss -------------------#
|
||||
|
||||
control "aws_config_delivery_channel recall" do
|
||||
# Test scalar param
|
||||
describe aws_config_delivery_channel(fixtures['delivery_channel_01']) do
|
||||
it { should exist }
|
||||
end
|
||||
|
||||
# Test hash parameter
|
||||
describe aws_config_delivery_channel(channel_name: fixtures['delivery_channel_01']) do
|
||||
it { should exist }
|
||||
end
|
||||
|
||||
# Test recorder that doesnt exist
|
||||
describe aws_config_delivery_channel(channel_name: 'NonExistentChannel') do
|
||||
it { should_not exist }
|
||||
end
|
||||
end
|
||||
|
||||
#------------------- Properties -------------------#
|
||||
control "aws_config_delivery_channel properties" do
|
||||
describe aws_config_delivery_channel(fixtures['delivery_channel_01']) do
|
||||
its('s3_bucket_name') { should eq fixtures['s3_bucket_for_delivery_channel'] }
|
||||
its('s3_key_prefix') { should eq nil }
|
||||
its('sns_topic_arn') { should eq fixtures['sns_topic_for_delivery_channel_arn'] }
|
||||
its('delivery_frequency_in_hours') { should eq 24 }
|
||||
its('delivery_frequency_in_hours') { should be > 3 }
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue