Create Public and Private VPC With VPC Flow Logs Using Cloudformation

In this blog we will learn how to add true/false option in cloudformation to configure VPC flow logs.

Note: To learn basic of cloudformation, please check our old blog: Click me

Main Script:

This script will create a VPC, 3 private subnet, 3 public subnet, enable VPC flow logs(Optional), NAT gateway for private instances, IGW for public and custom Route tables.

  1
  2{
  3	"AWSTemplateFormatVersion": "2010-09-09",
  4	"Description" : "Create 3 private subnet for APP and 3 Public subnet for WEB with New VPC and VPC Flow Logs enabler",
  5
  6"Parameters": {
  7    "myVPCcidr": {
  8                      "Description": "Enter VPC CIDR",
  9                "Type": "String",
 10                "MinLength": "9",
 11                "MaxLength": "18",
 12                "Default": "10.10.0.0/16",
 13                "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
 14                "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
 15                    },
 16    "myVPCName":{
 17                   "Description":"Enter the name of  Your VPC",
 18                   "Type":"String",
 19                   "ConstraintDescription": "This name is will assign to Name tag"
 20                },
 21  "myPrivateSubnet1" : {
 22     "Description": "Enter your APP private subnet 1 CIDR here",
 23	 "Type": "String",
 24      "MinLength": "9",
 25      "MaxLength": "18",
 26      "Default": "10.10.1.0/24",
 27      "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
 28      "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
 29  },
 30  "myPrivateSubnet1Name":{
 31	     "Description":"Enter the name of 1st App Private Subnet name",
 32		 "Type":"String"
 33	  },
 34  "myPrivateSubnet1AZ" : {
 35
 36			"Description":"Select the AZ in which you want to create the subnet:",
 37		    "Type": "AWS::EC2::AvailabilityZone::Name"
 38
 39      },
 40
 41   "myPrivateSubnet2" : {
 42	"Description": "Enter your APP subnet 2 CIDR here",
 43	 "Type": "String",
 44      "MinLength": "9",
 45      "MaxLength": "18",
 46      "Default": "10.10.2.0/24",
 47      "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
 48      "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
 49
 50
 51  },
 52   "myPrivateSubnet2Name":{
 53	     "Description":"Enter the name of 2nd APP Private Subnet name",
 54		 "Type":"String"
 55	  },
 56   "myPrivateSubnet2AZ" : {
 57
 58			"Description":"Select the AZ in which you want to create the subnet:",
 59		    "Type": "AWS::EC2::AvailabilityZone::Name"
 60
 61      },
 62
 63
 64  "myPrivateSubnet3" : {
 65		"Description": "Enter your APP subnet 3 CIDR here",
 66		 "Type": "String",
 67      "MinLength": "9",
 68      "MaxLength": "18",
 69      "Default": "10.10.3.0/24",
 70      "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
 71      "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
 72
 73  },
 74   "myPrivateSubnet3Name":{
 75	     "Description":"Enter the name of 3rd APP Private Subnet name",
 76		 "Type":"String"
 77	  },
 78	"myPrivateSubnet3AZ" : {
 79
 80			"Description":"Select the AZ in which you want to create the subnet:",
 81		    "Type": "AWS::EC2::AvailabilityZone::Name"
 82
 83      },
 84
 85
 86  "myPublicSubnet1" : {
 87		"Description": "Enter your public Web subnet 1 CIDR here",
 88		 "Type": "String",
 89      "MinLength": "9",
 90      "MaxLength": "18",
 91      "Default": "10.10.7.0/24",
 92      "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
 93      "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
 94
 95  },
 96	"myPublicSubnet1Name":{
 97	     "Description":"Enter the name of 1st Web Public Subnet name",
 98		 "Type":"String"
 99	  },
100	"myPublicSubnet1AZ" : {
101
102			"Description":"Select the AZ in which you want to create the subnet:",
103		    "Type": "AWS::EC2::AvailabilityZone::Name"
104
105      },
106
107
108    "myPublicSubnet2" : {
109			"Description": "Enter your Public Web subnet 2 CIDR here",
110			 "Type": "String",
111      "MinLength": "9",
112      "MaxLength": "18",
113      "Default": "10.10.8.0/24",
114      "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
115      "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
116  },
117    "myPublicSubnet2Name":{
118	     "Description":"Enter the name of 2nd Public Subnet name",
119		 "Type":"String"
120	  },
121	"myPublicSubnet2AZ" : {
122
123			"Description":"Select the AZ in which you want to create the subnet:",
124		    "Type": "AWS::EC2::AvailabilityZone::Name"
125
126      },
127
128
129	"myPublicSubnet3" : {
130			"Description": "Enter your Public subnet 3 CIDR here",
131			 "Type": "String",
132      "MinLength": "9",
133      "MaxLength": "18",
134      "Default": "10.10.9.0/24",
135      "AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
136      "ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x."
137  },
138   "myPublicSubnet3Name":{
139	     "Description":"Enter the name of 3rd Public Subnet name",
140		 "Type":"String"
141	  },
142	  "myPublicSubnet3AZ" : {
143
144			"Description":"Select the AZ in which you want to create the subnet:",
145		    "Type": "AWS::EC2::AvailabilityZone::Name"
146
147      },
148
149
150"myPrivateRouteName":{
151	     "Description":"Enter the name of Private RouteTable ",
152		 "Type":"String"
153	  },
154"myPublicRouteName":{
155	     "Description":"Enter the name of Public RouteTable name",
156		 "Type":"String"
157	  },
158"myIGWName":{
159	     "Description":"Enter the name of IGW",
160		 "Type":"String"
161	  },
162"myNATName":{
163	     "Description":"Enter the name of Private RouteTable",
164		 "Type":"String"
165	  },
166"myNATEIPName":{
167	     "Description":"Enter the name of NAT EIP",
168		 "Type":"String"
169	  },
170
171
172"ApplicationTagName" : {
173	     "Description":"Enter the name of Application Name",
174		 "Type":"String"
175	  },
176"ApplicationVersionName" : {
177	     "Description":"Enter the name of Application Version",
178		 "Type":"String"
179	  },
180 "EnableVPCFlow" : {
181    "Description": "Whether you want to enable VPC Flow logs.",
182    "Default" : "false",
183    "Type" : "String",
184    "AllowedValues" : ["true", "false"]
185  }
186
187
188},
189"Conditions" : {
190    "createVPCFlow" : {"Fn::Equals" : [{"Ref" : "EnableVPCFlow"}, "true"]}
191  },
192"Metadata" : {
193  "AWS::CloudFormation::Interface" : {
194       "ParameterGroups" : [
195      {
196        "Label" : { "default" : "VPC Details" },
197        "Parameters" : [ "myVPCcidr","myVPCName" ]
198      },
199	  {
200        "Label" : { "default" : "Private Private Subnet 1 Details" },
201        "Parameters" : [ "myPrivateSubnet1","myPrivateSubnet1AZ","myPrivateSubnet1Name" ]
202      },
203	  {
204        "Label" : { "default" : "Private private Subnet 2 Details" },
205        "Parameters" : [ "myPrivateSubnet2","myPrivateSubnet2AZ","myPrivateSubnet2Name" ]
206      },
207	  {
208        "Label" : { "default" : "Private Private Subnet 3 Details" },
209        "Parameters" : [ "myPrivateSubnet3","myPrivateSubnet3AZ","myPrivateSubnet3Name" ]
210      },
211	  {
212        "Label" : { "default" : "Public Public Subnet 1 Details" },
213        "Parameters" : [ "myPublicSubnet1","myPublicSubnet1AZ","myPublicSubnet1Name" ]
214      },
215	  {
216        "Label" : { "default" : "Public Public Subnet 2 Details" },
217        "Parameters" : [ "myPublicSubnet2","myPublicSubnet2AZ","myPublicSubnet2Name" ]
218      },
219	  {
220        "Label" : { "default" : "Public Public Subnet 3 Details" },
221        "Parameters" : [ "myPublicSubnet3","myPublicSubnet3AZ","myPublicSubnet3Name" ]
222      },
223	  {
224        "Label" : { "default" : "Add All Tags Details" },
225        "Parameters" : [ "ApplicationTagName","ApplicationVersionName"]
226      },
227	  {
228        "Label" : { "default" : "Add All Nat Gateway Tags Details" },
229        "Parameters" : [ "myNATEIPName","myNATName" ]
230      },
231	  {
232        "Label" : { "default" : "Add All Route Table Tags Details" },
233        "Parameters" : [ "myPrivateRouteName","myPublicRouteName"]
234      },
235      {
236        "Label" : { "default" : "Add IGW Tags Details" },
237        "Parameters" : [ "myIGWName"]
238      }
239	  ]
240
241  }
242  },
243"Resources" : {
244    "myVPC" : {
245               "Type" : "AWS::EC2::VPC",
246               "Properties" : {
247                    "CidrBlock" : { "Ref" : "myVPCcidr" },
248                    "EnableDnsSupport" : "true",
249                    "EnableDnsHostnames" : "true",
250                    "InstanceTenancy" : "default",
251                    "Tags" : [ {"Key" : "Name", "Value" : { "Ref" : "myVPCName" }} ]
252                  }
253                },
254    "myAWSVPCsubnet1": {
255			"Type": "AWS::EC2::Subnet",
256			"Properties": {
257				"VpcId": {
258					"Ref": "myVPC"
259				},
260				"CidrBlock": { "Ref" : "myPrivateSubnet1" },
261				"AvailabilityZone": { "Ref" : "myPrivateSubnet1AZ" },
262				"Tags": [{
263					"Key": "Name",
264					"Value": { "Ref" : "myPrivateSubnet1Name" }
265				},
266				{
267					"Key": "appname",
268					"Value": { "Ref" : "ApplicationTagName" }
269				},
270				{
271					"Key": "appversion",
272					"Value": { "Ref" : "ApplicationVersionName" }
273				}
274				]
275			}
276		},
277	"myAWSVPCsubnet2": {
278			"Type": "AWS::EC2::Subnet",
279			"Properties": {
280				"VpcId": {
281					"Ref": "myVPC"
282				},
283				"CidrBlock": { "Ref" : "myPrivateSubnet2" },
284				"AvailabilityZone": { "Ref" : "myPrivateSubnet2AZ" },
285				"Tags": [{
286					"Key": "Name",
287					"Value": { "Ref" : "myPrivateSubnet2Name" }
288				},
289				{
290					"Key": "appname",
291					"Value": { "Ref" : "ApplicationTagName" }
292				},
293				{
294					"Key": "appversion",
295					"Value": { "Ref" : "ApplicationVersionName" }
296				}]
297			}
298		},
299	"myAWSVPCsubnet3": {
300			"Type": "AWS::EC2::Subnet",
301			"Properties": {
302				"VpcId": {
303					"Ref": "myVPC"
304				},
305				"CidrBlock": { "Ref" : "myPrivateSubnet3" },
306				"AvailabilityZone": { "Ref" : "myPrivateSubnet3AZ" },
307				"Tags": [{
308					"Key": "Name",
309					"Value": { "Ref" : "myPrivateSubnet3Name" }
310				},
311				{
312					"Key": "appname",
313					"Value": { "Ref" : "ApplicationTagName" }
314				},
315				{
316					"Key": "appversion",
317					"Value": { "Ref" : "ApplicationVersionName" }
318				}]
319			}
320		},
321	"myAWSVPCsubnet7": {
322			"Type": "AWS::EC2::Subnet",
323			"Properties": {
324				"VpcId": {
325					"Ref": "myVPC"
326				},
327				"CidrBlock": { "Ref" : "myPublicSubnet1" },
328				"AvailabilityZone": { "Ref" : "myPublicSubnet1AZ" },
329				"Tags": [{
330					"Key": "Name",
331					"Value": { "Ref" : "myPublicSubnet1Name" }
332				},
333				{
334					"Key": "appname",
335					"Value": { "Ref" : "ApplicationTagName" }
336				},
337				{
338					"Key": "appversion",
339					"Value": { "Ref" : "ApplicationVersionName" }
340				}]
341			}
342		},
343	"myAWSVPCsubnet8": {
344			"Type": "AWS::EC2::Subnet",
345			"Properties": {
346				"VpcId": {
347					"Ref": "myVPC"
348				},
349				"CidrBlock": { "Ref" : "myPublicSubnet2" },
350				"AvailabilityZone": { "Ref" : "myPublicSubnet2AZ" },
351				"Tags": [{
352					"Key": "Name",
353					"Value": { "Ref" : "myPublicSubnet2Name" }
354				},
355				{
356					"Key": "appname",
357					"Value": { "Ref" : "ApplicationTagName" }
358				},
359				{
360					"Key": "appversion",
361					"Value": { "Ref" : "ApplicationVersionName" }
362				}]
363			}
364		},
365	"myAWSVPCsubnet9": {
366			"Type": "AWS::EC2::Subnet",
367			"Properties": {
368				"VpcId": {
369					"Ref": "myVPC"
370				},
371				"CidrBlock": { "Ref" : "myPublicSubnet3" },
372				"AvailabilityZone": { "Ref" : "myPublicSubnet3AZ" },
373				"Tags": [{
374					"Key": "Name",
375					"Value": { "Ref" : "myPublicSubnet3Name" }
376				},
377				{
378					"Key": "appname",
379					"Value": { "Ref" : "ApplicationTagName" }
380				},
381				{
382					"Key": "appversion",
383					"Value": { "Ref" : "ApplicationVersionName" }
384				}]
385			}
386		},
387	"myVPCpublicRoute" : {
388                   "Type" : "AWS::EC2::RouteTable",
389               "Properties" : {
390                                  "VpcId" : { "Ref" : "myVPC" },
391                                  "Tags" : [ { "Key" : "Name", "Value" : { "Ref" : "myPublicRouteName" } },
392				{
393					"Key": "appname",
394					"Value": { "Ref" : "ApplicationTagName" }
395				},
396				{
397					"Key": "appversion",
398					"Value": { "Ref" : "ApplicationVersionName" }
399				}]
400                           }
401                },
402	"myVPCprivateRoute" : {
403                "Type" : "AWS::EC2::RouteTable",
404               "Properties" : {
405                                  "VpcId" : { "Ref" : "myVPC" },
406                                  "Tags" : [ { "Key" : "Name", "Value" : { "Ref" : "myPrivateRouteName" } },
407				{
408					"Key": "appname",
409					"Value": { "Ref" : "ApplicationTagName" }
410				},
411				{
412					"Key": "appversion",
413					"Value": { "Ref" : "ApplicationVersionName" }
414				} ]
415                           }
416                },
417	"PublicSubnet1RouteTableAssociation" : {
418                       "Type" : "AWS::EC2::SubnetRouteTableAssociation",
419                       "Properties" : {
420                          "SubnetId" : { "Ref" : "myAWSVPCsubnet7" },
421                          "RouteTableId" : { "Ref" : "myVPCpublicRoute" }
422                       }
423                    },
424	"PublicSubnet2RouteTableAssociation" : {
425                       "Type" : "AWS::EC2::SubnetRouteTableAssociation",
426                       "Properties" : {
427                          "SubnetId" : { "Ref" : "myAWSVPCsubnet8" },
428                          "RouteTableId" : { "Ref" : "myVPCpublicRoute" }
429                       }
430                    },
431	"PublicSubnet3RouteTableAssociation" : {
432                       "Type" : "AWS::EC2::SubnetRouteTableAssociation",
433                       "Properties" : {
434                          "SubnetId" : { "Ref" : "myAWSVPCsubnet9" },
435                          "RouteTableId" : { "Ref" : "myVPCpublicRoute" }
436                       }
437                    },
438	"PrivateSubnet1RouteTableAssociation" : {
439                       "Type" : "AWS::EC2::SubnetRouteTableAssociation",
440                       "Properties" : {
441                          "SubnetId" : { "Ref" : "myAWSVPCsubnet1"},
442                          "RouteTableId" : { "Ref" : "myVPCprivateRoute" }
443                       }
444                    },
445	"PrivateSubnet2RouteTableAssociation" : {
446                       "Type" : "AWS::EC2::SubnetRouteTableAssociation",
447                       "Properties" : {
448                          "SubnetId" : { "Ref" : "myAWSVPCsubnet2"},
449                          "RouteTableId" : { "Ref" : "myVPCprivateRoute" }
450                       }
451                    },
452	"PrivateSubnet3RouteTableAssociation" : {
453                       "Type" : "AWS::EC2::SubnetRouteTableAssociation",
454                       "Properties" : {
455                          "SubnetId" : { "Ref" : "myAWSVPCsubnet3"},
456                          "RouteTableId" : { "Ref" : "myVPCprivateRoute" }
457                       }
458                    },
459	"myInternetGateway" : {
460                      "Type" : "AWS::EC2::InternetGateway",
461                      "Properties" : {
462                        "Tags" : [ {"Key" : "Name", "Value" : { "Ref" : "myIGWName" }}]
463                      }
464                },
465	"AttachIGWGateway" : {
466                       "Type" : "AWS::EC2::VPCGatewayAttachment",
467                       "Properties" : {
468                          "VpcId" : { "Ref" : "myVPC" },
469                          "InternetGatewayId" : { "Ref" : "myInternetGateway" }
470                        }
471                },
472    "AttachedtoPublicRoute" : {
473                   "Type" : "AWS::EC2::Route",
474                   "DependsOn" : "myInternetGateway",
475                   "Properties" : {
476                      "RouteTableId" : { "Ref" : "myVPCpublicRoute" },
477                      "DestinationCidrBlock" : "0.0.0.0/0",
478                      "GatewayId" : { "Ref" : "myInternetGateway" }
479                   }
480            },
481	"myAWSVPCNAT" : {
482           "Type" : "AWS::EC2::NatGateway",
483           "Properties" : {
484              "AllocationId" : { "Fn::GetAtt" : ["EIP", "AllocationId"]},
485              "SubnetId" : { "Ref" : "myAWSVPCsubnet7"},
486              "Tags" : [ {"Key" : "Name", "Value" : { "Ref" : "myNATName" } },
487				{
488					"Key": "appname",
489					"Value": { "Ref" : "ApplicationTagName" }
490				},
491				{
492					"Key": "appversion",
493					"Value": { "Ref" : "ApplicationVersionName" }
494				} ]
495             }
496        },
497	"EIP" : {
498           "Type" : "AWS::EC2::EIP",
499           "Properties" : {
500              "Domain" : "vpc",
501			  "Tags" : [ {"Key" : "Name", "Value" : { "Ref" : "myNATEIPName" } },
502				{
503					"Key": "appname",
504					"Value": { "Ref" : "ApplicationTagName" }
505				},
506				{
507					"Key": "appversion",
508					"Value": { "Ref" : "ApplicationVersionName" }
509				} ]
510           }
511        },
512	"AttachNATtoPrivateRoute" : {
513           "Type" : "AWS::EC2::Route",
514           "Properties" : {
515              "RouteTableId" : { "Ref" : "myVPCprivateRoute" },
516              "DestinationCidrBlock" : "0.0.0.0/0",
517              "NatGatewayId" : { "Ref" : "myAWSVPCNAT" }
518           }
519        },
520
521	"VPCFlowRole": {
522            "Type": "AWS::IAM::Role",
523		    "Condition": "createVPCFlow",
524            "Properties": {
525                "AssumeRolePolicyDocument": {
526                    "Version": "2012-10-17",
527                    "Statement": [
528                        {
529                            "Effect": "Allow",
530                            "Principal": {
531                                "Service": "vpc-flow-logs.amazonaws.com"
532                            },
533                            "Action": "sts:AssumeRole"
534                        }
535                    ]
536                },
537                "Policies": [
538                    {
539                        "PolicyName": "flowlogs-policy",
540                        "PolicyDocument": {
541                            "Version": "2012-10-17",
542                            "Statement": [
543                                {
544                                    "Effect": "Allow",
545                                    "Action": [
546                                        "logs:CreateLogStream",
547                                        "logs:PutLogEvents",
548                                        "logs:DescribeLogGroups",
549                                        "logs:DescribeLogStreams"
550                                    ],
551                                    "Resource": {
552                                        "Fn::GetAtt": [
553                                            "VPCLogGroup",
554                                            "Arn"
555                                        ]
556                                    }
557                                }
558                            ]
559                        }
560                    }
561                ]
562            }
563        },
564	"VPCLogGroup": {
565            "Type": "AWS::Logs::LogGroup",
566		    "Condition": "createVPCFlow",
567            "Properties": {
568					"LogGroupName" : { "Fn::Join" : [ "-", [ {
569								  "Ref": "myVPCName"
570									},"FlowLogsGroup" ] ]
571				  				}
572			}
573        },
574	"FlowLog": {
575            "Type": "AWS::EC2::FlowLog",
576		    "Condition": "createVPCFlow",
577            "Properties": {
578                "DeliverLogsPermissionArn": {
579                    "Fn::GetAtt": [
580                        "VPCFlowRole",
581                        "Arn"
582                    ]
583                },
584                "LogGroupName": { "Fn::Join" : [ "-", [ {
585								  "Ref": "myVPCName"
586									},"FlowLogsGroup" ] ]
587				  				},
588                "ResourceId":  {
589					"Ref": "myVPC"
590				  },
591				  "ResourceType": "VPC",
592				  "TrafficType": "ALL"
593            }
594        }
595}
596}

Use above script and share your feedback. We love to hear your thoughts and if you need any new script, please let us know.

I :heart: AWS! :smile: Enjoy