How to Deploy Terraform Modules as Service Catalog Products on AWS

Gustavo Zanotto
4 min readApr 14, 2023

--

AWS Service Catalog is a powerful tool that allows users to manage and distribute products within their organization. Recently, AWS has expanded the capabilities of Service Catalog by allowing users to create products using not only CloudFormation templates but also Terraform templates.

As more companies adopt Terraform for infrastructure-as-code management, it’s exciting to see how easily Terraform templates can be transformed into Service Catalog products. This integration offers a range of benefits, from simple module management to full environment deployment, and can help increase efficiency and productivity. In this article, I will guide you through the process of creating and deploying Terraform-based products.

Pre-Requirements

Getting Started

Now that you have installed the Terraform Reference Engine, we can get started by creating our first product:

  1. Let's start by creating a Service Catalog Portfolio:
resource "aws_servicecatalog_portfolio" "lab_tf_modules" {
name = "LAB-TF-MODULES"
description = "Terraform Modules"
provider_name = "Gus"
}

2. For this new feature, our Terraform templates must be uploaded in ".tar.gz". So, let's compress all the ".tf" files from any Terraform Module that we want to add as a Service Catalog Product. In this case, I will be using my terraform module aws-ssm-patch-asg (which I have wrote another Medium post about how to use it here).

- cd terraform-aws-ssm-patch-asg
- tar -czvf aws-ssm-patch-asg.tar.gz *.tf

3. Update the compressed file to a S3 Bucket of your preference.

4. Now, let's create our first Service Catalog Product and associate it with our Portfolio:

resource "aws_servicecatalog_product" "ssm_patch_asg" {
name = "SSM-PATCH-ASG"
owner = "Gus"
type = "TERRAFORM_OPEN_SOURCE"

provisioning_artifact_parameters {
name = "v1.0"
type = "TERRAFORM_OPEN_SOURCE"
disable_template_validation = true
template_url = "https://cf-templates-1xxxxxxl.s3.us-east-2.amazonaws.com/servicecatalog-product-2xxxxxVB-aws-ssm-patch-asg.tar.gz"
}
}

resource "aws_servicecatalog_product_portfolio_association" "ssm_patch_asg" {
portfolio_id = aws_servicecatalog_portfolio.lab_tf_modules.id
product_id = aws_servicecatalog_product.ssm_patch_asg.id
}

5. As mentioned in the official documentation, here, we should add a Launch Constraint for our Terraform Products, so let's create our IAM Launch Role first — I will be giving Administrator access because I will be using the same role to deploy many different terraform modules but feel free to restrict it better and have multiple launch roles for your products if you wish.

resource "aws_iam_role" "terraform_launcher" {
name = "SCLaunch-Terraform"
path = "/"
assume_role_policy = <<POLICY
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "GivePermissionsToServiceCatalog",
"Effect": "Allow",
"Principal": {
"Service": "servicecatalog.amazonaws.com"
},
"Action": "sts:AssumeRole"
},
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::YOUR_ACCOUNT_ID:root"
},
"Action": "sts:AssumeRole"
}
]
}
POLICY
}

resource "aws_iam_role_policy_attachment" "terraform_launcher" {
role = aws_iam_role.terraform_launcher.name
policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
}
  • NOTE: The role name must start with "SCLaunch-"

6. Now, let's create the constraint:

resource "aws_servicecatalog_constraint" "ssm_patch_asg" {
portfolio_id = aws_servicecatalog_portfolio.lab_tf_modules.id
product_id = aws_servicecatalog_product.ssm_patch_asg.id
type = "LAUNCH"

parameters = jsonencode({
"LocalRoleName" : "${aws_iam_role.terraform_launcher.name}"
})
}

7. Congratulations, you have your first Terraform product in place. Now, we need to specify who will have access to our Portfolio. In my case, since I am using a single account, I just want to give access to the IAM Role that I am assuming to access this LAB AWS Account. In "principal_arn" you can specify any IAM User, Role or Group.

resource "aws_servicecatalog_principal_portfolio_association" "lab_access" {
portfolio_id = aws_servicecatalog_portfolio.lab_tf_modules.id
principal_arn = "arn:aws:iam::123456789:role/AssumedRoleName"
}

Note: If you want to share your Portfolio with other AWS Accounts or a whole AWS Organization, you can use this resource.

8. Now, you should see your newly created product in Service Catalog > Provisioning > Products, you can select and Launch It. All the variables from your Terraform Module will be available there as input parameters and once its deployed you will be able to see your Terraform Outputs in the Outputs Tab.

Conclusion

This is definitely a great new feature on AWS that allow us to explore and give our customers and users the ability to easily create AWS resources with a few clicks and following the security and best practices standards that we define in our templates. Although, there is always room for improvements especially in a recently launched feature. I have been using Terraform in a daily basis for more than 5 years and my first impressions about this new tool is that:

  • We should avoid input variables different than bool/string/number in the modules we are creating to be used via Service Catalog in order to get a better user experience when deploying our products and also because the input space is currently just one line and typing medium/big maps/lists may be difficult to visualize/troubleshoot.
  • Even though you can use a Github or Bitbucket connection via AWS CodeStar to upload your Terraform templates, they will still need to be in .tar.gz.

Thank you!

I am looking forward to explore more through this new integration and bring some more use cases here. Stay tuned!

--

--

Gustavo Zanotto

DevOps Engineer | 5x AWS Certified | Terraform | CKA/CKAD