Browse by type
AWS Service Catalog and Terraform Terminology
- hub or fulfillment account: The account where the Terraform server or engine will live.
- spoke account: The spoke accounts that will execute Terraform files against the Terraform engine living in the Hub account.
This solution requires that a Terraform server be deployed and available. You can use an existing Terraform server, or you can deploy a new Terraform server using the supplied CloudFormation templates. The supplied CloudFormation templates will create a new Amazon Elastic Compute Cloud (Amazon EC2) instance and install Terraform.
You can use one Terraform server to target resources across multiple AWS accounts. For the purposes of this paper, we will name the AWS account where the Terraform server resides the “hub account”. Accounts that send requests to the server and contain the provisioned resource will be called “spoke accounts”. For the Terraform server to operate, you must create AWS Identity and Access Management (IAM) roles in each of the spoke accounts and create an AWS Lambda launch function in each desired region of each spoke account. For example, a deployment for 3 accounts that each use us-east-1 and us-east-2 regions will result in 1 Terraform server account, 3 spoke account roles, and 6 Lambda launch functions. The hub account and region containing the Terraform server may also be a spoke account, in which case you must also deploy the IAM role and Lambda launch functions in the hub account and region.
The key to the solution is a CloudFormation template that acts as a proxy to Terraform. The CloudFormation template uses a custom resource, implemented via an AWS Lambda function to call the Terraform APIs. The CloudFormation template can then be customized to capture specific parameters and used to create an AWS Service Catalog product.
The Terraform files are placed in an Amazon Simple Storage Service (Amazon S3) bucket that can be accessed from AWS Service Catalog in each of the spoke accounts. See the following figure.
Once the solution is deployed, end users in each spoke account can launch AWS Service Catalog products. Information about which Terraform file to use, input parameters, and an IAM permission role is passed to the Terraform server from the CloudFormation template. The Terraform server uses this information to manage AWS resources in the originating spoke account. The outputs of the Terraform server are stored in the Amazon S3 Output State Files bucket. The end user has access to this bucket via the AWS Service Catalog GUI or API.
Copy the Service Catalog Terraform components to a S3 bucket to be launched from CloudFormation.
It is assumed that the user has Administerative privileges in IAM for S3, CloudFormation, EC2, VPC, Lambda, and Service Catalog.
There are two methods for copying files to S3 - AWS S3 Console - AWS Command Line Interface (CLI)
Get the content Via Download - Choose the Clone or download button - Choose Download ZIP - Unzip the file into a folder

The aws-service-catalog-terraform-reference-architecture folder is created

Note [YOUR-ACCOUNT-ID] NO DASHES
Choose the Upload button
Use the file explorer opened earlier to drag over the following folders
TerraformCustomResourceHandler
Choose Upload
git clone https://github.com/aws-samples/aws-service-catalog-terraform-reference-architecture.git
The aws-service-catalog-terraform-reference-architecture folder is created
To view the contents
cd aws-service-catalog-terraform-reference-architecture
ls -l
CODE_OF_CONDUCT.md
CONTRIBUTING.md
documentation
LICENSE
NOTICE
README.md
ServiceCatalogSamples
TerraformCustomResourceHandler
TerraformScripts
Note [YOUR-ACCOUNT-ID] NO DASHES
AWS CLI Install Instructions
Create a S3 bucket to host the installation content
aws s3 mb s3://scterraform-[YOUR-ACCOUNT-ID]
Copy the following files to the bucket maintaining the file structure:
aws s3 sync ./TerraformCustomResourceHandler/bin/ s3://scterraform-[YOUR-ACCOUNT-ID]/TerraformCustomResourceHandler/bin/
aws s3 sync ./ServiceCatalogSamples/ s3://scterraform-[YOUR-ACCOUNT-ID]/TerraformCustomResourceHandler/bin/
aws s3 sync ./TerraformScripts/ s3://scterraform-[YOUR-ACCOUNT-ID]/TerraformScripts/
You now have all the files needed for launch in the S3 Bucket which has the same file structure as this github repo:
S3 Bukcet: scterraform-[YOUR-ACCOUNT-ID]
├── TerraformScripts/
│ ├── cloudformation-templates/
│ │ ├── terraform-architecture-single-account.yaml
│ │ ├── terraform-fulfillment-server.yaml
│ │ ├── terraform-launch-lambda.yaml
│ │ └── terraform-spoke-principals.yaml
│ └── bin/
│ └── sc_terraform_wrapper-1.2-py3-none-any.whl
└── TerraformCustomResourceHandler/
└── bin/
└── aws-servicecatalog-terraform-wrapper.jar
Note We have only listed the files you must have access to for this demonstration, more files are included in the actual git repository
### Installing the Service Catalog Terraform reference architecture into a single account hub account
When the Status changes to CREATE_COMPLETE once the stack is created.
The stack output will look similar to the image below.


Service Catalog Console

For each spoke account, you’ll need to enable communication with the hub account by creating an executing role with a trust relationship back to the hub account. Then, create a Lambda launch function in each desired region within the spoke account. Finally, add each spoke account to the SNS topic that queues requests for the spoke account. The supplied CloudFormation stacks will provision these roles and Lambda functions.
Note: Make sure the TerraformArchitecture-SingleAccount CloudFormation stack has a status of CREATE_COMPLETE before proceeding.
The Status changes to CREATE_COMPLETE once the stack is created.
Note: Make sure the TerraformLaunchRole CloudFormation stack has a status of CREATE_COMPLETE before proceeding. 1. Sign in to the AWS Console using the spoke account. 2. Navigate to the CloudFormation console. https://console.aws.amazon.com/cloudformation/ 3. Verify the region. 4. Choose Create Stack. 5. Under Choose a template, select Specify an Amazon S3 template URL. 6. Type the following URL:https://s3.amazonaws.com/scterraform-[YOUR-ACCOUNT-ID]/TerraformScripts/cloudformation-templates/terraform-launch-lambda.yaml 7. Choose Next 8. For Stack name, type TerraformLaunchLambda. 9. For Fulfillment Account ID type the hub account ID. 10. For FulfillmentRegion enter the region 11. Update the remaining parameters (optional). 12. Choose Next. 13. Choose Next. 14. Choose Create** to create the Terraform instance.
The Status changes to CREATE_COMPLETE once the stack is created.
This section is intended for users with a basic working knowledge of GitHub. For more information on GitHub, see https://developer.github.com/v3/guides/.
To use the Terraform Reference Architecture with GitHub, follow these steps.
1. Create a MachineUser with access to the repositories you would like to reference: https://developer.github.com/v3/guides/managing-deploy-keys/#machine-users
Create a secret in your hub account that contains your MachineUser's private key. For example:
aws secretsmanager create-secret --secret-string "`cat id_rsa`" --name TerraformMachineUserIdentity
For more information, see https://docs.aws.amazon.com/secretsmanager/latest/userguide/manage_create-basic-secret.html
Generate a hashed known_hosts file containing the public keys of your repository's host:
a. Retrieve Github's public key using the following commands:
touch known_hosts
chmod 600 known_hosts
ssh-keyscan -t rsa github.com >> known_hosts
b. Verify the public key against Github's public key fingerprints using the following command:
cat known_hosts | ssh-keygen -lf -
c. Compare the output to the public key fingerprints Github has posted: https://help.github.com/articles/github-s-ssh-key-fingerprints/
d. Generate a hashed known_hosts file using the public key:
ssh-keygen -H -f known_hosts
Create a secret in your hub account that contains the hashed known_hosts file. For example:
``aws secretsmanager create-secret --secret-string "cat known_hosts`"
$ claude mcp add aws-service-catalog-terraform-reference-architecture \
-- python -m otcore.mcp_server <graph>