Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

When using aurora dbinstance make sure certain properties aren't used #1409

Merged
merged 1 commit into from
Mar 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions src/cfnlint/rules/resources/rds/AuroraDBInstanceProperties.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
"""
Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""
import six
from cfnlint.rules import CloudFormationLintRule
from cfnlint.rules import RuleMatch


class AuroraDBInstanceProperties(CloudFormationLintRule):
"""Aurora DB instances have a lot properties that can't be set and vice and versa"""
id = 'E3029'
shortdesc = 'Aurora instances don\'t require certain properties'
description = 'Certain properties are not reuqired when using the Aurora engine for AWS::RDS::DBInstance'
source_url = 'https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html'
tags = ['resources', 'rds']
aurora_not_required_props = [
'AllocatedStorage',
'BackupRetentionPeriod',
'CopyTagsToSnapshot',
'DeletionProtection',
'EnableIAMDatabaseAuthentication',
'MasterUserPassword',
'StorageEncrypted',
]
aurora_engines = [
'aurora',
'aurora-mysql',
'aurora-postgresql',
]

def __init__(self):
"""Init"""
super(AuroraDBInstanceProperties, self).__init__()
self.resource_property_types = ['AWS::RDS::DBInstance']

def check(self, properties, path, cfn):
"""Check itself"""
matches = []
property_sets = cfn.get_object_without_conditions(
properties, ['Engine'] + self.aurora_not_required_props)
for property_set in property_sets:
properties = property_set.get('Object')
scenario = property_set.get('Scenario')
engine_sets = properties.get_safe('Engine', type_t=six.string_types)
for engine, _ in engine_sets:
if engine in self.aurora_engines:
for prop in properties:
if prop in self.aurora_not_required_props:
path_prop = path[:] + [prop]
message = 'You cannot specify {} for Aurora AWS::RDS::DBInstance at {}'
if scenario is None:
matches.append(
RuleMatch(path_prop, message.format(prop, '/'.join(map(str, path_prop)))))
else:
scenario_text = ' and '.join(
['when condition "%s" is %s' % (k, v) for (k, v) in scenario.items()])
matches.append(
RuleMatch(path_prop, message.format(prop, '/'.join(map(str, path_prop)) + ' ' + scenario_text)))
return matches

def match_resource_properties(self, properties, _, path, cfn):
"""Match for sub properties"""
matches = []
matches.extend(self.check(properties, path, cfn))
return matches
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
AWSTemplateFormatVersion: 2010-09-09
Description: "RDS Storage Encrypted"
Parameters:
Engine:
Type: String
UseAurora:
Type: String
AllowedValues:
- "true"
- "false"
Conditions:
IsAurora:
Fn::Or:
- !Equals [!Ref Engine, "aurora"]
- !Equals [!Ref Engine, "aurora-mysql"]
- !Equals [!Ref Engine, "aurora-postgresql"]
IsAurora2: !Equals [!Ref UseAurora, "true"]
Resources:
MyDBSmall:
Type: "AWS::RDS::DBInstance"
Properties:
Engine: aurora
AllocatedStorage: "100"
DBInstanceClass: db.r3.2xlarge
StorageEncrypted: true
MyDbInstance2:
Type: "AWS::RDS::DBInstance"
Properties:
Engine: !Ref Engine
DBInstanceClass: db.r3.2xlarge
# While this is bad we can't determine the Engine so skipping
AllocatedStorage: !If [IsAurora, "100", !Ref "AWS::NoValue"]
MySqlInstance:
Type: "AWS::RDS::DBInstance"
Properties:
Engine: !If [IsAurora2, aurora-mysql, mysql]
DBInstanceClass: db.r3.2xlarge
# Since we can figure out the engine this one should fail
AllocatedStorage: !If [IsAurora2, "100", !Ref "AWS::NoValue"]
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
AWSTemplateFormatVersion: 2010-09-09
Description: "RDS Storage Encrypted"
Parameters:
Engine:
Type: String
UseAurora:
Type: String
AllowedValues:
- "true"
- "false"
Conditions:
IsAurora:
Fn::Or:
- !Equals [!Ref Engine, "aurora"]
- !Equals [!Ref Engine, "aurora-mysql"]
- !Equals [!Ref Engine, "aurora-postgresql"]
IsAurora2: !Equals [!Ref UseAurora, "true"]
Resources:
MyDbInstance1:
Type: "AWS::RDS::DBInstance"
Properties:
Engine: mysql
AllocatedStorage: "100"
DBInstanceClass: db.r3.2xlarge
StorageEncrypted: true
MyDbInstance2:
Type: "AWS::RDS::DBInstance"
Properties:
Engine: !Ref Engine
DBInstanceClass: db.r3.2xlarge
AllocatedStorage: !If [IsAurora, !Ref "AWS::NoValue", "100"]
MySqlInstance:
Type: "AWS::RDS::DBInstance"
Properties:
Engine: !If [IsAurora2, aurora-mysql, mysql]
DBInstanceClass: db.r3.2xlarge
AllocatedStorage: !If [IsAurora2, !Ref "AWS::NoValue", "100"]
27 changes: 27 additions & 0 deletions test/unit/rules/resources/rds/test_auroa_dbinstance_properties.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""
Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
SPDX-License-Identifier: MIT-0
"""
from test.unit.rules import BaseRuleTestCase
from cfnlint.rules.resources.rds.AuroraDBInstanceProperties import AuroraDBInstanceProperties # pylint: disable=E0401


class TestAuroraDBInstanceProperties(BaseRuleTestCase):
"""Test RDS Auror Auto Scaling Configurartion"""

def setUp(self):
"""Setup"""
super(TestAuroraDBInstanceProperties, self).setUp()
self.collection.register(AuroraDBInstanceProperties())
self.success_templates = [
'test/fixtures/templates/good/resources/rds/aurora_dbinstance_properties.yaml'
]

def test_file_positive(self):
"""Test Positive"""
self.helper_file_positive()

def test_file_negative_alias(self):
"""Test failure"""
self.helper_file_negative(
'test/fixtures/templates/bad/resources/rds/aurora_dbinstance_properties.yaml', 3)