mirror of
https://github.com/inspec/inspec
synced 2024-11-27 07:00:39 +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_cloudtrail_trails'
|
||||||
require 'resources/aws/aws_cloudwatch_alarm'
|
require 'resources/aws/aws_cloudwatch_alarm'
|
||||||
require 'resources/aws/aws_cloudwatch_log_metric_filter'
|
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_config_recorder'
|
||||||
require 'resources/aws/aws_ec2_instance'
|
require 'resources/aws/aws_ec2_instance'
|
||||||
require 'resources/aws/aws_iam_access_key'
|
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
|
|
@ -34,3 +34,80 @@ output "role_for_config_recorder_arn" {
|
||||||
output "config_recorder_name" {
|
output "config_recorder_name" {
|
||||||
value = "${aws_config_configuration_recorder.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