Keep your AWS IaC inline with CloudFormation initial prep for Terraform, Jenkins, and Packer

Carlos Garcia
3 min readFeb 5, 2020

Using native IaC tools to prep your AWS account for third-party IaC stack should be of no surprise by now. With the rise of the ever so friendly HCL and the versatility of the tools, many companies are forgoing native tools such as AWS CloudFormation and going straight to using Terraform. That may not be the best move! Most of the time, the initial config and setup is done manually and thus never documented, which goes against the IaC methodology — unless of course you are keeping a repo with account config code.

To fix the missing documentation steps, we’ll use CloudFormation to deploy initial resources needed for third-party IaC Stacks. I know that some teams rather create a cross-account roles and assume it locally to deploy backend configs but I find it extremely difficult to document and I rather have a common template.

Always start with IAM…

After considering the purpose of the account and what/who is going to access the account + which resources, we can start creating the IAM roles, users, and policies.

IAM: Jenkins Role + Instance Profile

We’ve already decided that this account will host a Jenkins box to do deployments using Pipelines from Github. With that in mind, we need to include the following in our CloudFormation template:

  • Jenkins EC2 Role with “ReadOnly” access to S3. We wan to be able to fetch stuff from S3
  • Inline policy to enable our Jenkins box to both “Create” and “Read” SSM parameters. We are aiming both fetch and put sensitive information to and from our Jenkins box (SSH key for repo access, initial password, Roles, Buckets, Account Ids, etc…)

…if you want more info on including the actual instance in this template:

IAM: Packer User + Keys + SSM Parameter

This should be fairly simple; In a perfect world we’d be using a role that could only be assumed by the Jenkins box. However, at the time of publication, Packer does (did) not support role based deployment. Therefore, we’ll create a user with an inline policy using the official documentation (https://packer.io/docs/builders/amazon.html). Also, we’re going to include in our CloudFormation template a resource for access keys and SSM parameters to hold these values (make sure to use encryption), that way we can call the parameter as an input variable.

NOTE: make sure you include the following as part of the User’s inline policy. You’ll need it when giving the Packer temp instance a profile/role.

iam:GetInstanceProfile
iam:PassRole

IAM: Terraform Role (Deployment Role)

As mentioned above, we’ll use this role to make pipeline deployments. With that in mind, we’ll go ahead and include the following in our CloudFormation:

  • Terraform Role that can ONLY be assumed by the previous Jenkins Role. Permissions on this role should be limited to the resource you want to deploy — Most people would grant PowerUser but that seems like an overkill.

Note: if using cross-account access, set this up on recipient account

S3: Terraform Bucket + Bucket Policy

We need to include a S3 Bucket with SSE + Versioning enabled.

Do not forget to limit access with a Bucket Policy that only allows our Terraform Role since each pipeline deployment will assume the Terraform Role to fetch the TF State.

DynamoDB: Terraform Lock Table

This one is fairly simple, all we need is a simple table with a lock ID attribute and a schema by the same value. Minimum read/write capacity…. 5 maybe?

SSM Parameters: Bucket ARN, Terraform Role ARN, Packer Access Keys

These are the parameters we are going to pass when we perform a Packer build or Terraform init in our Jenkins Pipelines. This will allow us to not have hard coded sensitive data in our Jenkins box or our Github repos where our Jenkinsfiles will be stored.

In Conclusion…

…if the steps above are covered in an initial CloudFormation template (which can always be adjusted to accommodate cross account access), it would be much easier to have a clear understanding of the starting path rather than just doing manual setups to pick up IaC methodologies later on.

--

--

Carlos Garcia

AWS Engineer and DevOps dude. Keep it simple and to the point!