AWS CloudFormation template with ConfigRule
I'm new to AWS but already tried looking everywhere for this, and couldn't find a proper answer.
My aim is to create a CloudFormation template which forms a new stack, without assuming that AWS Config is already enabled. This template should define several more items, one of them should be a ConfigRule.
In order to achieve that, I found this template which seems fine, then tried to add a ConfigRule from one of these examples, into the same template file. But when I try to create a new stack from this combined template, I get this error:
You must create a configuration recorder before you can create or update a Config rule. (Service: AmazonConfig; Status Code: 400; Error Code: NoAvailableConfigurationRecorderException
Since the template file does define a configuration recorder, I'm not sure what's wrong with it. This is basically a copy of the linked template, and I marked with comments around the places which I added only in order to add some example config rule which should be created as part of the template:
AWSTemplateFormatVersion: 2010-09-09
Description: 'The AWS CloudFormation template creates KMS encryption keys for Config and S3, an encrypted S3 bucket, and enables Config for the account'
# added for configRule - start (1)
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: Configuration
Parameters:
- Frequency
ParameterLabels:
Frequency:
default: Frequency
Parameters:
Frequency:
Type: String
Default: 24hours
Description: Maximum rule execution frequency.
AllowedValues:
- 1hour
- 3hours
- 6hours
- 12hours
- 24hours
Mappings:
Settings:
FrequencyMap:
1hour : One_Hour
3hours : Three_Hours
6hours : Six_Hours
12hours : Twelve_Hours
24hours : TwentyFour_Hours
# added for configRule - end (#1)
Resources:
# added for configRule - start (2)
CheckForRootMFA:
Type: AWS::Config::ConfigRule
Properties:
Description: Checks whether the root user of your AWS account requires multi-factor authentication for console sign-in.
MaximumExecutionFrequency: !FindInMap
- Settings
- FrequencyMap
- !Ref Frequency
Source:
Owner: AWS
SourceIdentifier: ROOT_ACCOUNT_MFA_ENABLED
# added for configRule - end (2)
# KMS S3 Config Service encryption key
s3configKey:
Type: AWS::KMS::Key
Properties:
KeyPolicy:
Version: 2012-10-17
Id: key-s3config
Statement:
- Sid: Enable IAM User Permissions
Effect: Allow
Principal:
AWS: !Join
- ''
- - 'arn:aws:iam::'
- !Ref 'AWS::AccountId'
- ':root'
Action: 'kms:*'
Resource: '*'
s3configKeyAlias:
Type: AWS::KMS::Alias
Properties:
AliasName: alias/s3config
TargetKeyId:
Ref: s3configKey
# Build AWS Config Service S3 Bucket for Storage
AWSConfigS3Bucket:
Type: AWS::S3::Bucket
DeletionPolicy: Retain
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
KMSMasterKeyID: !Sub 'arn:aws:kms:${AWS::Region}:${AWS::AccountId}:${s3configKeyAlias}'
SSEAlgorithm: 'aws:kms'
# Build AWS Config Recorder
ConfigRecorder:
Type: 'AWS::Config::ConfigurationRecorder'
Properties:
Name: 'ConfigRecoder'
RecordingGroup:
AllSupported: true
IncludeGlobalResourceTypes: true
RoleARN: !GetAtt
- AWSIAM
- Arn
# Build IAM Role for Config
AWSIAM:
Type: 'AWS::IAM::Role'
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- config.amazonaws.com
Action:
- 'sts:AssumeRole'
ManagedPolicyArns:
- 'arn:aws:iam::aws:policy/service-role/AWSConfigRole'
Path: /
Policies:
- PolicyName: S3-access
PolicyDocument:
Statement:
- Effect: Allow
Action:
- 's3:PutObject'
Resource: !Join
- ''
- - 'arn:aws:s3:::'
- !Ref AWSConfigS3Bucket
- /AWSLogs/
- !Ref 'AWS::AccountId'
- /*
Condition:
StringLike:
's3:x-amz-acl': bucket-owner-full-control
- Effect: Allow
Action:
- 's3:GetBucketAcl'
Resource: !Join
- ''
- - 'arn:aws:s3:::'
- !Ref AWSConfigS3Bucket
# Create Config Delivery Channel
DeliveryChannel:
Type: 'AWS::Config::DeliveryChannel'
Properties:
S3BucketName: !Ref AWSConfigS3Bucket
Outputs:
S3KMSKeyAlias:
Description: 'S3 KMS Key Alias'
Value:
Ref: 's3configKeyAlias'
AWSIAM:
Description: 'IAM Role for Config'
Value:
Ref: 'AWSIAM'
AWSConfigS3Bucket:
Description: 'Encrypted S3 Bucket for Config Logs'
Value:
Ref: 'AWSConfigS3Bucket'
ConfigRecorder:
Description: 'Config Recorder'
Value:
Ref: 'ConfigRecorder'
DeliveryChannel:
Description: 'Config Delivery Channel'
Value:
Ref: 'DeliveryChannel'
Solution 1:
CloudFormation usually works out the correct order for deployment of components, but sometimes it gets it wrong. You can use the DependsOn attribute to give it a hint to say the Config Recorder must be created before the Config Rule. I'm not 100% sure this will help but it's worth a shot.
CheckForRootMFA:
DependsOn: ConfigRecorder
Type: AWS::Config::ConfigRule
Properties:
(etc)
Looking at my own Config templates I can see I create the following
- AWS::Config::ConfigurationRecorder
- AWS::Config::DeliveryChannel
- AWS::SNS::Topic
But I don't actually create config rules as I use AWS Security Hub which creates them for me.