1+ require 'yaml'
2+
3+ describe 'compiled component redshift' do
4+
5+ context 'cftest' do
6+ it 'compiles test' do
7+ expect ( system ( "cfhighlander cftest #{ @validate } --tests tests/redshift_federation_iam_role.test.yaml" ) ) . to be_truthy
8+ end
9+ end
10+
11+ let ( :template ) { YAML . load_file ( "#{ File . dirname ( __FILE__ ) } /../out/tests/redshift_federation_iam_role/redshift.compiled.yaml" ) }
12+
13+ context "Resource" do
14+
15+
16+ context "RedshiftLoggingS3Bucket" do
17+ let ( :resource ) { template [ "Resources" ] [ "RedshiftLoggingS3Bucket" ] }
18+
19+ it "is of type AWS::S3::Bucket" do
20+ expect ( resource [ "Type" ] ) . to eq ( "AWS::S3::Bucket" )
21+ end
22+
23+ it "to have property BucketName" do
24+ expect ( resource [ "Properties" ] [ "BucketName" ] ) . to eq ( { "Fn::Join" => [ "-" , [ "redshift" , "logs" , { "Ref" => "EnvironmentName" } , { "Ref" => "AWS::Region" } , { "Fn::Select" => [ 4 , { "Fn::Split" => [ "-" , { "Fn::Select" => [ 2 , { "Fn::Split" => [ "/" , { "Ref" => "AWS::StackId" } ] } ] } ] } ] } ] ] } )
25+ end
26+
27+ it "to have property BucketEncryption" do
28+ expect ( resource [ "Properties" ] [ "BucketEncryption" ] ) . to eq ( { "ServerSideEncryptionConfiguration" => [ { "ServerSideEncryptionByDefault" => { "SSEAlgorithm" => "AES256" } } ] } )
29+ end
30+
31+ it "to have property PublicAccessBlockConfiguration" do
32+ expect ( resource [ "Properties" ] [ "PublicAccessBlockConfiguration" ] ) . to eq ( { "BlockPublicAcls" => true , "BlockPublicPolicy" => true , "IgnorePublicAcls" => true , "RestrictPublicBuckets" => true } )
33+ end
34+
35+ it "to have property Tags" do
36+ expect ( resource [ "Properties" ] [ "Tags" ] ) . to eq ( [ { "Key" => "Environment" , "Value" => { "Ref" => "EnvironmentName" } } ] )
37+ end
38+
39+ end
40+
41+ context "RedshiftLoggingS3BucketPolicy" do
42+ let ( :resource ) { template [ "Resources" ] [ "RedshiftLoggingS3BucketPolicy" ] }
43+
44+ it "is of type AWS::S3::BucketPolicy" do
45+ expect ( resource [ "Type" ] ) . to eq ( "AWS::S3::BucketPolicy" )
46+ end
47+
48+ it "to have property Bucket" do
49+ expect ( resource [ "Properties" ] [ "Bucket" ] ) . to eq ( { "Ref" => "RedshiftLoggingS3Bucket" } )
50+ end
51+
52+ it "to have property PolicyDocument" do
53+ expect ( resource [ "Properties" ] [ "PolicyDocument" ] ) . to eq ( { "Statement" => [ { "Principal" => { "Service" => "redshift.amazonaws.com" } , "Action" => [ "s3:PutObject" , "s3:GetBucketAcl" ] , "Effect" => "Allow" , "Resource" => [ { "Fn::Sub" => "arn:aws:s3:::${RedshiftLoggingS3Bucket}" } , { "Fn::Sub" => "arn:aws:s3:::${RedshiftLoggingS3Bucket}/*" } ] } ] } )
54+ end
55+
56+ end
57+
58+ context "RedshiftIAMRole" do
59+ let ( :resource ) { template [ "Resources" ] [ "RedshiftIAMRole" ] }
60+
61+ it "is of type AWS::IAM::Role" do
62+ expect ( resource [ "Type" ] ) . to eq ( "AWS::IAM::Role" )
63+ end
64+
65+ it "to have property AssumeRolePolicyDocument" do
66+ expect ( resource [ "Properties" ] [ "AssumeRolePolicyDocument" ] ) . to eq ( { "Version" => "2012-10-17" , "Statement" => [ { "Effect" => "Allow" , "Principal" => { "Service" => "redshift.amazonaws.com" } , "Action" => "sts:AssumeRole" } , { "Effect" => "Allow" , "Principal" => { "Service" => "glue.amazonaws.com" } , "Action" => "sts:AssumeRole" } ] } )
67+ end
68+
69+ it "to have property Policies" do
70+ expect ( resource [ "Properties" ] [ "Policies" ] ) . to eq ( [ { "PolicyName" => "s3-logging" , "PolicyDocument" => { "Statement" => [ { "Sid" => "s3logging" , "Action" => [ "s3:GetBucketLocation" , "s3:GetObject" , "s3:ListMultipartUploadParts" , "s3:ListBucket" , "s3:ListBucketMultipartUploads" ] , "Resource" => [ { "Fn::Sub" => "arn:aws:s3:::${RedshiftLoggingS3Bucket}" } , { "Fn::Sub" => "arn:aws:s3:::${RedshiftLoggingS3Bucket}/*" } ] , "Effect" => "Allow" } ] } } , { "PolicyName" => "glue" , "PolicyDocument" => { "Statement" => [ { "Sid" => "glue" , "Action" => [ "glue:CreateDatabase" , "glue:DeleteDatabase" , "glue:GetDatabase" , "glue:GetDatabases" , "glue:UpdateDatabase" , "glue:CreateTable" , "glue:DeleteTable" , "glue:BatchDeleteTable" , "glue:UpdateTable" , "glue:GetTable" , "glue:GetTables" , "glue:BatchCreatePartition" , "glue:CreatePartition" , "glue:DeletePartition" , "glue:BatchDeletePartition" , "glue:UpdatePartition" , "glue:GetPartition" , "glue:GetPartitions" , "glue:BatchGetPartition" ] , "Resource" => [ "*" ] , "Effect" => "Allow" } ] } } , { "PolicyName" => "logs" , "PolicyDocument" => { "Statement" => [ { "Sid" => "logs" , "Action" => [ "logs:*" ] , "Resource" => [ "*" ] , "Effect" => "Allow" } ] } } ] )
71+ end
72+
73+ end
74+
75+ context "RedshiftFederationIAMRole" do
76+ let ( :resource ) { template [ "Resources" ] [ "RedshiftFederationIAMRole" ] }
77+
78+ it "is of type AWS::IAM::Role" do
79+ expect ( resource [ "Type" ] ) . to eq ( "AWS::IAM::Role" )
80+ end
81+
82+ it "to have property AssumeRolePolicyDocument" do
83+ expect ( resource [ "Properties" ] [ "AssumeRolePolicyDocument" ] ) . to eq ( { "Version" => "2012-10-17" , "Statement" => [ { "Effect" => "Allow" , "Principal" => { "Federated" => { "Fn::Sub" => "arn:aws:iam::${AWS::AccountId}:saml-provider/redshift-federation-saml-provider" } } , "Action" => [ "sts:AssumeRoleWithSAML" , "sts:TagSession" ] , "Condition" => { "StringEquals" => { "SAML:aud" => "http://localhost:7890/redshift/" } } } ] } )
84+ end
85+
86+ it "to have property Policies" do
87+ expect ( resource [ "Properties" ] [ "Policies" ] ) . to eq ( [ { "PolicyName" => "redshift" , "PolicyDocument" => { "Statement" => [ { "Sid" => "redshift" , "Action" => [ "redshift:CreateClusterUser" , "redshift:JoinGroup" , "redshift:GetClusterCredentials" , "redshift:ListSchemas" , "redshift:ListTables" , "redshift:ListDatabases" , "redshift:ExecuteQuery" , "redshift:FetchResults" , "redshift:CancelQuery" , "redshift:DescribeClusters" , "redshift:DescribeQuery" , "redshift:DescribeTable" ] , "Resource" => [ { "Fn::Sub" => "arn:aws:redshift:${AWS::Region}:${AWS::AccountId}:cluster:${RedshiftCluster}" } , { "Fn::Sub" => "arn:aws:redshift:${AWS::Region}:${AWS::AccountId}:dbuser:${RedshiftCluster}/${!redshift:DbUser}" } , { "Fn::Sub" => "arn:aws:redshift:${AWS::Region}:${AWS::AccountId}:dbname:${RedshiftCluster}/${!redshift:DbName}" } , { "Fn::Sub" => "arn:aws:redshift:${AWS::Region}:${AWS::AccountId}:dbgroup:${RedshiftCluster}/mygroup" } ] , "Effect" => "Allow" } ] } } ] )
88+ end
89+
90+ end
91+
92+ context "RedshiftSecurityGroup" do
93+ let ( :resource ) { template [ "Resources" ] [ "RedshiftSecurityGroup" ] }
94+
95+ it "is of type AWS::EC2::SecurityGroup" do
96+ expect ( resource [ "Type" ] ) . to eq ( "AWS::EC2::SecurityGroup" )
97+ end
98+
99+ it "to have property GroupDescription" do
100+ expect ( resource [ "Properties" ] [ "GroupDescription" ] ) . to eq ( { "Fn::Sub" => "${EnvironmentName} - Redshift cluster security group" } )
101+ end
102+
103+ it "to have property VpcId" do
104+ expect ( resource [ "Properties" ] [ "VpcId" ] ) . to eq ( { "Ref" => "VpcId" } )
105+ end
106+
107+ it "to have property Tags" do
108+ expect ( resource [ "Properties" ] [ "Tags" ] ) . to eq ( [ { "Key" => "Environment" , "Value" => { "Ref" => "EnvironmentName" } } ] )
109+ end
110+
111+ end
112+
113+ context "SecretRedshiftMasterUser" do
114+ let ( :resource ) { template [ "Resources" ] [ "SecretRedshiftMasterUser" ] }
115+
116+ it "is of type AWS::SecretsManager::Secret" do
117+ expect ( resource [ "Type" ] ) . to eq ( "AWS::SecretsManager::Secret" )
118+ end
119+
120+ it "to have property Description" do
121+ expect ( resource [ "Properties" ] [ "Description" ] ) . to eq ( { "Fn::Sub" => "${EnvironmentName} Secrets Manager to store Redshift user credentials" } )
122+ end
123+
124+ it "to have property Name" do
125+ expect ( resource [ "Properties" ] [ "Name" ] ) . to eq ( "SecretRedshiftMasterUser" )
126+ end
127+
128+ it "to have property GenerateSecretString" do
129+ expect ( resource [ "Properties" ] [ "GenerateSecretString" ] ) . to eq ( { "SecretStringTemplate" => { "Fn::Sub" => "{\" username\" : \" ${MasterUsername}\" }" } , "GenerateStringKey" => "password" , "PasswordLength" => 32 , "ExcludePunctuation" => true } )
130+ end
131+
132+ end
133+
134+ context "SecretTargetAttachment" do
135+ let ( :resource ) { template [ "Resources" ] [ "SecretTargetAttachment" ] }
136+
137+ it "is of type AWS::SecretsManager::SecretTargetAttachment" do
138+ expect ( resource [ "Type" ] ) . to eq ( "AWS::SecretsManager::SecretTargetAttachment" )
139+ end
140+
141+ it "to have property SecretId" do
142+ expect ( resource [ "Properties" ] [ "SecretId" ] ) . to eq ( { "Ref" => "SecretRedshiftMasterUser" } )
143+ end
144+
145+ it "to have property TargetId" do
146+ expect ( resource [ "Properties" ] [ "TargetId" ] ) . to eq ( { "Ref" => "RedshiftCluster" } )
147+ end
148+
149+ it "to have property TargetType" do
150+ expect ( resource [ "Properties" ] [ "TargetType" ] ) . to eq ( "AWS::Redshift::Cluster" )
151+ end
152+
153+ end
154+
155+ context "RedshiftClusterSubnetGroup" do
156+ let ( :resource ) { template [ "Resources" ] [ "RedshiftClusterSubnetGroup" ] }
157+
158+ it "is of type AWS::Redshift::ClusterSubnetGroup" do
159+ expect ( resource [ "Type" ] ) . to eq ( "AWS::Redshift::ClusterSubnetGroup" )
160+ end
161+
162+ it "to have property Description" do
163+ expect ( resource [ "Properties" ] [ "Description" ] ) . to eq ( { "Fn::Sub" => "${EnvironmentName} - Redshift cluster subnet group" } )
164+ end
165+
166+ it "to have property SubnetIds" do
167+ expect ( resource [ "Properties" ] [ "SubnetIds" ] ) . to eq ( { "Ref" => "SubnetIds" } )
168+ end
169+
170+ it "to have property Tags" do
171+ expect ( resource [ "Properties" ] [ "Tags" ] ) . to eq ( [ { "Key" => "Environment" , "Value" => { "Ref" => "EnvironmentName" } } ] )
172+ end
173+
174+ end
175+
176+ context "RedshiftClusterParameterGroup" do
177+ let ( :resource ) { template [ "Resources" ] [ "RedshiftClusterParameterGroup" ] }
178+
179+ it "is of type AWS::Redshift::ClusterParameterGroup" do
180+ expect ( resource [ "Type" ] ) . to eq ( "AWS::Redshift::ClusterParameterGroup" )
181+ end
182+
183+ it "to have property Description" do
184+ expect ( resource [ "Properties" ] [ "Description" ] ) . to eq ( { "Fn::Sub" => "${EnvironmentName} - Redshift cluster parameter group" } )
185+ end
186+
187+ it "to have property ParameterGroupFamily" do
188+ expect ( resource [ "Properties" ] [ "ParameterGroupFamily" ] ) . to eq ( "redshift-1.0" )
189+ end
190+
191+ it "to have property Parameters" do
192+ expect ( resource [ "Properties" ] [ "Parameters" ] ) . to eq ( [ { "ParameterName" => "enable_user_activity_logging" , "ParameterValue" => "true" } ] )
193+ end
194+
195+ it "to have property Tags" do
196+ expect ( resource [ "Properties" ] [ "Tags" ] ) . to eq ( [ { "Key" => "Environment" , "Value" => { "Ref" => "EnvironmentName" } } ] )
197+ end
198+
199+ end
200+
201+ context "RedshiftCluster" do
202+ let ( :resource ) { template [ "Resources" ] [ "RedshiftCluster" ] }
203+
204+ it "is of type AWS::Redshift::Cluster" do
205+ expect ( resource [ "Type" ] ) . to eq ( "AWS::Redshift::Cluster" )
206+ end
207+
208+ it "to have property ClusterType" do
209+ expect ( resource [ "Properties" ] [ "ClusterType" ] ) . to eq ( { "Fn::If" => [ "RedshiftSingleNodeClusterCondition" , "single-node" , "multi-node" ] } )
210+ end
211+
212+ it "to have property NumberOfNodes" do
213+ expect ( resource [ "Properties" ] [ "NumberOfNodes" ] ) . to eq ( { "Fn::If" => [ "RedshiftSingleNodeClusterCondition" , { "Ref" => "AWS::NoValue" } , { "Ref" => "NumberOfNodes" } ] } )
214+ end
215+
216+ it "to have property Encrypted" do
217+ expect ( resource [ "Properties" ] [ "Encrypted" ] ) . to eq ( { "Ref" => "Encrypt" } )
218+ end
219+
220+ it "to have property KmsKeyId" do
221+ expect ( resource [ "Properties" ] [ "KmsKeyId" ] ) . to eq ( { "Fn::If" => [ "EncryptWithKMS" , { "Ref" => "KmsKeyId" } , { "Ref" => "AWS::NoValue" } ] } )
222+ end
223+
224+ it "to have property NodeType" do
225+ expect ( resource [ "Properties" ] [ "NodeType" ] ) . to eq ( { "Ref" => "NodeType" } )
226+ end
227+
228+ it "to have property DBName" do
229+ expect ( resource [ "Properties" ] [ "DBName" ] ) . to eq ( { "Fn::If" => [ "DatabaseNameSet" , { "Ref" => "DatabaseName" } , { "Ref" => "AWS::NoValue" } ] } )
230+ end
231+
232+ it "to have property PubliclyAccessible" do
233+ expect ( resource [ "Properties" ] [ "PubliclyAccessible" ] ) . to eq ( false )
234+ end
235+
236+ it "to have property MasterUsername" do
237+ expect ( resource [ "Properties" ] [ "MasterUsername" ] ) . to eq ( { "Fn::Sub" => "{{resolve:secretsmanager:${SecretRedshiftMasterUser}:SecretString:username}}" } )
238+ end
239+
240+ it "to have property MasterUserPassword" do
241+ expect ( resource [ "Properties" ] [ "MasterUserPassword" ] ) . to eq ( { "Fn::Sub" => "{{resolve:secretsmanager:${SecretRedshiftMasterUser}:SecretString:password}}" } )
242+ end
243+
244+ it "to have property ClusterParameterGroupName" do
245+ expect ( resource [ "Properties" ] [ "ClusterParameterGroupName" ] ) . to eq ( { "Ref" => "RedshiftClusterParameterGroup" } )
246+ end
247+
248+ it "to have property ClusterSubnetGroupName" do
249+ expect ( resource [ "Properties" ] [ "ClusterSubnetGroupName" ] ) . to eq ( { "Ref" => "RedshiftClusterSubnetGroup" } )
250+ end
251+
252+ it "to have property VpcSecurityGroupIds" do
253+ expect ( resource [ "Properties" ] [ "VpcSecurityGroupIds" ] ) . to eq ( [ { "Ref" => "RedshiftSecurityGroup" } ] )
254+ end
255+
256+ it "to have property AutomatedSnapshotRetentionPeriod" do
257+ expect ( resource [ "Properties" ] [ "AutomatedSnapshotRetentionPeriod" ] ) . to eq ( { "Ref" => "AutomatedSnapshotRetentionPeriod" } )
258+ end
259+
260+ it "to have property PreferredMaintenanceWindow" do
261+ expect ( resource [ "Properties" ] [ "PreferredMaintenanceWindow" ] ) . to eq ( { "Ref" => "MaintenanceWindow" } )
262+ end
263+
264+ it "to have property LoggingProperties" do
265+ expect ( resource [ "Properties" ] [ "LoggingProperties" ] ) . to eq ( { "Fn::If" => [ "EnableLoggingCondition" , { "BucketName" => { "Ref" => "RedshiftLoggingS3Bucket" } , "S3KeyPrefix" => "AWSLogs" } , { "Ref" => "AWS::NoValue" } ] } )
266+ end
267+
268+ it "to have property IamRoles" do
269+ expect ( resource [ "Properties" ] [ "IamRoles" ] ) . to eq ( [ { "Fn::GetAtt" => [ "RedshiftIAMRole" , "Arn" ] } ] )
270+ end
271+
272+ it "to have property SnapshotIdentifier" do
273+ expect ( resource [ "Properties" ] [ "SnapshotIdentifier" ] ) . to eq ( { "Fn::If" => [ "SnapshotSet" , { "Ref" => "Snapshot" } , { "Ref" => "AWS::NoValue" } ] } )
274+ end
275+
276+ it "to have property OwnerAccount" do
277+ expect ( resource [ "Properties" ] [ "OwnerAccount" ] ) . to eq ( { "Fn::If" => [ "SnapshotAccountOwnerSet" , { "Ref" => "SnapshotAccountOwner" } , { "Ref" => "AWS::NoValue" } ] } )
278+ end
279+
280+ it "to have property Tags" do
281+ expect ( resource [ "Properties" ] [ "Tags" ] ) . to eq ( [ { "Key" => "Environment" , "Value" => { "Ref" => "EnvironmentName" } } ] )
282+ end
283+
284+ end
285+
286+ end
287+
288+ end
0 commit comments