Bootstrapping a Secure AWS as-Code Environment—Your MVS Checklist

IaC streamlined AWS as-code environments, but what about security? Enter MVS.

David Melamed writer profile image
By David Melamed
Jit Logo
Edited by Jit Team

Updated March 5, 2024.

a checklist with the words bootstrapping a secure aws as - code

This content is brought to you by Jit—a platform that simplifies continuous security for developers, enabling dev teams to adopt a ‘minimal viable security’ mindset, and build secure cloud apps by design from day 0, progressing iteratively in a just-in-time manner.

Infrastructure as Code (IaC) has changed how we manage cloud operations and made it a lot easier and quicker to roll out infrastructure on demand—with a single config file.

Besides the benefits, the underlying stack also comes with its set of security challenges when adopting the AWS anything-as-code model.

Let's talk about the best practices for secure bootstrapping AWS as-code environment—and introduce the minimum viable security (MVS) approach that delivers baseline security controls for any stack.

Embracing an Everything-as-Code Model

In line with the IaC principles, more organizations are adopting as-code frameworks for different tech stack components: security, policy, compliance, configuration, and operations.

AWS supports various as-code frameworks, including their own CloudFormation, Terraform, and Pulumi.

They have also recently rolled out their next-gen IaC in the form of AWS CDK. Now it's possible to spin up a complex cloud architecture by defining simple, code-based templates—via an API that provisions and manages resources.

With environment-as-code pipelines, organizations can leverage the same code to manage and extend their deployment environment across multiple regions and accounts, all through a single workflow.

» Boost the quality of your solutions—check the AWS Foundational Technical Review checklist

Adopting Minimum Viable Security for Baseline Security Controls

The IaC frameworks come with the benefits of automation across the entire stack for more rapid delivery and tighter controls. However, securing each environment has its challenges.

Organizations just starting up must cut through the noise surrounding security and exploits, and figure out minimum critical controls. The AWS security baseline parameters generally elude emerging companies on their way to launch the first version of a product.

To solve this, the minimum viable security (MVS) approach offers a vendor-neutral security baseline. This, in turn, reduces the complexity and overhead when deploying infrastructure, specifically cloud (native) environments.

Similar to Agile methods, MVS focuses on a minimal checklist of critical security controls.

This approach establishes a sufficient security posture, tackles the most common threats, and integrates seamlessly into existing automation tooling and pipelines used to configure complex cloud-based environments.

To demonstrate this in practice, we’ll show how the automated MVS approach works when securing AWS instances.

How to Secure AWS Environments as Code: Best Practices

At Jit, we have identified a few layers upon which to focus our AWS security controls. These provide the AWS security baseline that can be expressed as code to automate the bootstrapping of your AWS environments without compromising velocity.

The layers include:

  • Account Structure
  • Identity and Access Management
  • User Creation and Secret Management
  • Hierarchies, Governance, and Policies
  • Access Controls

Below we’ll dive into our AWS security best practices checklist and how to automate within your existing IaC and automated pipelines. Many of the practices we cover are tried, true, and applied at Jit for our own security controls.

a pink and purple web page with a cat on it

Open ASPM Platform

App + cloud security that developers love

Read reviews


SAST, SCA, secrets detection, IaC scanning, DAST, CSPM, and other product security controls

Easy for developers to adopt

Automated scanning within dev environments

Automated prioritization

Automatically surface exploitable vulnerabilities in production

Easy onboarding

Integrate Jit with your Source Code Manager to enable one-click activation for all tools

Jit empowers developers to consistently and independently resolve vulnerabilities before production with automated scanning in their environment.

Rather than requiring developers to scroll through long vulnerability backlogs in different UIs, Jit provides immediate feedback on the security of every code change within GitHub, GitLab, or VsCode.

As a result, Jit makes it exceptionally easy for developers to adopt regular security testing within their environment.

  • Unified SAST, SCA, secrets detection, IaC scanning, CSPM, DAST, and other product security controls
  • Unified execution and UX for all security tools
  • Fast and automated scanning within GitHub, GitLab, or VsCode
  • Jit’s Context Engine determines whether a vulnerability is actually exploitable in production to prevent alert fatigue and long backlogs of irrelevant vulnerabilities
  • Unified monitoring and reporting

Easy for developers to adopt

Unifies all tools

Automated vulnerability prioritization based on runtime context

Fast onboarding across all repos

Not open source

1. Build a Secure AWS Account Structure

First off, we will split our AWS accounts into three primary organizational units (OUs):

  • Users: These OUs let us host a dedicated account to set up all users.
  • Sandbox: For developing or testing new code changes; can also host accounts for experimenting with as-code templates and CI/CD pipelines.
  • Workloads: Contain staging/production environments and various accounts running external-facing services.

As cloud workloads grow, DevOps teams usually set up multiple accounts for rapid innovation and flexible controls. AWS accounts help DevOps teams achieve isolation and independence by providing natural boundaries for billing, security, and access to resources.

While building AWS accounts, we recommend the following practices:

  • Use organizational units (OUs) to group accounts into logical and hierarchical structures, based on similar and related functions.
  • Maintain the lowest possible structure depth to avoid complexity.
  • Keep a master account for managing all OUs and related billing for cost control and ease of maintenance.
  • Assign limited cloud resources, data, or workloads to an organization’s management or master account for maximum security.
  • Isolate production and non-production workload environments from each other. AWS workloads are best kept in accounts, where each account can have more than one workload.
  • By separating workload environments, administrators can secure production venues from unauthorized access.

2. Follow Identity and Access Management Practices

For managing access to and permissions for AWS resources, Identity and Access Management (IAM) offers a first line of defense by streamlining the creation of users, roles, and groups.

When provisioning an AWS environment through automation, organizations should leverage existing modules to manage IAM users, roles, and permissions.

Administering robust security through IAM relies on a set of common practices that we also apply at Jit:

  • Make sure IAM policies for a user, group, or role initially grant only the permissions needed to accomplish a given task—the approach known as “least privilege.”
  • Create separate roles for different tasks for each IAM user.
  • Use session tokens as temporary credentials for authorization. You should additionally configure a session token to have a short lifetime to prevent misuse.
  • Do not use a root user’s access key to perform regular activities or any programmatic task. You should also rotate the access key of the root user regularly.
  • If account users select their passwords, there should be a strong baseline password policy and the requirement to periodically change the password.
  • Implement multi-factor authentication (MFA) for additional security.

3. Automate User Creation with Encrypted Secrets

To cut down the risks associated with manual efforts, organizations should embrace automation for user creation. This way, all stages of the process flow—account creation, configuration, and assignment to an OU—require minimal manual intervention.

Automation also helps streamline the user experience by integrating with onboarding and offboarding user workflows.

The mechanism provides a fine balance between agility and control by permitting automated configuration and validation of IAM policies across multiple environments (dev, staging, or production).

Image description
Figure 1: A typical user creation process flow (Source: Amazon)

Apart from user creation, consider automating identity federation and secret provisioning for a comprehensive user creation cycle. A typical workflow resembles the above process flow, along with leveraging tools such as Keybase for the automatic encryption of credentials and keypairs.

4. Create AWS Account Hierarchy, Structure & Policies with AWS Organizations

AWS Organizations brings granular controls to structure accounts in a manageable way. The service offers improved flexibility and hierarchical structure to AWS resources based on organizational units (OUs).

For any AWS organization, it is best to start with a basic OU structure with core OUs like infrastructure and security.

Then, create a policy inheritance framework that allows maximum access to OUs at the foundation level. You can gradually limit access with each layer of the OU. The layering of policies can further continue to the account and instance levels.

Organizations should also apply service control policies (SCPs) on the OUs rather than individual accounts. SCPs offer a multi-layered approach to access management, with a redundant security check that takes precedence over IAM policies.

As one of the best practices, use trusted access for authorizing services across your organization. This mechanism grants permissions only to designated services without affecting the overall permissions of users or roles.

As workloads grow, include other organizational units based on common themes, such as policy staging, suspended accounts, individual users, deployments, and transitional accounts.

5. Secure Remote Access to the AWS Console

Securing remote access to the AWS console is one of the easiest—and crucial—parts of maintaining security in an AWS as-code environment.

A minimal approach here is to leverage the AWS Management Console and AWS Directory Service, and enforce IAM policies on account switching.

Once logged in, based on the user’s role (read-only or read-write access), this approach lets individual users switch accounts from within the console.

Additionally, you can also enforce MFA through a trust policy between the user’s account and the target account to ensure only users with MFA enabled can access the target account.

6. Enforce Secure Access of AWS APIs

Since the majority of API endpoints are public-facing, it is extremely important to secure them. You'd want to limit unauthenticated API routes by enforcing a robust authentication and authorization mechanism for accessing the APIs.

Apart from leveraging various AWS built-in mechanisms to safeguard both public and private API endpoints, you should also adopt minimal security controls. To this end, enable MFA to use the AWS CLI or use AWS Vault to secure keypairs.

Apart from this, there are several approaches to achieving controlled access to APIs. These include:

  • IAM-based role and policy permissions
  • Lambda authorizers
  • Client-side SSL certificates
  • Robust web application firewall (WAF) rules
  • Throttling targets
  • JWT authorizers
  • Creating resource-based policies to allow access from specific IPs or VPCs
  • API keys

» Learn about our solutions for building a modern minimum viable secure product

From MVS to AWS Security

The as-code model for various computing components allows you to automatically, consistently, and predictably spin up deployment environments using manifest files.

While the everything-as-code approach simplifies the deployment and management of resources on AWS, secure bootstrapping of AWS as-code environment can’t be ignored as part of this process. It should also benefit from the guardrails automation can provide.

The MVS approach, applied as code, is one of the solutions. The next steps would be to look at concrete code examples or bootstrap a secure AWS environment through one of the as-code frameworks, for example, Terraform.