In the previous section of our series on AWS CloudFormation, we extended our base template to enable it to create a working OpenVPN server that we can connect to and start using to enhance our privacy.
In this final part of the series, we will address the issue of CloudFormation being unable to remove the S3 bucket on stack deletion. We will accomplish this by adding a custom resource to the template, which will invoke a Lambda function and wait for that function to respond with an outcome. The Lambda function will delete each resource in the bucket and then attempt to remove the bucket itself. CloudFormation will wait for the function to complete, after which, it will be able to complete the stack deletion.
A quick note before we begin – the resources we create in this tutorial may incur charges on your account if you’re not eligible for the free tier of AWS service. These resources should be minimal, but if you’re following along, be sure to delete your stack when you’re finished, otherwise you may be charged.
To follow along, copy the code from our final template into your text editor:
What’s in our CloudFormation template?
This template extends the base template we worked through in parts one and two. If you’re not familiar with the template we’re working from, we encourage you to start from the beginning of the series and work your way through to see how we’ve built up our stack over time.
EmptyS3BucketExecutionRole – The IAM role our Lambda function will assume when it executes.
EmptyS3BucketExecutionPolicy – This policy will be attached to our Lambda execution role, EmptyS3BucketExecutionRole. The Lambda function will be granted write output to CloudWatch Logs and full access to S3.
EmptyS3BucketLambda – This Lambda function will empty and delete the S3 bucket which was created with our stack. The function will be invoked when CloudFormation emits events for stack creation, update, and deletion. Lambda functions can be loaded by CloudFormation from either an S3 bucket, or embedded inline within the template.
EmptyS3BucketAction – Custom resource for the EmptyS3BucketLambda function. CloudFormation will wait for the associated Lambda function to signal back with cfn-response. If your Lambda function does not respond to the Custom Resource, the CloudFormation stack will be stuck in a pending state for a long, long time (an hour or more).
Run and test your CloudFormation stack
Run the template and wait for the installation to be in a CREATE_COMPLETE state. After it has completed, delete the stack and confirm it completes without error; if successful, your entire stack (including the S3 bucket) will be removed from the CloudFormation UI when the deletion is complete.
Debugging and troubleshooting
If the stack deletion throws an error and fails to delete, you can check the Events tab in the CloudFormation console, which will let you know which resource had a problem. If there was an issue with with the Lambda function or the S3 bucket, you can take a look at the CloudWatch Logs for the Lambda function to see what went wrong. Here’s how you can find these logs:
First, unfold the Resource section and click on the physical ID of the Lambda function. This should take you to your Lambda function.
On the screen for your Lambda function, click Monitoring. Click View logs in CloudWatch Logs, and select the log stream (there should be only one). From here, you can read the output from the console.log statements in the function
That’s it! We now have a fully automated deployment of OpenVPN, and can use our new setup to increase our security on public or uncontrolled internet connections. Because we’ve automated the creation of our system, our resources can be deployed and destroyed quickly and efficiently, which saves us both time and money.
CloudFormation is a powerful tool that allows us to write “code” that describes our infrastructure. While we created a relatively small example in this project, CloudFormation can also be used to quickly deploy massive systems in a fraction of the time it would take to create them manually. Its uses aren’t limited to VPN servers, of course – it can be used to create any number of setups you commonly use. If you have a specific system – or even a component element of a system – that needs to be created more than once, time is always a factor. With CloudFormation, we now have the power to spend less time doing the boring work, and more time to spend doing what we enjoy.
In this guide, we covered a few concepts that may be unfamiliar, including CloudFormation custom resources and the cfn-response. If you’re interested in learning more, we’ve provided some helpful resources below.
CloudFormation custom resources
Custom resources bind an external service into our CloudFormation workflow. CloudFormation sends an SNS message to invoke and waits for the external service to provide a response with the outcome. Check here for more information.
When we use our Lambda function, we need a way to retrieve a response for error handling, to ensure that the function worked properly. Check here for more information.
YouTube Video Walkthrough
I have also created a corresponding video walkthrough for this section. If you would like an added level of detail you can follow along with me here. If you found this content helpful please subscribe to my channel: