Introduction
Modules in Terraform are a collection of resources that can be linked or just created individually. When we call a module, we are calling a file with a bunch of resources with some parameters inside, parameters we need either to specify in the resource itself or in another file which stores our variables.
Why do we use Terraform?
- It is a very useful tool to develop, change and have a versioning of our infrastructure in an efficient and safe way.
- It is a tool that allows you to define infrastructure as code and enables you to change and track the infrastructure with ease.
- It is independent of the platform or ‘cloud agnostic’ and allows working with multiple cloud providers.
What do we need for this lab?
- Terraform installed. In this case we run v.0.12.7.
- In our case, we are using AWS as our Cloud Provider, so we need a user with programmatic access. We need as well to give access to this user with the proper IAM Policy.
- Your preferred code editor.
Let’s get started!
Usually, first we should either set up a Terraform module with our required parameters or just get some official module from the network. In our case, I did myself a module with an S3 Bucket and its own policy and therefore, I specify what options I’d like the module to have.
It’d look something like this:
resource "aws_s3_bucket" "this" { bucket = var.bucket_name acl = var.type_acl force_destroy = var.destroy tags = { Name = var.tag_name } versioning { enabled = var.versioning } } resource "aws_s3_bucket_policy" "this" { bucket = var.bucket_name policy = templatefile("${path.module}/templates/s3_origin_access_identity.json", { origin_access_identity_arn = aws_cloudfront_origin_access_identity.this.iam_arn, origin_access_identity_bucket_name = var.bucket_name }) }
As you may noticed, everything is “variablized”. Hence, we’ll need to create a file with our variables stored with their custom values.
In the same folder we have our file “main.tf”, we create our “variables.tf”:
### S3 VARIABLES variable "bucket_name" { } variable "tag_name" { } variable "type_acl" { } variable "versioning" { } variable "destroy" { } variable "aliases" { } variable "certificate_arn" { }
In this particular case, you may ask yourselves why these variables don’t have any value stored. And the answer is, we’re using a main file called “terragrunt.hcl” which will store all our values when we call the module.
Another thing that may be confusing is how to specfiy the bucket policy. We can either specifyit with a heredoc file (EOF) or straightaway with a function of Terraform called “templatefile”.
The first example is in Terraform Documentation, a website that I strongly recommend you to visit to understand how powerful modules and its attributes are.
The second example, and the one we used, it’d look something like this:
On the same folder, we must have a folder called “templates” and inside, introduce the bucket policy as a JSON file.
{ "Version": "2012-10-17", "Id": "PolicyForCloudFrontPrivateS3Content", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "${origin_access_identity_arn}" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::${origin_access_identity_bucket_name}/*" } ] }
You may’ve noticed we introduced ${origin_access_identity_arn} and ${origin_access_identity_bucket_name} and this is because we want to set such values manually like this:
policy = templatefile("${path.module}/templates/s3_origin_access_identity.json", { origin_access_identity_arn = aws_cloudfront_origin_access_identity.this.iam_arn, origin_access_identity_bucket_name = var.bucket_name })
As you see, we introduce the “arn” calling another resource called “aws_cloudfront_origin_access_identity” and the bucket name we introduce it as we have seen before with our variables file.
Now you just need to specify your Terraform provider and to call the module with another file with the values you have specified and deploy it:
provider "aws" { region = var.region version = "~> 2.0" } provider "aws" { alias = "aws_us_east_1" region = "us-east-1" } module "s3" { source = "../../../../../../modules/s3-cloudfront/" bucket_name = var.bucket_name tag_name = var.tag_name type_acl = var.type_acl versioning = var.versioning destroy = var.destroy aliases = var.aliases certificate_arn = var.certificate_arn }
Deploy it with a terraform init, terraform plan and terraform apply.
Conclusion
So, we saw how to deploy an S3 Bucket with its policy with Terraform. I strongly recommend you visiting the official Terraform Documentation to keep learning about modules and all related with them.
I invite you all in case you need information about the DevOps world, to contact us and keep checking our blog to find other useful posts.