Skip to main content
Redhat Developers  Logo
  • AI

    Get started with AI

    • Red Hat AI
      Accelerate the development and deployment of enterprise AI solutions.
    • AI learning hub
      Explore learning materials and tools, organized by task.
    • AI interactive demos
      Click through scenarios with Red Hat AI, including training LLMs and more.
    • AI/ML learning paths
      Expand your OpenShift AI knowledge using these learning resources.
    • AI quickstarts
      Focused AI use cases designed for fast deployment on Red Hat AI platforms.
    • No-cost AI training
      Foundational Red Hat AI training.

    Featured resources

    • OpenShift AI learning
    • Open source AI for developers
    • AI product application development
    • Open source-powered AI/ML for hybrid cloud
    • AI and Node.js cheat sheet

    Red Hat AI Factory with NVIDIA

    • Red Hat AI Factory with NVIDIA is a co-engineered, enterprise-grade AI solution for building, deploying, and managing AI at scale across hybrid cloud environments.
    • Explore the solution
  • Learn

    Self-guided

    • Documentation
      Find answers, get step-by-step guidance, and learn how to use Red Hat products.
    • Learning paths
      Explore curated walkthroughs for common development tasks.
    • See all learning

    Hands-on

    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.
    • Interactive labs
      Learn by doing in these hands-on, browser-based experiences.
    • Interactive demos
      Click through product features in these guided tours.

    Browse by topic

    • AI/ML
    • Automation
    • Java
    • Kubernetes
    • Linux
    • See all topics

    Training & certifications

    • Courses and exams
    • Certifications
    • Skills assessments
    • Red Hat Academy
    • Learning subscription
    • Explore training
  • Build

    Get started

    • Red Hat build of Podman Desktop
      A downloadable, local development hub to experiment with our products and builds.
    • Developer Sandbox
      Spin up Red Hat's products and technologies without setup or configuration.

    Download products

    • Access product downloads to start building and testing right away.
    • Red Hat Enterprise Linux
    • Red Hat AI
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Featured

    • Red Hat build of OpenJDK
    • Red Hat JBoss Enterprise Application Platform
    • Red Hat OpenShift Dev Spaces
    • Red Hat Developer Toolset

    References

    • E-books
    • Documentation
    • Cheat sheets
    • Architecture center
  • Community

    Get involved

    • Events
    • Live AI events
    • Red Hat Summit
    • Red Hat Accelerators
    • Community discussions

    Follow along

    • Articles & blogs
    • Developer newsletter
    • Videos
    • Github

    Get help

    • Customer service
    • Customer support
    • Regional contacts
    • Find a partner

    Join the Red Hat Developer program

    • Download Red Hat products and project builds, access support documentation, learning content, and more.
    • Explore the benefits

Zero trust automation on AWS with Ansible and Terraform

No keys, no ports, no problem

September 22, 2025
Alina Buzachis
Related topics:
Application modernizationAutomation and managementDevOps
Related products:
Red Hat Ansible Automation Platform

    In the blog post What's new in cloud automation: Red Hat Ansible Certified Content Collection for amazon.aws 10.0.0, we introduced version 10.0.0 of the Red Hat Ansible Certified Content Collection for amazon.aws. We highlighted key enhancements and full support for amazon.aws.aws_ssm, a security-focused, agent-based connection plug-in that represents a significant leap forward in how we automate Amazon EC2 infrastructure.

    In this follow-up, we'll move from concepts to execution by showcasing a real-world use case where we combine the following:

    • HashiCorp Terraform for provisioning private EC2 instances
    • AWS Systems Manager (SSM) as the connection mechanism
    • Ansible automation using the new amazon.aws.aws_ssm connection plug-in and the amazon.aws.aws_ec2 dynamic inventory plug-in

    We'll explore a scenario that demonstrates the power of this plug-in in the context of Day 0, Day 1, and Day 2 operations. We'll walk through provisioning infrastructure with Terraform, then managing configuration and lifecycle tasks using Red Hat Ansible Automation Platform, all without opening a single inbound port. This flow is illustrated in Figure 1.

    This scenario aligns with modern cloud architecture trends, including zero trust networking, no-SSH environments, and compliance-driven infrastructure management.

    Automation flow: Day 0, Day 1 and Day 2 Operations
    Figure 1: Automation flow: Day 0, Day 1, and Day 2 operations.

    Embracing zero trust: Why amazon.aws.aws_ssm?

    Traditionally, managing EC2 instances has required juggling key pairs, managing SSH access, and configuring security groups—all of which introduce security complexity and operational overhead. The amazon.aws.aws_ssm connection plug-in, newly supported in the amazon.aws 10.0.0 certified collection, changes that paradigm entirely.

    By using the AWS Systems Manager (SSM) agent pre-installed on supported EC2 AMIs, this plug-in allows Ansible Automation Platform to connect over the AWS-managed control plane, eliminating the need for SSH access or public IP addresses. That means:

    • No open inbound ports, including port 22
    • No SSH keys to manage or rotate
    • No bastion hosts
    • Cloud-native logging of session activity via CloudTrail and SSM
    • Better alignment with compliance frameworks like CIS, HIPAA, or ISO 27001

    This drastically reduces your attack surface and simplifies your operational model.

    Real-world scenario: Private web servers, fully automated

    Let's consider a common scenario: Suppose your security team mandates that all EC2 instances must reside in private subnets, without public IP addresses or SSH access. You need to provision a fleet of web servers and automate their configuration—all without compromising this zero trust security posture.

    In this scenario, we'll:

    1. Provision EC2 resources with Terraform.
    2. Enable remote access via SSM.
    3. Automate software installation and configuration using Ansible over SSM.
    4. Manage both Day 1 and Day 2 tasks.

    Day 0 Operations: Security-focused provisioning with Terraform

    Our journey begins with infrastructure provisioning. Using Terraform, we define a virtual private cloud (VPC), deploy private subnets, restrict all inbound traffic via security groups, and launch EC2 instances with IAM roles that enable SSM access.

    Here's a simplified Terraform configuration:

    # Configure the AWS Provider
    provider "aws" {
      region = var.aws_region
    }
    # --- VPC and Networking Setup ---
    # Create a new VPC
    resource "aws_vpc" "zero_trust_vpc" {
      cidr_block = "10.0.0.0/16"
      tags = {
        Name    = "${var.project_name}-vpc"
        Project = var.project_name
      }
    }
    # Create a public subnet for the NAT Gateway
    resource "aws_subnet" "public_subnet" {
      vpc_id            = aws_vpc.zero_trust_vpc.id
      cidr_block        = "10.0.1.0/24"
      availability_zone = "${var.aws_region}a" # Use a specific AZ for simplicity
      tags = {
        Name    = "${var.project_name}-public-subnet"
        Project = var.project_name
      }
    }
    # Create a private subnet for the EC2 instance
    resource "aws_subnet" "private_subnet" {
      vpc_id            = aws_vpc.zero_trust_vpc.id
      cidr_block        = "10.0.2.0/24"
      availability_zone = "${var.aws_region}a" # Use a specific AZ for simplicity
      tags = {
        Name    = "${var.project_name}-private-subnet"
        Project = var.project_name
      }
    }
    # Create an Internet Gateway for the public subnet
    resource "aws_internet_gateway" "igw" {
      vpc_id = aws_vpc.zero_trust_vpc.id
      tags = {
        Name    = "${var.project_name}-igw"
        Project = var.project_name
      }
    }
    # Create an Elastic IP for the NAT Gateway
    resource "aws_eip" "nat_eip" {
      vpc        = true
      depends_on = [aws_internet_gateway.igw] # Ensure IGW exists before EIP
      tags = {
        Name    = "${var.project_name}-nat-eip"
        Project = var.project_name
      }
    }
    # Create a NAT Gateway in the public subnet
    resource "aws_nat_gateway" "nat_gateway" {
      allocation_id = aws_eip.nat_eip.id
      subnet_id     = aws_subnet.public_subnet.id
      tags = {
        Name    = "${var.project_name}-nat-gateway"
        Project = var.project_name
      }
    }
    # Create a public route table
    resource "aws_route_table" "public_rt" {
      vpc_id = aws_vpc.zero_trust_vpc.id
      tags = {
        Name    = "${var.project_name}-public-rt"
        Project = var.project_name
      }
    }
    # Add route to Internet Gateway for public route table
    resource "aws_route" "public_internet_route" {
      route_table_id         = aws_route_table.public_rt.id
      destination_cidr_block = "0.0.0.0/0"
      gateway_id             = aws_internet_gateway.igw.id
    }
    # Associate public route table with public subnet
    resource "aws_route_table_association" "public_subnet_association" {
      subnet_id      = aws_subnet.public_subnet.id
      route_table_id = aws_route_table.public_rt.id
    }
    # Create a private route table
    resource "aws_route_table" "private_rt" {
      vpc_id = aws_vpc.zero_trust_vpc.id
      tags = {
        Name    = "${var.project_name}-private-rt"
        Project = var.project_name
      }
    }
    # Add route to NAT Gateway for private route table
    resource "aws_route" "private_nat_route" {
      route_table_id         = aws_route_table.private_rt.id
      destination_cidr_block = "0.0.0.0/0"
      nat_gateway_id         = aws_nat_gateway.nat_gateway.id
    }
    # Associate private route table with private subnet
    resource "aws_route_table_association" "private_subnet_association" {
      subnet_id      = aws_subnet.private_subnet.id
      route_table_id = aws_route_table.private_rt.id
    }
    # --- Security Group for EC2 Instance ---
    # Create a security group for the EC2 instance
    resource "aws_security_group" "ec2_sg" {
      name        = "${var.project_name}-ec2-sg"
      description = "Allow outbound traffic for private EC2"
      vpc_id      = aws_vpc.zero_trust_vpc.id
      # Allow all outbound traffic (needed for updates, SSM endpoints, etc.)
      egress {
        from_port   = 0
        to_port     = 0
        protocol    = "-1"
        cidr_blocks = ["0.0.0.0/0"]
      }
      # No inbound rules needed for SSH/HTTP as we are using SSM
      # If you need specific inbound rules are needed within the VPC, add them here.
      tags = {
        Name    = "${var.project_name}-ec2-sg"
        Project = var.project_name
      }
    }
    # --- S3 Bucket ---
    resource "aws_s3_bucket" "zero_trust_bucket" {
      bucket = "${var.project_name}-ssm-bucket" # S3 bucket names must be globally unique
      tags = {
        Name    = "${var.project_name}-ssm-bucket"
        Project = var.project_name
      }
    }
    # --- IAM Role for EC2 (SSM Permissions) ---
    # Create an IAM role for the EC2 instance
    resource "aws_iam_role" "ssm_ec2_role" {
      name = "${var.project_name}-ssm-ec2-role"
      assume_role_policy = jsonencode({
        Version = "2012-10-17"
        Statement = [
          {
            Action = "sts:AssumeRole"
            Effect = "Allow"
            Principal = {
              Service = "ec2.amazonaws.com"
            }
          },
        ]
      })
      tags = {
        Name    = "${var.project_name}-ssm-ec2-role"
        Project = var.project_name
      }
    }
    # Attach the AmazonSSMManagedInstanceCore policy to the role
    resource "aws_iam_role_policy_attachment" "ssm_policy_attachment" {
      role       = aws_iam_role.ssm_ec2_role.name
      policy_arn = "arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore"
    }
    # Create an instance profile for the EC2 instance
    resource "aws_iam_instance_profile" "ssm_instance_profile" {
      name = "${var.project_name}-ssm-instance-profile"
      role = aws_iam_role.ssm_ec2_role.name
    }
    # --- EC2 Instance (Private) ---
    # Find the latest Amazon Linux 2 AMI
    data "aws_ami" "amazon_linux_2" {
      most_recent = true
      owners      = ["amazon"]
      filter {
        name   = "name"
        values = ["amzn2-ami-hvm-*-x86_64-gp2"]
      }
      filter {
        name   = "virtualization-type"
        values = ["hvm"]
      }
      filter {
        name   = "architecture"
        values = ["x86_64"]
      }
    }
    # Create the private EC2 instance
    resource "aws_instance" "private_webserver" {
      ami                         = data.aws_ami.amazon_linux_2.id
      instance_type               = var.instance_type
      subnet_id                   = aws_subnet.private_subnet.id
      vpc_security_group_ids      = [aws_security_group.ec2_sg.id]
      associate_public_ip_address = false # Crucial for zero-trust (no public IP)
      iam_instance_profile        = aws_iam_instance_profile.ssm_instance_profile.name
      tags = {
        Name    = "${var.project_name}-webserver"
        Project = var.project_name
      }
    }

    To bring this zero trust automation workflow to life, you can start by provisioning your infrastructure using the scripts provided in this GitHub repository. You can get started by cloning the repository and applying the Terraform configuration:

    git clone https://github.com/alinabuzachis/aws-ansible-zero-trust-automation.git
    cd terraform
    terraform init
    terraform apply

    This configuration ensures security-focused, SSM-enabled infrastructure is provisioned on Day 1, with no exposure to the public internet.

    Day 1 and Day 2 operations: Lifecycle automation with Ansible Automation Platform

    With the infrastructure in place and SSM connectivity configured, we now shift into Day 1 and Day 2 operations—the critical tasks that define how systems are configured, updated, and maintained over their lifecycle. These operations are where the real value of automation emerges: you're not just provisioning servers, but keeping them consistent, security-focused, and production-ready at all times.

    What sets this workflow apart is that all Ansible automation is executed via the amazon.aws.aws_ssm connection plug-in, without ever relying on SSH, key pairs, or opening inbound ports. Connections are tunneled through AWS Systems Manager (SSM), and all actions are traceable through CloudTrail and SSM session logs.

    Rather than relying on static inventory files, we'll use the amazon.aws.aws_ec2 dynamic inventory plug-in to automatically discover and group EC2 instances based on AWS tags or other metadata. This allows your Ansible Automation Platform environment to stay aligned with your cloud infrastructure—no manual updates required.

    Dynamic inventory with amazon.aws.aws_ec2: Let Ansible Automation Platform discover your infrastructure

    While you can manually track EC2 instance IDs in a static inventory, dynamic environments benefit greatly from Ansible's amazon.aws.aws_ec2 inventory plug-in. With this plug-in, Ansible Automation Platform can automatically discover and group your EC2 instances based on tags, regions, or instance attributes. This eliminates the need to update your inventory manually.

    Let's configure a dynamic inventory (aws_ec2.yml) that targets all EC2 instances tagged with Project=zero-trust-demo:

    plugin: amazon.aws.aws_ec2
    regions:
      - "eu-central-1"
    keyed_groups:
      - prefix: tags
        key: tag_
    filters:
      instance-state-name: running
      tag:Project: zero-trust-demo
    compose:
      ansible_host: instance_id
      ansible_connection: "'aws_ssm'"
      ansible_aws_ssm_bucket_name: '"zero-trust-demo-ssm-bucket"'
      ansible_aws_ssm_region: '"eu-central-1"'

    This configuration tells Ansible Automation Platform to:

    • Discover EC2 instances in the eu-central-1 region.
    • Target only instances tagged with Project=zero-trust-demo.
    • Use the EC2 instance ID as the hostname (required for SSM).
    • Automatically assign the amazon.aws.aws_ssm connection method and region per host.

    This makes your inventory flexible and fully automatic—perfect for modern infrastructure that changes frequently or spans multiple environments. This dynamic inventory adapts as your infrastructure evolves. Tag a new instance with Environment=dev, and Ansible Automation Platform will pick it up automatically. No need to manually update your inventory.

    Day 1 Ansible Playbook: Configure Apache via SSM

    Now that the infrastructure is discoverable, we can automate common configuration tasks using Ansible Automation Platform—reliably, flexibly, and at scale.

    Here's a simple example playbook (configure_web.yml) that installs and configures Apache on all matching instances:

    ---
    - name: Configure Apache on EC2 via SSM
      hosts: tag__Name_zero_trust_demo_webserver
      gather_facts: false
      tasks:
        - name: Install Apache HTTP Server
          ansible.builtin.package:
            name: httpd
            state: present
        - name: Enable and start Apache service
          ansible.builtin.service:
            name: httpd
            state: started
            enabled: true
        - name: Create a sample homepage
          ansible.builtin.copy:
            dest: /var/www/html/index.html
            content: "<h1>Welcome to Ansible over SSM!</h1>"

    This playbook runs against all instances dynamically grouped under tag__Name_zero_trust_demo_webserver, thanks to our inventory plug-in.

    You can execute this playbook in Ansible Automation Platform, which ensures that all necessary software is installed and configured on your infrastructure without requiring command-line intervention.

    Looking ahead: Security, scalability, and compliance

    This is a complete, security-focused configuration workflow, with no SSH keys, no exposed ports, and no infrastructure outside your control. You gain the full power of Ansible Automation Platform for post-deployment automation while aligning with cloud-native and zero trust principles.

    Typical Day 2 operations now become seamless:

    • Updating packages across private subnets
    • Rotating secrets without exposing endpoints
    • Applying compliance patches across fleets
    • Enforcing configuration drift remediation
    • Automating routine administrative tasks via cron jobs or scheduled playbooks

    Additionally, because all actions are routed through SSM, they are logged, monitored, and centrally auditable, which gives you better governance and compliance tracking without sacrificing agility.

    This approach scales effortlessly. Add new EC2 instances? Tag them and let your dynamic inventory detect them. Rotate credentials? Let IAM and SSM handle the heavy lifting. Need audit trails? SSM integrates with AWS CloudTrail for full session logging. Everything happens within your existing AWS IAM and logging architecture.

    Most importantly, this model aligns with evolving security expectations. Whether you're working in finance, healthcare, or any highly regulated industry, moving away from open SSH access toward network-isolated, centrally audited control is imperative.

    Final thoughts

    With the release of version 10.0.0 of the Red Hat Ansible Certified Content Collection for amazon.aws, we see a firm shift toward security-focused, cloud-native automation. Now fully supported, the amazon.aws.aws_ssm connection plug-in empowers users to automate in ways that are scalable, compliant, and operationally resilient.

    By combining HashiCorp Terraform, Red Hat Ansible Automation Platform, and SSM, you can confidently deliver Day 0, Day 1, and Day 2 operations for AWS environments that meet the highest standards of automation maturity and infrastructure security.

    Where to go next

    • Explore the latest articles about Ansible automation on Red Hat Developer and the Red Hat Blog.
    • Check out this YouTube playlist for everything about Ansible Collections.
    • If you're new to Ansible automation, download the Red Hat Certified Engineer (RHCE) Ansible Automation Study Guide (O'Reilly).
    • To learn more about Ansible Automation Platform, check out our getting started guide.

    Related Posts

    • How to create execution environments using ansible-builder

    • Set up a continuous integration pipeline with Ansible Automation Platform & GitLab

    • How to deploy Azure Red Hat OpenShift using Terraform

    • Monitor an Ansible Automation Platform database using Prometheus and Grafana

    • Patch updates on RHEL servers with Ansible Automation Platform 2.4

    • Generate Ansible Playbooks using natural language prompts

    Recent Posts

    • Federated identity across the hybrid cloud using zero trust workload identity manager

    • Confidential virtual machine storage attack scenarios

    • Introducing virtualization platform autopilot

    • Integrate zero trust workload identity manager with Red Hat OpenShift GitOps

    • Best Practice Configuration and Tuning for Linux and Windows VMs

    What’s up next?

    ansible-study-guide-ebook-tile card

    Download the Red Hat Certified Engineer (RHCE) Ansible Automation Study Guide and learn to build and operate scalable IT automation across cloud, hybrid, and edge environments.

    Get the e-book
    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Platforms

    • Red Hat AI
    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform
    • See all products

    Build

    • Developer Sandbox
    • Developer tools
    • Interactive tutorials
    • API catalog

    Quicklinks

    • Learning resources
    • E-books
    • Cheat sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site status dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2026 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Chat Support

    Please log in with your Red Hat account to access chat support.