SBOMs in Action: Securing Your Golden AMIs From Build to Runtime
Learn how to build secure, immutable golden AMIs on AWS with SBOMs, Cosign signatures, and continuous validation for robust cloud security.
Join the DZone community and get the full member experience.
Join For FreeGolden Amazon Machine Images (AMIs) are the foundation for launching consistent and efficient instances in your AWS cloud environment. Ensuring their security and immutability is paramount. This guide delves into how Software Bill of Materials (SBOMs), cryptographic signing, and runtime validation create a robust framework for building and maintaining secure golden AMIs.
Steps Involved in Building Golden AMIs
Step | Description |
---|---|
Start with a Trusted Base Image | Begin by selecting a minimal, reputable base image, such as AWS-provided base AMIs that are regularly updated with the latest security patches. |
Add Necessary Packages | Install required packages using package managers like yum, apt, or pip. Ensure that packages are sourced from trusted repositories and specify version numbers for consistency. |
Configure Users and Permissions | Follow the Principle of Least Privilege when creating user accounts, removing unnecessary default users and groups. Configure SSH for key-based authentication and restrict root access. |
Functional Testing | Verify the functionality of installed software and applications, including network connectivity and essential system services, to ensure everything works as expected. |
Vulnerability Scanning | Utilize tools such as Amazon Inspector or Grype to scan the AMI for vulnerabilities. Address any critical findings promptly to mitigate potential security risks. |
Understanding Drift and Its Causes
AMI drift occurs when a running instance diverges from its original AMI configuration. This can result from ad-hoc administrator modifications, automated patching, configuration management tools like Puppet or Chef, and changes by application users. These deviations emphasize the need for ongoing monitoring and management of AMI configurations in cloud environments to maintain system consistency and security.
Detecting Drift With SBOMs
Once an EC2 instance is created from a golden AMI, maintaining its integrity is crucial. SBOMs (Software Bill of Materials) play a key role in detecting drift, which occurs when the software environment changes from its original state. By regularly generating and comparing SBOMs for the running instance against the original, any unauthorized modifications, updates, or anomalies can be quickly identified. This ensures that the instance remains consistent with the approved configuration, enhancing security and operational reliability.
Signing SBOMs for Trust and Verification
The cryptographic signing of your SBOMs adds a layer of trust and verification, ensuring:
- Authenticity: The SBOM originates from a trusted source.
- Integrity: The SBOM hasn't been tampered with.
Continuous Validation: Maintaining AMI Integrity at Runtime
Runtime validation, powered by SBOMs, continuously monitors the running instance, comparing its current state to the original signed SBOM. This proactive approach detects any unauthorized changes, triggering alerts for swift remediation.
Tools
Here are some of the tools that can be used for building AMI and validating the instances runtime.
Packer
Creates consistent machine images (VMs, Docker containers) across platforms from a single configuration, ensuring standardized environments and automating image creation.
Grype
Scans container images and file systems for vulnerabilities using Anchore's database, providing fast, detailed reports and integrating seamlessly into CI/CD pipelines.
Syft
Generates Software Bill of Materials (SBOM) from container images, revealing software components, dependencies, and licenses for enhanced security and regulatory compliance.
Cosign
Signs and verifies container images to ensure integrity and authenticity, protecting against unauthorized or tampered images and supporting various key management solutions.
Getting Started AMI Build Pipeline
Let’s dive into a simple example to demonstrate how to build a pipeline.
Workflow
Sample Code
Define Packer Template
{
"builders": [{
"type": "amazon-ebs",
"ami_name": "golden-ami-{{timestamp}}",
"instance_type": "t2.micro",
"region": "us-east-1",
"source_ami": "ami-0c55b159cbfafe1f0", // Amazon Linux 2 AMI (HVM), SSD Volume Type
// ... other configurations (VPC, subnet, etc.)
}],
"provisioners": [{
"type": "ansible",
"playbook_file": "./ansible/playbook.yml",
"user": "ec2-user" // Default user for Amazon Linux 2
}]
}
Provision With Ansible
Ansible automates configuration management. Create a playbook to install and configure software.
- name: Configure AMI
hosts: all
become: true
tasks:
- name: Update apt cache
apt: update_cache=yes
- name: Install required packages
apt: name={{ item }} state=present
loop:
- curl
- wget
- git
- name: Install security packages
apt: name={{ item }} state=present
loop:
- syft
- grype
- cosign
Setup Agents, File Systems and Permissions
- hosts: all
become: yes
tasks:
# Install CloudWatch Agent
- name: Install CloudWatch Agent
yum:
name: amazon-cloudwatch-agent
state: present
- name: Start CloudWatch Agent
service:
name: amazon-cloudwatch-agent
state: started
enabled: yes
# Set up filesystem (Example: Creating a directory)
- name: Set up filesystem (Example: Creating a directory)
file:
path: /data
state: directory
mode: '0755'
# Set permissions (Example: Granting user access)
- name: Set permissions (Example: Granting user access)
file:
path: /data
owner: ec2-user
group: ec2-user
mode: 'u+rwx,g+rx,o+rx'
# ... other configurations (software installation, security hardening, etc.)
Functional Testing
---
- name: Test setup
hosts: localhost
connection: local
tasks:
# Test: Check if Apache is installed and running
- shell: systemctl is-active --quiet httpd && systemctl is-enabled --quiet httpd
register: httpd_status
failed_when: not httpd_status.rc == 0
# Test: Check if port 80 is listening
- wait_for:
port: 80
# Test: Check drive size (Example: Root volume)
- shell: df -h /
register: df_output
failed_when: "'Size' not in df_output.stdout"
# Test: Check DHCP/IP connectivity
- shell: ping -c 1 8.8.8.8
register: ping_result
failed_when: ping_result.rc != 0
# Test: Check DNS resolution
- uri:
url: http://www.google.com
method: GET
status_code: 200
register: dns_test_result
failed_when: dns_test_result.status != 200
# Test: Check user existence
- shell: id ec2-user
register: user_check_result
failed_when: user_check_result.rc != 0
Generate and Sign SBOM
# Generate and sign SBOM
- name: Generate and sign SBOM
shell: |
syft -o cyclonedx dir:/ > /etc/sbom/golden.json
cosign generate-key-pair
cosign sign-blob --key cosign.key /etc/sbom/golden.json
cp cosign.pub /etc/sbom/cosign.pub # Store public key in AMI
Vulnerability Scanning
jobs:
vulnerability_scan:
commands:
- grype dir:/ --output json > grype_results.json
- aws securityhub batch-import-findings --findings file://grype_results.json
Continuous SBOM Validation
Include a validation script in the AMI to run continuously and detect configuration drift. During validation packages introduced by docker containers should be excluded as they are installed as part of the workload.
#!/bin/bash
GOLDEN_SBOM="/etc/sbom/golden.json"
NEW_SBOM="/tmp/current_sbom.json"
PUBLIC_KEY="/etc/sbom/cosign.pub"
# Exclude container filesystems from the scan
syft -o cyclonedx dir:/ --exclude '/var/lib/docker/**' --exclude '/run/containerd/**' --exclude '/var/run/docker.sock' > "$NEW_SBOM"
if ! cosign verify-blob --key "$PUBLIC_KEY" "$GOLDEN_SBOM"; then
# Alert: SBOM verification failed!
logger -t sbom_validation "SBOM verification failed!"
elif ! diff "$GOLDEN_SBOM" "$NEW_SBOM"; then
# Alert: SBOM drift detected!
logger -t sbom_validation "SBOM drift detected!"
fi
rm "$NEW_SBOM"
Configure the AMI to run the above script on a continuous basis using cron or another script that's running with sleep time.
Automate With CodeBuild
AWS CodeBuild automates AMI creation. Define build steps for Packer and Ansible integration.
version: 0.2
phases:
install:
runtime-versions:
python: 3.8
commands:
- pip install ansible
- curl -fsSL https://apt.releases.hashicorp.com/gpg | apt-key add -
- apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
- apt-get update && apt-get install packer
build:
commands:
- packer init .
- packer validate .
- packer build .
Conclusion
In conclusion, integrating SBOMs and runtime validation into your AMI creation process not only fortifies your infrastructure against unauthorized changes but also enhances compliance and operational efficiency. By ensuring that your cloud images remain secure, consistent, and reliable, you lay a robust foundation for scaling and maintaining a resilient cloud environment.
Opinions expressed by DZone contributors are their own.
Comments