Simplifying AWS Infrastructure with SSO, CLI, CodeCommit and Terraform

A Best Practice Guide to Referencing Remote Terraform Modules Stored in CodeCommit Using SSO Temporary Credentials

By Brandon Prasnicki, Senior Solutions Architect, Cloud

The modern cloud ecosystem offers an abundance of tools and services designed to simplify infrastructure management, enhance security, and streamline development workflows. Among these, AWS Single Sign-On (SSO), the AWS Command Line Interface (CLI), AWS CodeCommit, and Terraform stand out as powerful solutions for automating and managing cloud resources efficiently.

Terraform is an open-source tool that allows you to define infrastructure as code, making it easier to create and manage AWS resources consistently by using re-usable modules.  By passing variables into these modules you can re-use the same templated code to create unique resources quickly and efficiently.

AWS SSO simplifies the management of user access to AWS accounts and applications, allowing users to sign in using a single set of credentials. When integrated with the AWS CLI, it enables seamless access to AWS services from the command line, adhering to the principle of least privilege.

AWS CodeCommit is a managed source control service that hosts Git repositories, including those containing Terraform modules. AWS CodeCommit is low cost and lives right within your AWS environment and can be secured just like your other AWS resources using AWS SSO and iam policies.

This article assumes you have some basic Terraform knowledge, but you may want to better organize your code and make use of remote modules. AWS CodeCommit may be a good choice for this Terraform code, however you may have been challenged (as I was) to discover how to make use of a common module repository.

Many examples you will find searching the internet will be limited in regards to putting all the pieces together to make use of remote Terraform modules you may have created for re-use in your CodeCommit repository. When it comes to referencing CodeComit repositories and using SSO and related AWS profiles to authenticate and reference these modules, the ‘How-To’ in a best practice sort of way is a bit hard to find. This article will guide you through leveraging these tools to configure AWS SSO for CLI access, manage AWS profiles, and deploy an Amazon EC2 instance profile using a remote CodeCommit Terraform module.

Getting Started with AWS SSO and CLI

Configuring AWS SSO for CLI Access

  1. Ensure AWS CLI Version 2.x: AWS SSO requires AWS CLI version 2.  Check your version with aws –version and update if necessary.
  2. Configure SSO: Run aws configure sso and follow the prompts. You’ll need to provide your SSO start URL, SSO region, account ID, and role name. This process authenticates your session and sets up an SSO profile in the AWS CLI.
  3. To login to SSO using a profile configured in your main.tf, use aws sso login –profile <profile-name>.  You will see a browser login to authenticate via SSO and generate a token for your cli session.
  4. Use Your SSO Profile: List available profiles using aws sso list-profiles. To use a specific profile, include –profile <profile-name> in your CLI commands. 

The profile configuration can also be seen, verified and modified in your .aws/config file:

[profile Dev]

sso_start_url = https://<sso url>/start

sso_region = us-east-1

sso_account_id = <account number>

sso_role_name = AWSAdministratorAccess

region = us-east-1

These profiles will correspond to the profile configuration in your terraform code:

Main.tf:

provider "aws" {
region  = var.region
profile = var.aws_profile
}

terraform.tfvars

aws_profile = "Dev"
region = "us-east-1"

With SSO configured, you’re now ready to interact with AWS services through the CLI and Terraform using your SSO credentials.  Any resources created will be created in the Dev account because of the profile I have configured in my aws config file and referenced in my main.tf of my workload terraform environment.

Automating EC2 Instance Profile Deployment with Terraform and AWS CodeCommit

A common use case for using common modules we see often is defining an EC2 profile to allow SSM functionality. A common module for this is rather simple, and simply attaches the ‘AmazonSSMManagedInstanceCore’ policy to a newly created instance profile/role. Since this is something we do over and over again and very little change is needed to the module, it is a good use case for a shared module in a remote repository and reference the module when the workload configuration needs it.

To deploy an EC2 instance profile using Terraform, you can reference a Terraform module stored in a CodeCommit repository separate from your environment configuration. This approach promotes code reuse and simplifies infrastructure management. Then during instance creation, we can reference this module output to attach the instance profile to the instance we create in the Dev account using the Dev profile (or users can use it from the UI when launching instances etc). Of course, the shared module could be more complex and take in different variables for policies to attach and loop etc, but that is beyond the scope of the point for this article.

To create a CodeCommit repository, simply navigate to the CodeCommit service and create the repository. Note, you may choose to keep code in a separate account from where your other AWS resources live (compute, EC2, VPC etc). It is important to remember that it isn’t where your code lives that matters, but rather the configuration of the profile related to your .aws/config that drives where resources are created.

Referencing a Remote CodeCommit Terraform Module

1. Create Your Terraform Configuration:

When creating resources using a common Terraform module stored in another repository, update the module call in the file you are working on for the relevant AWS account environment as configured in your aws profile (e.g., main.tf).  To reference the remote CodeCommit module for deploying an EC2 instance profile, specify the module’s source attribute with the CodeCommit repository in the source line (all one line) in the format below, and then provide any required variables for the module:

Here is an example of a call from my ‘Dev’ CodeCommit repository making use of the sharedmodules repository’s module ‘IAM_SSM_instance_profile’.  Common tags passes relevant environment specific names and tags into the shared module.

module "IAM_SSM_instance_profile" {
source = "git::codecommit::us-east-1://shared-
services@sharedmodules//modules/IAM_SSM_instance_profile"
common_tags = var.common_tags
}

An important note here is the AWS profile credentials in relation to where the repo exists.  Here it is ‘shared-services’ and is noted after the // in the source line.  It may be the case (and is generally best practice) that you may have your AWS CodeCommit code in an account not related to your workload account resources.   For this example, the code is in another account (shared-services).  While I am creating resources in the ‘Dev’ account profile, the code lives in the shared-services account for both the environment and shared modules, and therefore the profile is noted in the source path.  

Another note is that for this example, this ‘shared-services’ account is in the same organization, and is using the same SSO login URL and authentication, but it is defined as another profile within the .aws/config file.  One aws login CLI command is all that is needed to authenticate as long as a profile is configured for both profiles and using the same SSO configuration.  This can be configured using the aws configure sso as seen above, or again manually configured/verified in your .aws/config file:

[profile shared-services]

sso_start_url = https://<sso url>/start

sso_region = us-east-1

sso_account_id = <account number>

sso_role_name = AWSAdministratorAccess

region = us-east-1

2. Initialize and Apply Terraform:

•     Initialize Terraform: Run terraform init to initialize the working directory, allowing Terraform to download the necessary plugins and modules.  This will install from the remote repository using the shared-services profile.

•     Apply Configuration: Execute terraform apply to create the resources defined in your Terraform configuration. Terraform will prompt you for confirmation before proceeding.  This will apply the configuration into your ‘Dev’ environment using your ‘Dev’ profile.

Conclusion

Integrating AWS SSO with the CLI, combined with the power of Terraform and AWS CodeCommit, provides a robust framework for managing AWS resources. By following the steps outlined above, developers can streamline their workflows, enhance security, and efficiently deploy and manage EC2 instances and other AWS services. This approach not only saves time but also ensures that infrastructure deployments are consistent, repeatable, and scalable and follow best practices in modular design and leveraging SSO for temporary credentials and least privilege.

Read more AWS blogs here, and find details on the AWS services TekStream offers here. And, as always, submit your questions on the form below. Thanks!