Low RDS Backup Retention Period

  • Query id: e649a218-d099-4550-86a4-1231e1fcb60d
  • Query name: Low RDS Backup Retention Period
  • Platform: CloudFormation
  • Severity: Low
  • Category: Backup
  • CWE: 778
  • URL: Github

Description

AWS RDS backup retention policy should be at least 7 days
Documentation

Code samples

Code samples with security vulnerabilities

Positive test num. 1 - yaml file
AWSTemplateFormatVersion: "2010-09-09"
Description: Creates RDS Cluster
Parameters:
  PMDatabaseEngine:
    Type: String
    Default: "MySQL"
    Description: "Database engine, Aurora, MySQL or PostgreSQL"
  PMRDSSG:
    Description: "Select the Security Group to use for the ELB"
    Type: "AWS::EC2::SecurityGroup::Id"
  PMDatabaseEngineVer:
    Type: String
    Description: "Database engine ver"
  PMDatabaseUsername:
    NoEcho: 'true'
    Type: String
    Description: "Database admin account name"
  PMDatabasePassword:
    NoEcho: 'true'
    Type: String
    Description: "Database admin account password"
  PMDBClusterParameterGroupName:
    Description: "Db Parameter Groupname"
    Type: String
  PMDatabaseInstanceClass:
    Type: String
    Default: "db.t2.micro"
    Description: "Database instance class"
  PMPrivateSubnets:
    Description: "Subnets to launch instances into"
    Type: "List<AWS::EC2::Subnet::Id>"
  PMServerEnv:
    Description: "Server Environment name."
    ConstraintDescription: "Choose an Environment from the drop down"
    Type: String
  PMDBClusterIdentifier:
    Description: "Db Cluster Name."
    Type: String

Resources:
  DatabaseCluster:
    Type: "AWS::RDS::DBCluster"
    Properties:
      VpcSecurityGroupIds:
      - Ref: "PMRDSSG"
      Engine: !Ref "PMDatabaseEngine"
      EngineVersion: !Ref "PMDatabaseEngineVer"
      MasterUsername: !Ref "PMDatabaseUsername"
      MasterUserPassword: !Ref "PMDatabasePassword"
      DBClusterParameterGroupName: !Ref "RDSDBClusterParameterGroup"
      StorageEncrypted: true
      BackupRetentionPeriod: 3
      PreferredBackupWindow: '12:00-13:00'
      PreferredMaintenanceWindow: 'mon:13:00-mon:14:00'

  Database1:
    Type: "AWS::RDS::DBInstance"
    Properties:
      Engine: !Ref "PMDatabaseEngine"
      DBClusterIdentifier: !Ref "DatabaseCluster"
      DBInstanceClass: !Ref "PMDatabaseInstanceClass"
      DBSubnetGroupName: !Ref "DbSubnetGroup"
      DBInstanceIdentifier: !Sub "${PMDBClusterIdentifier}-db1"

  Database2:
    Type: "AWS::RDS::DBInstance"
    Properties:
      Engine: !Ref "PMDatabaseEngine"
      DBClusterIdentifier: !Ref "DatabaseCluster"
      DBInstanceClass: !Ref "PMDatabaseInstanceClass"
      DBSubnetGroupName: !Ref "DbSubnetGroup"
      DBInstanceIdentifier: !Sub "${PMDBClusterIdentifier}-db2"

  DbSubnetGroup:
    Type: "AWS::RDS::DBSubnetGroup"
    Properties:
      DBSubnetGroupDescription: !Sub "${PMServerEnv} RDS DB subnet group"
      SubnetIds:
        Ref: "PMPrivateSubnets"

  RDSDBClusterParameterGroup:
    Type: "AWS::RDS::DBClusterParameterGroup"
    Properties:
      Description: "CloudFormation Sample Aurora Cluster Parameter Group"
      Family: !Ref "PMDBClusterParameterGroupName"
      Parameters:
        time_zone: "UTC"
        collation_connection: "utf8_general_ci"
        character_set_database: "utf8"

Outputs:
  RdsDbId:
    Description: "RDS Database Cluster ID"
    Value: !Ref "DatabaseCluster"
  RdsEndpointAdd:
    Description: "RDS Database Endpoint"
    Value: !GetAtt "DatabaseCluster.Endpoint.Address"
  RdsReadEndpointAdd:
    Description: "RDS Read Database Endpoint"
    Value: !GetAtt "DatabaseCluster.ReadEndpoint.Address"
  RdsEndpointPort:
    Description: "RDS Database Port"
    Value: !GetAtt "DatabaseCluster.Endpoint.Port"
  DbUser:
    Description: "RDS Database admin account user"
    Value: !Ref "PMDatabaseUsername"
  DbPassword:
    Description: "RDS Database admin account password"
    Value: !Ref "PMDatabasePassword"
Positive test num. 2 - yaml file
AWSTemplateFormatVersion: 2010-09-09
Description: RDS Storage Encrypted
Parameters:
  SourceDBInstanceIdentifier:
    Type: String
  DBInstanceType:
    Type: String
  SourceRegion:
    Type: String
Resources:
  MyKey:
    Type: "AWS::KMS::Key"
    Properties:
      KeyPolicy:
        Version: 2012-10-17
        Id: key-default-1
        Statement:
          - Sid: Enable IAM User Permissions
            Effect: Allow
            Principal:
              AWS: !Join
                - ""
                - - "arn:aws:iam::"
                  - !Ref "AWS::AccountId"
                  - ":root"
            Action: "kms:*"
            Resource: "*"
  MyDBSmall:
    Type: "AWS::RDS::DBInstance"
    Properties:
      DBInstanceClass: !Ref DBInstanceType
      SourceDBInstanceIdentifier: !Ref SourceDBInstanceIdentifier
      SourceRegion: !Ref SourceRegion
      KmsKeyId: !Ref MyKey
      BackupRetentionPeriod: 6
Outputs:
  InstanceId:
    Description: InstanceId of the newly created RDS Instance
    Value: !Ref MyDBSmall
Positive test num. 3 - yaml file
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  DBUser:
    NoEcho: true
    Description: The database admin account username
    Type: String
    MinLength: 1
    MaxLength: 16
    AllowedPattern: "[a-zA-Z][a-zA-Z0-9]*"
    ConstraintDescription: must begin with a letter and contain only alphanumeric characters.
  DBPassword:
    NoEcho: true
    Description: The database admin account password
    Type: String
    MinLength: 1
    MaxLength: 41
    AllowedPattern: "[a-zA-Z0-9]*"
    ConstraintDescription: must contain only alphanumeric characters.
Resources:
  MyDB:
    Type: "AWS::RDS::DBInstance"
    Properties:
      AllocatedStorage: '5'
      DBInstanceClass: db.t2.small
      Engine: MySQL
      EngineVersion: '5.5'
      MasterUsername: !Ref DBUser
      MasterUserPassword: !Ref DBPassword
      DBParameterGroupName: !Ref MyRDSParamGroup
  MyRDSParamGroup:
    Type: "AWS::RDS::DBParameterGroup"
    Properties:
      Family: MySQL5.5
      Description: CloudFormation Sample Database Parameter Group
      Parameters:
        autocommit: '1'
        general_log: '1'
        old_passwords: '0'

Positive test num. 4 - yaml file
AWSTemplateFormatVersion: "2010-09-09"
Description: Creates RDS Cluster
Parameters:
  PMDatabaseEngine:
    Type: String
    Default: "MySQL"
    Description: "Database engine, Aurora, MySQL or PostgreSQL"
  PMRDSSG:
    Description: "Select the Security Group to use for the ELB"
    Type: "AWS::EC2::SecurityGroup::Id"
  PMDatabaseEngineVer:
    Type: String
    Description: "Database engine ver"
  PMDatabaseUsername:
    NoEcho: 'true'
    Type: String
    Description: "Database admin account name"
  PMDatabasePassword:
    NoEcho: 'true'
    Type: String
    Description: "Database admin account password"
  PMDBClusterParameterGroupName:
    Description: "Db Parameter Groupname"
    Type: String
  PMDatabaseInstanceClass:
    Type: String
    Default: "db.t2.micro"
    Description: "Database instance class"
  PMPrivateSubnets:
    Description: "Subnets to launch instances into"
    Type: "List<AWS::EC2::Subnet::Id>"
  PMServerEnv:
    Description: "Server Environment name."
    ConstraintDescription: "Choose an Environment from the drop down"
    Type: String
  PMDBClusterIdentifier:
    Description: "Db Cluster Name."
    Type: String

Resources:
  BadDatabaseCluster:
    Type: "AWS::RDS::DBCluster"
    Properties:
      VpcSecurityGroupIds:
      - Ref: "PMRDSSG"
      Engine: !Ref "PMDatabaseEngine"
      EngineVersion: !Ref "PMDatabaseEngineVer"
      MasterUsername: !Ref "PMDatabaseUsername"
      MasterUserPassword: !Ref "PMDatabasePassword"
      DBClusterParameterGroupName: !Ref "RDSDBClusterParameterGroup"
      StorageEncrypted: true
      PreferredBackupWindow: '12:00-13:00'
      PreferredMaintenanceWindow: 'mon:13:00-mon:14:00'

  Database1:
    Type: "AWS::RDS::DBInstance"
    Properties:
      Engine: !Ref "PMDatabaseEngine"
      DBClusterIdentifier: !Ref "DatabaseCluster"
      DBInstanceClass: !Ref "PMDatabaseInstanceClass"
      DBSubnetGroupName: !Ref "DbSubnetGroup"
      DBInstanceIdentifier: !Sub "${PMDBClusterIdentifier}-db1"

  Database2:
    Type: "AWS::RDS::DBInstance"
    Properties:
      Engine: !Ref "PMDatabaseEngine"
      DBClusterIdentifier: !Ref "DatabaseCluster"
      DBInstanceClass: !Ref "PMDatabaseInstanceClass"
      DBSubnetGroupName: !Ref "DbSubnetGroup"
      DBInstanceIdentifier: !Sub "${PMDBClusterIdentifier}-db2"

  DbSubnetGroup:
    Type: "AWS::RDS::DBSubnetGroup"
    Properties:
      DBSubnetGroupDescription: !Sub "${PMServerEnv} RDS DB subnet group"
      SubnetIds:
        Ref: "PMPrivateSubnets"

  RDSDBClusterParameterGroup:
    Type: "AWS::RDS::DBClusterParameterGroup"
    Properties:
      Description: "CloudFormation Sample Aurora Cluster Parameter Group"
      Family: !Ref "PMDBClusterParameterGroupName"
      Parameters:
        time_zone: "UTC"
        collation_connection: "utf8_general_ci"
        character_set_database: "utf8"

Outputs:
  RdsDbId:
    Description: "RDS Database Cluster ID"
    Value: !Ref "DatabaseCluster"
  RdsEndpointAdd:
    Description: "RDS Database Endpoint"
    Value: !GetAtt "DatabaseCluster.Endpoint.Address"
  RdsReadEndpointAdd:
    Description: "RDS Read Database Endpoint"
    Value: !GetAtt "DatabaseCluster.ReadEndpoint.Address"
  RdsEndpointPort:
    Description: "RDS Database Port"
    Value: !GetAtt "DatabaseCluster.Endpoint.Port"
  DbUser:
    Description: "RDS Database admin account user"
    Value: !Ref "PMDatabaseUsername"
  DbPassword:
    Description: "RDS Database admin account password"
    Value: !Ref "PMDatabasePassword"
Positive test num. 5 - json file
{
  "Outputs": {
    "RdsDbId": {
      "Description": "RDS Database Cluster ID",
      "Value": "DatabaseCluster"
    },
    "RdsEndpointAdd": {
      "Description": "RDS Database Endpoint",
      "Value": "DatabaseCluster.Endpoint.Address"
    },
    "RdsReadEndpointAdd": {
      "Description": "RDS Read Database Endpoint",
      "Value": "DatabaseCluster.ReadEndpoint.Address"
    },
    "RdsEndpointPort": {
      "Description": "RDS Database Port",
      "Value": "DatabaseCluster.Endpoint.Port"
    },
    "DbUser": {
      "Description": "RDS Database admin account user",
      "Value": "PMDatabaseUsername"
    },
    "DbPassword": {
      "Description": "RDS Database admin account password",
      "Value": "PMDatabasePassword"
    }
  },
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Creates RDS Cluster",
  "Parameters": {
    "PMRDSSG": {
      "Description": "Select the Security Group to use for the ELB",
      "Type": "AWS::EC2::SecurityGroup::Id"
    },
    "PMPrivateSubnets": {
      "Description": "Subnets to launch instances into",
      "Type": "List\u003cAWS::EC2::Subnet::Id\u003e"
    },
    "PMServerEnv": {
      "Description": "Server Environment name.",
      "ConstraintDescription": "Choose an Environment from the drop down",
      "Type": "String"
    },
    "PMDBClusterIdentifier": {
      "Type": "String",
      "Description": "Db Cluster Name."
    },
    "PMDBClusterParameterGroupName": {
      "Description": "Db Parameter Groupname",
      "Type": "String"
    },
    "PMDatabaseInstanceClass": {
      "Type": "String",
      "Default": "db.t2.micro",
      "Description": "Database instance class"
    },
    "PMDatabaseEngine": {
      "Type": "String",
      "Default": "MySQL",
      "Description": "Database engine, Aurora, MySQL or PostgreSQL"
    },
    "PMDatabaseEngineVer": {
      "Type": "String",
      "Description": "Database engine ver"
    },
    "PMDatabaseUsername": {
      "NoEcho": "true",
      "Type": "String",
      "Description": "Database admin account name"
    },
    "PMDatabasePassword": {
      "Description": "Database admin account password",
      "NoEcho": "true",
      "Type": "String"
    }
  },
  "Resources": {
    "Database2": {
      "Type": "AWS::RDS::DBInstance",
      "Properties": {
        "Engine": "PMDatabaseEngine",
        "DBClusterIdentifier": "DatabaseCluster",
        "DBInstanceClass": "PMDatabaseInstanceClass",
        "DBSubnetGroupName": "DbSubnetGroup",
        "DBInstanceIdentifier": "${PMDBClusterIdentifier}-db2"
      }
    },
    "DbSubnetGroup": {
      "Type": "AWS::RDS::DBSubnetGroup",
      "Properties": {
        "DBSubnetGroupDescription": "${PMServerEnv} RDS DB subnet group",
        "SubnetIds": {
          "Ref": "PMPrivateSubnets"
        }
      }
    },
    "RDSDBClusterParameterGroup": {
      "Properties": {
        "Description": "CloudFormation Sample Aurora Cluster Parameter Group",
        "Family": "PMDBClusterParameterGroupName",
        "Parameters": {
          "time_zone": "UTC",
          "collation_connection": "utf8_general_ci",
          "character_set_database": "utf8"
        }
      },
      "Type": "AWS::RDS::DBClusterParameterGroup"
    },
    "DatabaseCluster": {
      "Type": "AWS::RDS::DBCluster",
      "Properties": {
        "StorageEncrypted": true,
        "BackupRetentionPeriod": 3,
        "MasterUsername": "PMDatabaseUsername",
        "MasterUserPassword": "PMDatabasePassword",
        "DBClusterParameterGroupName": "RDSDBClusterParameterGroup",
        "PreferredBackupWindow": "12:00-13:00",
        "PreferredMaintenanceWindow": "mon:13:00-mon:14:00",
        "VpcSecurityGroupIds": [
          {
            "Ref": "PMRDSSG"
          }
        ],
        "Engine": "PMDatabaseEngine",
        "EngineVersion": "PMDatabaseEngineVer"
      }
    },
    "Database1": {
      "Type": "AWS::RDS::DBInstance",
      "Properties": {
        "DBInstanceIdentifier": "${PMDBClusterIdentifier}-db1",
        "Engine": "PMDatabaseEngine",
        "DBClusterIdentifier": "DatabaseCluster",
        "DBInstanceClass": "PMDatabaseInstanceClass",
        "DBSubnetGroupName": "DbSubnetGroup"
      }
    }
  }
}
Positive test num. 6 - json file
{
  "Outputs": {
    "InstanceId": {
      "Description": "InstanceId of the newly created RDS Instance",
      "Value": "MyDBSmall"
    }
  },
  "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z",
  "Description": "RDS Storage Encrypted",
  "Parameters": {
    "SourceDBInstanceIdentifier": {
      "Type": "String"
    },
    "DBInstanceType": {
      "Type": "String"
    },
    "SourceRegion": {
      "Type": "String"
    }
  },
  "Resources": {
    "MyKey": {
      "Type": "AWS::KMS::Key",
      "Properties": {
        "KeyPolicy": {
          "Version": "2012-10-17T00:00:00Z",
          "Id": "key-default-1",
          "Statement": [
            {
              "Action": "kms:*",
              "Resource": "*",
              "Sid": "Enable IAM User Permissions",
              "Effect": "Allow",
              "Principal": {
                "AWS": [
                  "",
                  [
                    "arn:aws:iam::",
                    "AWS::AccountId",
                    ":root"
                  ]
                ]
              }
            }
          ]
        }
      }
    },
    "MyDBSmall": {
      "Type": "AWS::RDS::DBInstance",
      "Properties": {
        "SourceDBInstanceIdentifier": "SourceDBInstanceIdentifier",
        "SourceRegion": "SourceRegion",
        "KmsKeyId": "MyKey",
        "BackupRetentionPeriod": 6,
        "DBInstanceClass": "DBInstanceType"
      }
    }
  }
}
Positive test num. 7 - json file
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Parameters": {
    "DBUser": {
      "AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*",
      "ConstraintDescription": "must begin with a letter and contain only alphanumeric characters.",
      "NoEcho": true,
      "Description": "The database admin account username",
      "Type": "String",
      "MinLength": 1,
      "MaxLength": 16
    },
    "DBPassword": {
      "AllowedPattern": "[a-zA-Z0-9]*",
      "ConstraintDescription": "must contain only alphanumeric characters.",
      "NoEcho": true,
      "Description": "The database admin account password",
      "Type": "String",
      "MinLength": 1,
      "MaxLength": 41
    }
  },
  "Resources": {
    "MyDB": {
      "Type": "AWS::RDS::DBInstance",
      "Properties": {
        "AllocatedStorage": "5",
        "DBInstanceClass": "db.t2.small",
        "Engine": "MySQL",
        "EngineVersion": "5.5",
        "MasterUsername": "DBUser",
        "MasterUserPassword": "DBPassword",
        "DBParameterGroupName": "MyRDSParamGroup"
      }
    },
    "MyRDSParamGroup": {
      "Type": "AWS::RDS::DBParameterGroup",
      "Properties": {
        "Family": "MySQL5.5",
        "Description": "CloudFormation Sample Database Parameter Group",
        "Parameters": {
          "general_log": "1",
          "old_passwords": "0",
          "autocommit": "1"
        }
      }
    }
  }
}
Positive test num. 8 - json file
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Creates RDS Cluster",
  "Parameters": {
    "PMDatabaseEngineVer": {
      "Type": "String",
      "Description": "Database engine ver"
    },
    "PMDatabaseUsername": {
      "NoEcho": "true",
      "Type": "String",
      "Description": "Database admin account name"
    },
    "PMDatabasePassword": {
      "Type": "String",
      "Description": "Database admin account password",
      "NoEcho": "true"
    },
    "PMDBClusterParameterGroupName": {
      "Description": "Db Parameter Groupname",
      "Type": "String"
    },
    "PMDBClusterIdentifier": {
      "Description": "Db Cluster Name.",
      "Type": "String"
    },
    "PMDatabaseEngine": {
      "Type": "String",
      "Default": "MySQL",
      "Description": "Database engine, Aurora, MySQL or PostgreSQL"
    },
    "PMRDSSG": {
      "Description": "Select the Security Group to use for the ELB",
      "Type": "AWS::EC2::SecurityGroup::Id"
    },
    "PMDatabaseInstanceClass": {
      "Type": "String",
      "Default": "db.t2.micro",
      "Description": "Database instance class"
    },
    "PMPrivateSubnets": {
      "Description": "Subnets to launch instances into",
      "Type": "List\u003cAWS::EC2::Subnet::Id\u003e"
    },
    "PMServerEnv": {
      "ConstraintDescription": "Choose an Environment from the drop down",
      "Type": "String",
      "Description": "Server Environment name."
    }
  },
  "Resources": {
    "BadDatabaseCluster": {
      "Type": "AWS::RDS::DBCluster",
      "Properties": {
        "PreferredMaintenanceWindow": "mon:13:00-mon:14:00",
        "VpcSecurityGroupIds": [
          {
            "Ref": "PMRDSSG"
          }
        ],
        "EngineVersion": "PMDatabaseEngineVer",
        "MasterUsername": "PMDatabaseUsername",
        "StorageEncrypted": true,
        "Engine": "PMDatabaseEngine",
        "MasterUserPassword": "PMDatabasePassword",
        "DBClusterParameterGroupName": "RDSDBClusterParameterGroup",
        "PreferredBackupWindow": "12:00-13:00"
      }
    },
    "Database1": {
      "Type": "AWS::RDS::DBInstance",
      "Properties": {
        "Engine": "PMDatabaseEngine",
        "DBClusterIdentifier": "DatabaseCluster",
        "DBInstanceClass": "PMDatabaseInstanceClass",
        "DBSubnetGroupName": "DbSubnetGroup",
        "DBInstanceIdentifier": "${PMDBClusterIdentifier}-db1"
      }
    },
    "Database2": {
      "Type": "AWS::RDS::DBInstance",
      "Properties": {
        "Engine": "PMDatabaseEngine",
        "DBClusterIdentifier": "DatabaseCluster",
        "DBInstanceClass": "PMDatabaseInstanceClass",
        "DBSubnetGroupName": "DbSubnetGroup",
        "DBInstanceIdentifier": "${PMDBClusterIdentifier}-db2"
      }
    },
    "DbSubnetGroup": {
      "Type": "AWS::RDS::DBSubnetGroup",
      "Properties": {
        "DBSubnetGroupDescription": "${PMServerEnv} RDS DB subnet group",
        "SubnetIds": {
          "Ref": "PMPrivateSubnets"
        }
      }
    },
    "RDSDBClusterParameterGroup": {
      "Type": "AWS::RDS::DBClusterParameterGroup",
      "Properties": {
        "Description": "CloudFormation Sample Aurora Cluster Parameter Group",
        "Family": "PMDBClusterParameterGroupName",
        "Parameters": {
          "collation_connection": "utf8_general_ci",
          "character_set_database": "utf8",
          "time_zone": "UTC"
        }
      }
    }
  },
  "Outputs": {
    "RdsReadEndpointAdd": {
      "Value": "DatabaseCluster.ReadEndpoint.Address",
      "Description": "RDS Read Database Endpoint"
    },
    "RdsEndpointPort": {
      "Description": "RDS Database Port",
      "Value": "DatabaseCluster.Endpoint.Port"
    },
    "DbUser": {
      "Value": "PMDatabaseUsername",
      "Description": "RDS Database admin account user"
    },
    "DbPassword": {
      "Description": "RDS Database admin account password",
      "Value": "PMDatabasePassword"
    },
    "RdsDbId": {
      "Description": "RDS Database Cluster ID",
      "Value": "DatabaseCluster"
    },
    "RdsEndpointAdd": {
      "Description": "RDS Database Endpoint",
      "Value": "DatabaseCluster.Endpoint.Address"
    }
  }
}

Code samples without security vulnerabilities

Negative test num. 1 - yaml file
AWSTemplateFormatVersion: "2010-09-09"
Description: Creates RDS Cluster
Parameters:
  PMDatabaseEngine:
    Type: String
    Default: "MySQL"
    Description: "Database engine, Aurora, MySQL or PostgreSQL"
  PMRDSSG:
    Description: "Select the Security Group to use for the ELB"
    Type: "AWS::EC2::SecurityGroup::Id"
  PMDatabaseEngineVer:
    Type: String
    Description: "Database engine ver"
  PMDatabaseUsername:
    NoEcho: 'true'
    Type: String
    Description: "Database admin account name"
  PMDatabasePassword:
    NoEcho: 'true'
    Type: String
    Description: "Database admin account password"
  PMDBClusterParameterGroupName:
    Description: "Db Parameter Groupname"
    Type: String
  PMDatabaseInstanceClass:
    Type: String
    Default: "db.t2.micro"
    Description: "Database instance class"
  PMPrivateSubnets:
    Description: "Subnets to launch instances into"
    Type: "List<AWS::EC2::Subnet::Id>"
  PMServerEnv:
    Description: "Server Environment name."
    ConstraintDescription: "Choose an Environment from the drop down"
    Type: String
  PMDBClusterIdentifier:
    Description: "Db Cluster Name."
    Type: String

Resources:
  DatabaseCluster:
    Type: "AWS::RDS::DBCluster"
    Properties:
      VpcSecurityGroupIds:
      - Ref: "PMRDSSG"
      Engine: !Ref "PMDatabaseEngine"
      EngineVersion: !Ref "PMDatabaseEngineVer"
      MasterUsername: !Ref "PMDatabaseUsername"
      MasterUserPassword: !Ref "PMDatabasePassword"
      DBClusterParameterGroupName: !Ref "RDSDBClusterParameterGroup"
      StorageEncrypted: true
      BackupRetentionPeriod: 16
      PreferredBackupWindow: '12:00-13:00'
      PreferredMaintenanceWindow: 'mon:13:00-mon:14:00'

  Database1:
    Type: "AWS::RDS::DBInstance"
    Properties:
      Engine: !Ref "PMDatabaseEngine"
      DBClusterIdentifier: !Ref "DatabaseCluster"
      DBInstanceClass: !Ref "PMDatabaseInstanceClass"
      DBSubnetGroupName: !Ref "DbSubnetGroup"
      DBInstanceIdentifier: !Sub "${PMDBClusterIdentifier}-db1"

  Database2:
    Type: "AWS::RDS::DBInstance"
    Properties:
      Engine: !Ref "PMDatabaseEngine"
      DBClusterIdentifier: !Ref "DatabaseCluster"
      DBInstanceClass: !Ref "PMDatabaseInstanceClass"
      DBSubnetGroupName: !Ref "DbSubnetGroup"
      DBInstanceIdentifier: !Sub "${PMDBClusterIdentifier}-db2"

  DbSubnetGroup:
    Type: "AWS::RDS::DBSubnetGroup"
    Properties:
      DBSubnetGroupDescription: !Sub "${PMServerEnv} RDS DB subnet group"
      SubnetIds:
        Ref: "PMPrivateSubnets"

  RDSDBClusterParameterGroup:
    Type: "AWS::RDS::DBClusterParameterGroup"
    Properties:
      Description: "CloudFormation Sample Aurora Cluster Parameter Group"
      Family: !Ref "PMDBClusterParameterGroupName"
      Parameters:
        time_zone: "UTC"
        collation_connection: "utf8_general_ci"
        character_set_database: "utf8"

Outputs:
  RdsDbId:
    Description: "RDS Database Cluster ID"
    Value: !Ref "DatabaseCluster"
  RdsEndpointAdd:
    Description: "RDS Database Endpoint"
    Value: !GetAtt "DatabaseCluster.Endpoint.Address"
  RdsReadEndpointAdd:
    Description: "RDS Read Database Endpoint"
    Value: !GetAtt "DatabaseCluster.ReadEndpoint.Address"
  RdsEndpointPort:
    Description: "RDS Database Port"
    Value: !GetAtt "DatabaseCluster.Endpoint.Port"
  DbUser:
    Description: "RDS Database admin account user"
    Value: !Ref "PMDatabaseUsername"
  DbPassword:
    Description: "RDS Database admin account password"
    Value: !Ref "PMDatabasePassword"
Negative test num. 2 - yaml file
AWSTemplateFormatVersion: 2010-09-09
Description: RDS Storage Encrypted
Parameters:
  SourceDBInstanceIdentifier:
    Type: String
  DBInstanceType:
    Type: String
  SourceRegion:
    Type: String
Resources:
  MyKey:
    Type: "AWS::KMS::Key"
    Properties:
      KeyPolicy:
        Version: 2012-10-17
        Id: key-default-1
        Statement:
          - Sid: Enable IAM User Permissions
            Effect: Allow
            Principal:
              AWS: !Join
                - ""
                - - "arn:aws:iam::"
                  - !Ref "AWS::AccountId"
                  - ":root"
            Action: "kms:*"
            Resource: "*"
  MyDBSmall:
    Type: "AWS::RDS::DBInstance"
    Properties:
      DBInstanceClass: !Ref DBInstanceType
      SourceDBInstanceIdentifier: !Ref SourceDBInstanceIdentifier
      SourceRegion: !Ref SourceRegion
      KmsKeyId: !Ref MyKey
      BackupRetentionPeriod: 7
Outputs:
  InstanceId:
    Description: InstanceId of the newly created RDS Instance
    Value: !Ref MyDBSmall
Negative test num. 3 - yaml file
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  DBUser:
    NoEcho: true
    Description: The database admin account username
    Type: String
    MinLength: 1
    MaxLength: 16
    AllowedPattern: "[a-zA-Z][a-zA-Z0-9]*"
    ConstraintDescription: must begin with a letter and contain only alphanumeric characters.
  DBPassword:
    NoEcho: true
    Description: The database admin account password
    Type: String
    MinLength: 1
    MaxLength: 41
    AllowedPattern: "[a-zA-Z0-9]*"
    ConstraintDescription: must contain only alphanumeric characters.
Resources:
  MyDB:
    Type: "AWS::RDS::DBInstance"
    Properties:
      AllocatedStorage: '5'
      DBInstanceClass: db.t2.small
      Engine: MySQL
      EngineVersion: '5.5'
      MasterUsername: !Ref DBUser
      MasterUserPassword: !Ref DBPassword
      DBParameterGroupName: !Ref MyRDSParamGroup
      BackupRetentionPeriod: 10
  MyRDSParamGroup:
    Type: "AWS::RDS::DBParameterGroup"
    Properties:
      Family: MySQL5.5
      Description: CloudFormation Sample Database Parameter Group
      Parameters:
        autocommit: '1'
        general_log: '1'
        old_passwords: '0'

Negative test num. 4 - json file
{
  "Parameters": {
    "PMDatabaseEngineVer": {
      "Description": "Database engine ver",
      "Type": "String"
    },
    "PMDatabaseUsername": {
      "NoEcho": "true",
      "Type": "String",
      "Description": "Database admin account name"
    },
    "PMDatabaseInstanceClass": {
      "Type": "String",
      "Default": "db.t2.micro",
      "Description": "Database instance class"
    },
    "PMRDSSG": {
      "Description": "Select the Security Group to use for the ELB",
      "Type": "AWS::EC2::SecurityGroup::Id"
    },
    "PMDatabasePassword": {
      "Description": "Database admin account password",
      "NoEcho": "true",
      "Type": "String"
    },
    "PMDBClusterParameterGroupName": {
      "Type": "String",
      "Description": "Db Parameter Groupname"
    },
    "PMPrivateSubnets": {
      "Description": "Subnets to launch instances into",
      "Type": "List\u003cAWS::EC2::Subnet::Id\u003e"
    },
    "PMServerEnv": {
      "ConstraintDescription": "Choose an Environment from the drop down",
      "Type": "String",
      "Description": "Server Environment name."
    },
    "PMDBClusterIdentifier": {
      "Type": "String",
      "Description": "Db Cluster Name."
    },
    "PMDatabaseEngine": {
      "Type": "String",
      "Default": "MySQL",
      "Description": "Database engine, Aurora, MySQL or PostgreSQL"
    }
  },
  "Resources": {
    "DatabaseCluster": {
      "Properties": {
        "PreferredMaintenanceWindow": "mon:13:00-mon:14:00",
        "Engine": "PMDatabaseEngine",
        "StorageEncrypted": true,
        "MasterUsername": "PMDatabaseUsername",
        "MasterUserPassword": "PMDatabasePassword",
        "DBClusterParameterGroupName": "RDSDBClusterParameterGroup",
        "BackupRetentionPeriod": 16,
        "PreferredBackupWindow": "12:00-13:00",
        "VpcSecurityGroupIds": [
          {
            "Ref": "PMRDSSG"
          }
        ],
        "EngineVersion": "PMDatabaseEngineVer"
      },
      "Type": "AWS::RDS::DBCluster"
    },
    "Database1": {
      "Type": "AWS::RDS::DBInstance",
      "Properties": {
        "Engine": "PMDatabaseEngine",
        "DBClusterIdentifier": "DatabaseCluster",
        "DBInstanceClass": "PMDatabaseInstanceClass",
        "DBSubnetGroupName": "DbSubnetGroup",
        "DBInstanceIdentifier": "${PMDBClusterIdentifier}-db1"
      }
    },
    "Database2": {
      "Type": "AWS::RDS::DBInstance",
      "Properties": {
        "DBInstanceIdentifier": "${PMDBClusterIdentifier}-db2",
        "Engine": "PMDatabaseEngine",
        "DBClusterIdentifier": "DatabaseCluster",
        "DBInstanceClass": "PMDatabaseInstanceClass",
        "DBSubnetGroupName": "DbSubnetGroup"
      }
    },
    "DbSubnetGroup": {
      "Type": "AWS::RDS::DBSubnetGroup",
      "Properties": {
        "DBSubnetGroupDescription": "${PMServerEnv} RDS DB subnet group",
        "SubnetIds": {
          "Ref": "PMPrivateSubnets"
        }
      }
    },
    "RDSDBClusterParameterGroup": {
      "Type": "AWS::RDS::DBClusterParameterGroup",
      "Properties": {
        "Description": "CloudFormation Sample Aurora Cluster Parameter Group",
        "Family": "PMDBClusterParameterGroupName",
        "Parameters": {
          "time_zone": "UTC",
          "collation_connection": "utf8_general_ci",
          "character_set_database": "utf8"
        }
      }
    }
  },
  "Outputs": {
    "RdsEndpointAdd": {
      "Value": "DatabaseCluster.Endpoint.Address",
      "Description": "RDS Database Endpoint"
    },
    "RdsReadEndpointAdd": {
      "Description": "RDS Read Database Endpoint",
      "Value": "DatabaseCluster.ReadEndpoint.Address"
    },
    "RdsEndpointPort": {
      "Description": "RDS Database Port",
      "Value": "DatabaseCluster.Endpoint.Port"
    },
    "DbUser": {
      "Description": "RDS Database admin account user",
      "Value": "PMDatabaseUsername"
    },
    "DbPassword": {
      "Value": "PMDatabasePassword",
      "Description": "RDS Database admin account password"
    },
    "RdsDbId": {
      "Description": "RDS Database Cluster ID",
      "Value": "DatabaseCluster"
    }
  },
  "AWSTemplateFormatVersion": "2010-09-09",
  "Description": "Creates RDS Cluster"
}
Negative test num. 5 - json file
{
  "Parameters": {
    "SourceDBInstanceIdentifier": {
      "Type": "String"
    },
    "DBInstanceType": {
      "Type": "String"
    },
    "SourceRegion": {
      "Type": "String"
    }
  },
  "Resources": {
    "MyKey": {
      "Type": "AWS::KMS::Key",
      "Properties": {
        "KeyPolicy": {
          "Version": "2012-10-17T00:00:00Z",
          "Id": "key-default-1",
          "Statement": [
            {
              "Principal": {
                "AWS": [
                  "",
                  [
                    "arn:aws:iam::",
                    "AWS::AccountId",
                    ":root"
                  ]
                ]
              },
              "Action": "kms:*",
              "Resource": "*",
              "Sid": "Enable IAM User Permissions",
              "Effect": "Allow"
            }
          ]
        }
      }
    },
    "MyDBSmall": {
      "Type": "AWS::RDS::DBInstance",
      "Properties": {
        "SourceDBInstanceIdentifier": "SourceDBInstanceIdentifier",
        "SourceRegion": "SourceRegion",
        "KmsKeyId": "MyKey",
        "BackupRetentionPeriod": 7,
        "DBInstanceClass": "DBInstanceType"
      }
    }
  },
  "Outputs": {
    "InstanceId": {
      "Description": "InstanceId of the newly created RDS Instance",
      "Value": "MyDBSmall"
    }
  },
  "AWSTemplateFormatVersion": "2010-09-09T00:00:00Z",
  "Description": "RDS Storage Encrypted"
}
Negative test num. 6 - json file
{
  "AWSTemplateFormatVersion": "2010-09-09",
  "Parameters": {
    "DBUser": {
      "MinLength": 1,
      "MaxLength": 16,
      "AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*",
      "ConstraintDescription": "must begin with a letter and contain only alphanumeric characters.",
      "NoEcho": true,
      "Description": "The database admin account username",
      "Type": "String"
    },
    "DBPassword": {
      "MinLength": 1,
      "MaxLength": 41,
      "AllowedPattern": "[a-zA-Z0-9]*",
      "ConstraintDescription": "must contain only alphanumeric characters.",
      "NoEcho": true,
      "Description": "The database admin account password",
      "Type": "String"
    }
  },
  "Resources": {
    "MyDB": {
      "Type": "AWS::RDS::DBInstance",
      "Properties": {
        "EngineVersion": "5.5",
        "MasterUsername": "DBUser",
        "MasterUserPassword": "DBPassword",
        "DBParameterGroupName": "MyRDSParamGroup",
        "BackupRetentionPeriod": 10,
        "AllocatedStorage": "5",
        "DBInstanceClass": "db.t2.small",
        "Engine": "MySQL"
      }
    },
    "MyRDSParamGroup": {
      "Type": "AWS::RDS::DBParameterGroup",
      "Properties": {
        "Family": "MySQL5.5",
        "Description": "CloudFormation Sample Database Parameter Group",
        "Parameters": {
          "autocommit": "1",
          "general_log": "1",
          "old_passwords": "0"
        }
      }
    }
  }
}