This is a Gruntwork Script Module meant to be used with Packer to build an AMI of a hardened Linux
OS. At present, the only supported Linux distribution is Amazon Linux. If you wish to add another distribution, please
contact support@gruntwork.io.
Our OS hardening is based primarily on the guidelines described in in the Center for Internet Security Benchmarks, which are freely downloadable. For Amazon Linux, we used the
CIS Amazon Linux Benchmark, v2.0.0 06-02-2016.
Note that we have not yet implemented the entire CIS Benchmark. At present, the primary implemented OS hardening feature
is mounting multiple partitions. We hope to implement more CIS recommendations over time.
Main Components of this Module
There are two major components to this module:
ami-builder: This is a Terraform template that launches an EC2 Instance with Packer pre-installed.
partition-scripts: This is a set of bash scripts that create multiple disk partitions, format them
as ext4, and mount them to various paths with various mount options such as noexec or nosuid. These scripts are
meant to be run in a Packer template that uses the Packer amazon-chroot
builder.
Fundamentally, to generate an AMI you must:
Create a Packer template amazon-linux.json that uses the partition-scripts.
Launch the ami-builder EC2 Instance.
Copy your Packer template onto the ami-builder EC2 Instance (e.g. with scp).
SSH into the ami-builder EC2 Instance and run packer build amazon-linux.json to build the AMI.
Terminate the ami-builder EC2 Instance.
We recognize that is a lot of manual steps to build a single AMI, so check out the os-hardening example
for a pre-built Packer template plus a script (packer-build.sh) that will automate all the above steps.
Why do I need to launch a separate EC2 Instance to run Packer?
This is because we're using the Packer amazon-chroot builder.
See below for additional details on what this is and how to use it.
How to Use this Module
The best way to use this module is to substantially copy the os-hardening example code.
Unlike most Gruntwork examples, the example for this module contains a full Packer build file plus a wrapper script to
create the AMI with a single command and may be viewed as a "canonical" way to instantiate the os-hardening modules.
How to Set Your EBS Volume Size and Configure The File System Partitions You Want
Before building the AMI with Packer, you may wish to customize the particular file systems and partitions that your
hardened OS will use. Follow these steps:
Set the value of the ebs_volume_size variable in the example Packer Template (e.g. amazon-linux.json) to the
desired EBS Volume size (in GB).
Edit the Packer Template so that the following scripts specify the desired partition paths
and sizes:
partition-volume: For each desired partition, add an argument like --partition '/home:4G'. For additional
details see partition-volume. Note that for the last --partition entry only,
you may specify * for the size to tell the script to create the largest possible partition based on remaining
disk space. Also, make sure your partition sizes don't exceed the space available on your EBS Volume!
cleanup-volume: For each desired partition, add an argument like --mount-point '/home'. For additional details see
cleanup-volume
Note that you will redundantly pass the same list of partition paths to each of the above scripts, but only
partition-volume needs both the mount point and the desired partition size.
Edit the files/etc/fstab file to match the partitions from the previous step. Specify any mount options as desired.
That's it! The Packer template will take care of the rest.
How to Build the AMI with Packer
Now we're ready to build the actual AMI. Note: The os-hardening example contains a script
that automates all these steps, but, for the sake of understanding, we'll describe them individually below:
Launch the ami-builder EC2 Instance. We will execute Packer from this EC2 Instance.
On your local machine run rsync so that your local directory is continually synced to the ami-builder:
whiletrue; do rsync -azv ./packer-templates/ ec2-user@54.212.196.166:~/ami-builder; sleep 1; done
Be sure to replace the IP address above with the IP address of your EC2 Instance.
Note that it is important to actually use sudo su versus just sudo since the $PATH variables are different for
the root user versus the ec2-user user.
The AMI will now build.
When finished, terminate the ami-builder EC2 Instance.
How to Launch an AMI with an Encrypted EBS Volume
As of Packer 0.12.3, Packer supports the encrypt_boot property for the amazon-chroot builder! See Pull Request #4584.
This will allow us to build an AMI as above, except that once the AMI is ready, Packer will automatically copy the
unencrypted Snapshot as an encrypted Snapshot,
create a new AMI based on the encrypted Snapshot, and delete the original AMI and its underlying unecncrypted Snapshot.
Until Packer 0.12.3 is released, you can still set encrypt_boot to true and earlier versions of Packer will simply
ignore this property. In the meantime, consider running an EC2 Instance with the root volume unencrypted, but with
additional volumes mounted as encrypted volumes.
Using Your Hardened OS as a "Base AMI"
A best practice we encourage is to first build your hardened OS Image using these modules and the os-hardening example.
You can now view this AMI as your "base AMI", and all other Packer builds can be built on top of this AMI. For example,
you might have:
Base AMI: Hardened OS (built from stock Amazon Linux)
Bastion Host: Built from Base AMI
MongoDB Host: Built from Base AMI
In the above example, the Bastion Host and MongoDB Host Packer builds will "just work" with a single exception: By default,
Packer uploads all scripts defined in the Remote Shell Provisioner
to /tmp and then executes them. But our hardened OS most likely has the noexec option set for the /tmp file system,
which means that no code can be executed from /tmp by design!
To fix this, you must set the remote_folder property,
to a folder that is executable. For example, here we set remote_folder to /home/ec2-user:
Much of the design for this module is motivated by our need to support multiple partitions
on a single volume, an OS hardening best practice.
The Packer amazon-ebs builder
Almost all Packer builds for AWS use the amazon-ebs builder. Packer
templates that use this builder work as follows:
Packer launches a brand new EC2 Instance and waits to SSH in.
Packer executes a series of provisioners (e.g. upload files, run shell scripts).
When finished, Packer shuts down the EC2 instance.
Packer takes a snapshot.
When the snapshot is complete, Packer creates an AMI and terminates the EC2 Instance.
The primary advantage of the amazon-ebs Packer builder is simplicity and isolation. Each Packer build launches a completely
fresh EC2 Instance. The primary downsides are (1) Packer builds are slow because you have to launch a completely new
EC2 instance for each build, and (2) it is not possible to make any file system changes to the root partition because
you can't unmount the very partition on which the OS itself is running.
The Packer amazon-chroot builder
To address the shortcomings of the amazon-ebs builder, Packer also has the amazon-chroot
builder. Packer templates that use this builder work as follows:
Out-of-band from Packer, someone launches an EC2 Instance (the "host system").
From the host system, run packer build <packer-template-file>.
Packer creates an EBS Volume based on the Snapshot that's part of the source AMI specified in the Packer template,
attaches it to the host system, and mounts it.
Packer executes the chroot command against the path where the EBS Volume has been mounted, which starts a process
that now sees /path/to/ebs-volume as the / directory.
Packer executes any provisioners in the Packer template. Because most provisioners are running in the chroot
environment, they will execute directly on the EBS Volume.
When all provisioners are complete, Packer detaches the volume, takes a snapshot, and creates an AMI from the snapshot.
The Packer Remote Shell Provisioner
Most Packer builds use the remote-shell provisioner to apply
configuration. It's called the remote shell provisioner because it executes shell commands on the "remote" EC2 Instance.
When using the amazon-ebs builder, that means the newly launched EC2 Instance runs the shell commands. When using the
amazon-chroot builder, that means the commands are run from within the chroot environment.
That is, Packer will first run chroot /path/to/ebs-volume and then execute all commands. An individual program has no
knowledge that it's running in a special environment. It will simply access the typical file system paths. But we, the
omniscient operator know that in reality what this program thinks is / is actually /path/to/ebs-volume.
This way, we can configure our EC2 Instance as we typically do in a Packer build, except that all configuration commands
are actually modifying the attached EBS Volume, not our root file system.
The Packer Local Shell Provisioner
The Packer local-shell provisioner executes shell commands
from your "local" machine.
When using the amazon-ebs builder, that means shell commands run from your local machine.
When using the amazon-chroot builder, that means the commands are run from the EC2 Instance where you launched Packer.
This is significant because it means we can execute Packer commands from the host system against the attached EBS Volume.
This allows us to, for example, delete partitions from the attached EBS Volume and add new partitions. It is the only way
to use Packer to create an AMI with multiple partitions.
Module Design Decisions
This section discusses some design decisions made when creating this module.
Which Tool We Used to Partition the Disks
Our choice of tooling was influenced in large part by whether EBS Volumes were originally partitioned to support the
legacy "MBR" format, or the newer GUID Partition Table (GPT) format.
The partition format of a block device refers to how the first few blocks on the disk are structured and where the boot
loader code resides. Historically, the MBR format has been in wide use, but its primary limitation is that it does not
permit a disk size greater than 2 TB. For this reason, a newer partition table format, GPT, was invented that supports
up to 9.4 Zetabytes! Because Amazon EBS Volumes sometimes need to exceed 2 TB, the GPT format was a natural choice and
is what all modern AMIs use for their underlying EBS Volumes.
But it turns out that not all Linux disk partition management tools support the GPT format. For example, the venerable
fdisk has only "experimental" support for GPT. For that reason, we opted to use the newer gdisk.
But gdisk works with an interactive prompt, whereas we want to execute full commands as part of our Packer build. For
this reason, we use sgdisk, which implements all the same functionality of gdisk but as a pure command-line tool
and not an interactive tool.
Managing Partitions with gdisk vs. LVM
Initially, we experimented with using the LVM (Logical Volume Manager) tool to manage our partitions. LVM is a software
tool that applies a unique file system format to a large disk partition and then allows software-based management of LVM
partitions. The primary benefit to using a layer like LVM is that you can dynamically resize disk partitions (including
root!) without taking your disk offline.
This approach was originally inspired by the presentation OS Hardening and Packer,
where the speaker makes extensive use of LVM with RHEL and the Packer amazon-chroot builder.
But LVM requires that the /boot directory be mounted to a separate file system, which in turn requires that / and
/boot be on separate disk partitions. Since the default boot loader configuration for the Amazon Linux EBS Volume
expects both / and /boot on a single partition (partition #1, to be exact), separating these two directories meant
that we needed to reload the boot loader.
However, this proved unworkable. Amazon Linux uses an older version of GRUB for its boot loader, and GRUB was unable to find
the "BIOS partition" of the disk where it should write part of the boot loader configuration. After many attempts, we
eventually gave up on this direction and instead settled for using traditional "on disk" volumes formatted with gdisk.
It's likely that these issues are specific to Amazon Linux. Also, the only practical consequence of this is that disk
partitions on EBS Volumes cannot be dynamically resized without stopping the instance and separately mounting the EBS
Volume. But since we anticipate most users will use an immutable infrastructure anyway, we felt that asking users who
needed additional space to build a new AMI was not unreasonable.
Gotchas
Per the Packer docs for the amazon-chroot builder, your
provisioning scripts must not leave any processes running or Packer will be unable to unmount the filesystem.
TODO
Consider setting up new CloudWatch metrics to report available space on multiple disk partitions, not just the root
disk partition.
Questions? Ask away.
We're here to talk about our services, answer any questions, give advice, or just to chat.
{"treedata":{"name":"root","toggled":true,"children":[{"name":".circleci","children":[{"name":"config.yml","path":".circleci/config.yml","sha":"3c23fe9e149a21f65e1defe58510e041bc2fee6f"},{"name":"post-upgrade-test-results.sh","path":".circleci/post-upgrade-test-results.sh","sha":"a4867e8fbdc334b7a90259568ee41ea577fbe764"},{"name":"set-upgrade-test-vars.sh","path":".circleci/set-upgrade-test-vars.sh","sha":"04ccab865d51c1169f7ae4648c38a3d98a9889ab"}]},{"name":".editorconfig","path":".editorconfig","sha":"a5eec1063e66c4cb953cba222dd50b4d314ef3e2"},{"name":".github","children":[{"name":"ISSUE_TEMPLATE","children":[{"name":"bug_report.md","path":".github/ISSUE_TEMPLATE/bug_report.md","sha":"d2e87e27c601e423865ed660ec697082470ca60f"},{"name":"feature_request.md","path":".github/ISSUE_TEMPLATE/feature_request.md","sha":"023a33099be2336476930c96e17ff1ba5dc55348"}]},{"name":"pull_request_template.md","path":".github/pull_request_template.md","sha":"6b100e40e323b5b07f40ed30616277c51c9f4b9e"}]},{"name":".gitignore","path":".gitignore","sha":"0494e0bc6b113e3569ca7005a54aec78bc0a611a"},{"name":".patcher","children":[{"name":"patches","children":[{"name":"v0.56.0","children":[{"name":"aws-provider-3.66.0","children":[{"name":"bump_provider.sh","path":".patcher/patches/v0.56.0/aws-provider-3.66.0/bump_provider.sh","sha":"11254794eacb43659723dadaf90c9ccf7e8e4564"},{"name":"create_script_for_terraform_init.sh","path":".patcher/patches/v0.56.0/aws-provider-3.66.0/create_script_for_terraform_init.sh","sha":"ad261a37b80ce056f4c2bd9b04e62e4187de1839"},{"name":"patch.yaml","path":".patcher/patches/v0.56.0/aws-provider-3.66.0/patch.yaml","sha":"b39be600ac6d0b780c1561ececc4bad4c0b3511c"}]}]},{"name":"v0.58.0","children":[{"name":"aws-provider-3.64","children":[{"name":"bump_provider.sh","path":".patcher/patches/v0.58.0/aws-provider-3.64/bump_provider.sh","sha":"07826c7966b45767db49b4f294ed9fda2e59ec10"},{"name":"create_script_for_terraform_init.sh","path":".patcher/patches/v0.58.0/aws-provider-3.64/create_script_for_terraform_init.sh","sha":"2d47d1a18989f08bdd0f06fe9b9c05629e745e89"},{"name":"patch.yaml","path":".patcher/patches/v0.58.0/aws-provider-3.64/patch.yaml","sha":"28f54eed4264f65d8fdb8711637159ee3f4f0220"}]}]},{"name":"v0.63.0","children":[{"name":"aws-provider-4.x","children":[{"name":"bump_provider.sh","path":".patcher/patches/v0.63.0/aws-provider-4.x/bump_provider.sh","sha":"d3daee144dd21814811d998e5ae69796b9956509"},{"name":"create_script_for_terraform_init.sh","path":".patcher/patches/v0.63.0/aws-provider-4.x/create_script_for_terraform_init.sh","sha":"26262b1471d987b63dee577714840e155d97df69"},{"name":"patch.yaml","path":".patcher/patches/v0.63.0/aws-provider-4.x/patch.yaml","sha":"c5301aab2e3e3ef08a5105dcb9429d7f0d66105c"}]}]},{"name":"v0.65.0","children":[{"name":"aws-provider-4.x","children":[{"name":"bump_provider.sh","path":".patcher/patches/v0.65.0/aws-provider-4.x/bump_provider.sh","sha":"7c61315127a8c8471a2688c089e23963161d5d35"},{"name":"create_script_for_terraform_init.sh","path":".patcher/patches/v0.65.0/aws-provider-4.x/create_script_for_terraform_init.sh","sha":"68e359ce7e2e28df8560a34300a938c0fc1d78dd"},{"name":"patch.yaml","path":".patcher/patches/v0.65.0/aws-provider-4.x/patch.yaml","sha":"967cf7dd0ec1e8c046eee8d0e6c8a6f4e9bbf8c2"}]}]}]}]},{"name":".pre-commit-config.yaml","path":".pre-commit-config.yaml","sha":"c54725b8fe2e0eb30c15d29380a23f1fb58360fa"},{"name":"CODEOWNERS","path":"CODEOWNERS","sha":"8cacc352065b723bf2230b4554710b648b13e52e"},{"name":"LICENSE.txt","path":"LICENSE.txt","sha":"f4e3d9bd4717a044ed31ad847a300eee74371a78"},{"name":"README.adoc","path":"README.adoc","sha":"d3ad8c9f56609a3c88a7d27d5fa5d183c76590b0"},{"name":"_ci","children":[{"name":"output-debug-values.sh","path":"_ci/output-debug-values.sh","sha":"39d6d5f080a53f932e3b5ec970b5f268fd00e50a"}]},{"name":"_docs","children":[{"name":"auto-update.png","path":"_docs/auto-update.png","sha":"77bfd1c65de0245ac8b3c67d5b0b64fc440824bf"},{"name":"aws-cloudtrail-architecture.png","path":"_docs/aws-cloudtrail-architecture.png","sha":"a2dd9a08b8ed77744fd5febab3be7bdf633dee79"},{"name":"aws-cloudtrail.png","path":"_docs/aws-cloudtrail.png","sha":"acc7dcaf4b46ce3cef1bcc20be0329e12c320e7f"},{"name":"aws-config-architecture.png","path":"_docs/aws-config-architecture.png","sha":"721458048d5e539468c438498863a91fa96e0a85"},{"name":"aws-config-rules-architecture.png","path":"_docs/aws-config-rules-architecture.png","sha":"29fe3f20358b176e385d1bcdc0357bff2c1d5b4a"},{"name":"aws-config-rules.png","path":"_docs/aws-config-rules.png","sha":"ac3f7b35bcac949887e62aee260d9cb70edd3ae8"},{"name":"aws-config.png","path":"_docs/aws-config.png","sha":"02f4b326aef57372def4f3fafa4f0e4cec07e395"},{"name":"aws-guardduty.png","path":"_docs/aws-guardduty.png","sha":"053b92412fb8e3fb5740acc404b493fe1dd7229b"},{"name":"aws-organizations-architecture.png","path":"_docs/aws-organizations-architecture.png","sha":"bd57412fe85d3fe8d5e358db5e3b7bfef3e786a9"},{"name":"aws-organizations-icon.png","path":"_docs/aws-organizations-icon.png","sha":"b2b3fa04f51a23e5bae1b3389ffedf5e17b3cef2"},{"name":"iam-access-analyzer.png","path":"_docs/iam-access-analyzer.png","sha":"36e38e69454beae66d35b9bf25b3e5ffe1e68a25"},{"name":"kms-icon.png","path":"_docs/kms-icon.png","sha":"cd4f350a9a3fda41089928a7e396ee8924b7a901"},{"name":"multi-account-multi-region-aws-config.png","path":"_docs/multi-account-multi-region-aws-config.png","sha":"a9c813b1799fe71554c20c8fefc703792293bfe4"},{"name":"multiaccount_guardduty.png","path":"_docs/multiaccount_guardduty.png","sha":"c56b50bbb4c2a041366b430cada27b88aa02524b"},{"name":"ssh-grunt-architecture.png","path":"_docs/ssh-grunt-architecture.png","sha":"9ced8c68bcc7957e50aa016cad6c5b043a05b470"},{"name":"terminal-icon.png","path":"_docs/terminal-icon.png","sha":"df09d52d5b1176d7e231bab6c7712c3728e45c1b"}]},{"name":"codegen","children":[{"name":"README.adoc","path":"codegen/README.adoc","sha":"e2b5314b4f15a8f5b6c1b3932e73de6e87d107f0"},{"name":"core-concepts.md","path":"codegen/core-concepts.md","sha":"84b96ff7db44ca1785f27d873fb559677ceead4a"},{"name":"generate-all.sh","path":"codegen/generate-all.sh","sha":"e95f7a1fe3b75636468472cd072e0d0b559f2eb5"},{"name":"generate-aws-config","children":[{"name":".gitignore","path":"codegen/generate-aws-config/.gitignore","sha":"b488f31b176e8da6501add7ce148074af2337d91"},{"name":"main.go","path":"codegen/generate-aws-config/main.go","sha":"02caf84ae66d751d71079437aeadd93853b72431"},{"name":"static","children":[{"name":"README.adoc","path":"codegen/generate-aws-config/static/README.adoc","sha":"dc4b0dc89afdd92984fceca74f2c2e087645d019"},{"name":"core-concepts.md","path":"codegen/generate-aws-config/static/core-concepts.md","sha":"976e6424dcb277f70377f92eb2a10d0c8e595a85"},{"name":"variables.tf","path":"codegen/generate-aws-config/static/variables.tf","sha":"5d33ad42f818f943993986c0c3bb964eee84f9ba"}]},{"name":"template_data.go","path":"codegen/generate-aws-config/template_data.go","sha":"3e7e5e495a7f126b671f587554f3d4e08278801a"}]},{"name":"generate-aws-guardduty","children":[{"name":".gitignore","path":"codegen/generate-aws-guardduty/.gitignore","sha":"b488f31b176e8da6501add7ce148074af2337d91"},{"name":"main.go","path":"codegen/generate-aws-guardduty/main.go","sha":"d755b77b23bea4615d3611d314fcb2c9d87331c2"},{"name":"static","children":[{"name":"README.adoc","path":"codegen/generate-aws-guardduty/static/README.adoc","sha":"692d7135fa34922062bfa772b405afc21b3c6ea7"},{"name":"variables.tf","path":"codegen/generate-aws-guardduty/static/variables.tf","sha":"1487cf2e1ebd7ae87152a0b40ffa9f2c27271557"}]},{"name":"template_data.go","path":"codegen/generate-aws-guardduty/template_data.go","sha":"e9e92e528711c97416b9487a604bb6a4c6211d24"}]},{"name":"generate-ebs-encryption","children":[{"name":".gitignore","path":"codegen/generate-ebs-encryption/.gitignore","sha":"a3f620a6c9c87b381bf6748917bdf9542792f54b"},{"name":"main.go","path":"codegen/generate-ebs-encryption/main.go","sha":"e56b775bc9fb475053318bd1806dae6d3b313be7"},{"name":"static","children":[{"name":"README.adoc","path":"codegen/generate-ebs-encryption/static/README.adoc","sha":"86b31069c9627391411f7b6cceed08e813a7a37e"},{"name":"variables.tf","path":"codegen/generate-ebs-encryption/static/variables.tf","sha":"4bb22b9bb519462a429baea8ffea9d1a3991be26"}]},{"name":"template_data.go","path":"codegen/generate-ebs-encryption/template_data.go","sha":"fd500cf79337ab316d3c0eb466c47ba408f75346"}]},{"name":"generate-multiregion-iam-access-analyzer","children":[{"name":".gitignore","path":"codegen/generate-multiregion-iam-access-analyzer/.gitignore","sha":"045b82ea48805332afcf6edb7a52b41310f0c72c"},{"name":"main.go","path":"codegen/generate-multiregion-iam-access-analyzer/main.go","sha":"fd18cfb0632d699f02b553b02c44d5b7fdc19811"},{"name":"static","children":[{"name":"README.adoc","path":"codegen/generate-multiregion-iam-access-analyzer/static/README.adoc","sha":"d87068a71e5a6149ba32dcc1ba33070d8b83aeaa"},{"name":"core-concepts.md","path":"codegen/generate-multiregion-iam-access-analyzer/static/core-concepts.md","sha":"6bbaac3d7e62744e3fe3f511cd4ae78b212d08a8"},{"name":"variables.tf","path":"codegen/generate-multiregion-iam-access-analyzer/static/variables.tf","sha":"6e8d81aac5af0cba584e6d0884e03cfbc23ba07f"}]},{"name":"template_data.go","path":"codegen/generate-multiregion-iam-access-analyzer/template_data.go","sha":"934f6eed2001f1155777dbdf30399d2cad447c6f"}]},{"name":"generate-multiregion-kms-grant","children":[{"name":".gitignore","path":"codegen/generate-multiregion-kms-grant/.gitignore","sha":"ce81abc8eeae39683199307d44536f0a8b1b7862"},{"name":"main.go","path":"codegen/generate-multiregion-kms-grant/main.go","sha":"75bcec53d20b60c89dead42310ab854d69bd1320"},{"name":"static","children":[{"name":"README.adoc","path":"codegen/generate-multiregion-kms-grant/static/README.adoc","sha":"7c33dc779f289c34d0c72ecce7a4a60d99c38098"},{"name":"core-concepts.md","path":"codegen/generate-multiregion-kms-grant/static/core-concepts.md","sha":"3eb1725fa927a84cc2a0341335d150bf5c6e70f5"},{"name":"variables.tf","path":"codegen/generate-multiregion-kms-grant/static/variables.tf","sha":"505b2d0cb9ecf78f0364e845cab72bf0c28365d5"}]},{"name":"template_data.go","path":"codegen/generate-multiregion-kms-grant/template_data.go","sha":"290280e7d9d065b6f8d14f2635daf05cff6607fb"}]},{"name":"generate-multiregion-kms","children":[{"name":".gitignore","path":"codegen/generate-multiregion-kms/.gitignore","sha":"dd60654458233c0bdb18892c5989f1828889d55b"},{"name":"main.go","path":"codegen/generate-multiregion-kms/main.go","sha":"1ff847b9fc534027a50e059b2a99cad3da0f6604"},{"name":"static","children":[{"name":"README.adoc","path":"codegen/generate-multiregion-kms/static/README.adoc","sha":"75402e428cc30fee27dc5dd469788cf1d71320eb"},{"name":"core-concepts.md","path":"codegen/generate-multiregion-kms/static/core-concepts.md","sha":"8ba58b9a40c3aad18e2b804f53c6439b549b756d"},{"name":"variables.tf","path":"codegen/generate-multiregion-kms/static/variables.tf","sha":"b1740fb059927c65f7afd76f902ba616a921a138"}]},{"name":"template_data.go","path":"codegen/generate-multiregion-kms/template_data.go","sha":"4e3e26c551042fd93ffcad5f96f96a13ed3dbf67"}]},{"name":"generator","children":[{"name":"autogen_variables.tf.tpl.go","path":"codegen/generator/autogen_variables.tf.tpl.go","sha":"2817455872b7ca544e003936ac04723ce4573dbb"},{"name":"aws.go","path":"codegen/generator/aws.go","sha":"6deab752db1f91eac4ea704e037f7f1d9fefe55c"},{"name":"cli.go","path":"codegen/generator/cli.go","sha":"cd548e5893223b1e8de92512a6ee1d9e0866bc94"},{"name":"errors.go","path":"codegen/generator/errors.go","sha":"21fd1f6d4bef60ea9cb39939783696526ddd02e7"},{"name":"generator.go","path":"codegen/generator/generator.go","sha":"be3611002c1f2c1da3923d718adffcfd881df284"},{"name":"main.tf.tpl.go","path":"codegen/generator/main.tf.tpl.go","sha":"5cc7edcf31fc4a7d8e3c023563d82912d44ad6df"},{"name":"outputs.tf.tpl.go","path":"codegen/generator/outputs.tf.tpl.go","sha":"46860a17e8d59f4d063483a479b25bef4b05d10c"}]},{"name":"go.mod","path":"codegen/go.mod","sha":"1dd795255966bfbf4b49a00ed8d3c8a681bc7059"},{"name":"go.sum","path":"codegen/go.sum","sha":"c49382c76fbed1305c185b99bc7c040606842def"},{"name":"logging","children":[{"name":"logging.go","path":"codegen/logging/logging.go","sha":"6aaf23efa4292058dc0d2cbe470c8f985b8651e9"}]}]},{"name":"examples","children":[{"name":"auto-update","children":[{"name":"README.md","path":"examples/auto-update/README.md","sha":"d7c630c4585bad7869d55bc6c62fca248eeb521a"},{"name":"auto-update-example.json","path":"examples/auto-update/auto-update-example.json","sha":"18ca339caae31c3e313e32a63300d08c2bfc5179"}]},{"name":"aws-config-multi-region","children":[{"name":"README.md","path":"examples/aws-config-multi-region/README.md","sha":"5d472db5cdc843b494852a062d8c0880f246fcd0"},{"name":"terraform","children":[{"name":"main.tf","path":"examples/aws-config-multi-region/terraform/main.tf","sha":"a9e3492c0d6953da9be139b2303f32ebd60f573f"},{"name":"outputs.tf","path":"examples/aws-config-multi-region/terraform/outputs.tf","sha":"77ee90f69634c965b8ebed79a8d3afd6adca4db4"},{"name":"providers.tf","path":"examples/aws-config-multi-region/terraform/providers.tf","sha":"8fb43f75bddac7d9cc310b7595043f076eb616a2"},{"name":"variables.tf","path":"examples/aws-config-multi-region/terraform/variables.tf","sha":"59522bebed5385bfd208715d4933208ae9abcbec"}]},{"name":"terragrunt","children":[{"name":"terragrunt.hcl","path":"examples/aws-config-multi-region/terragrunt/terragrunt.hcl","sha":"91047c414cb580200483c039cdb5f77e01fd788c"}]}]},{"name":"aws-config-rules","children":[{"name":"README.md","path":"examples/aws-config-rules/README.md","sha":"6cd2794e82af1e3c3620d8feaed136af5358207e"},{"name":"main.tf","path":"examples/aws-config-rules/main.tf","sha":"f70a39af913afccea0f4ae4cc1834c2e58416a9a"},{"name":"outputs.tf","path":"examples/aws-config-rules/outputs.tf","sha":"4319400eb4190f58458f2dd9398225869ff08da3"},{"name":"variables.tf","path":"examples/aws-config-rules/variables.tf","sha":"7d39063bdc912f043b060e8390a72fe1b984f2c5"}]},{"name":"aws-config","children":[{"name":"README.md","path":"examples/aws-config/README.md","sha":"5d66d09633de365e154669a090edc37fc70548d1"},{"name":"main.tf","path":"examples/aws-config/main.tf","sha":"83f2a3f136c03e0d6a05fde9901b6de845ccb671"},{"name":"outputs.tf","path":"examples/aws-config/outputs.tf","sha":"ddd32698f39772d663a2d9b8a6276260f5431068"},{"name":"variables.tf","path":"examples/aws-config/variables.tf","sha":"f119464824bd2821f2c6e8917e0670010090bc34"}]},{"name":"aws-organizations","children":[{"name":"README.md","path":"examples/aws-organizations/README.md","sha":"1da3c2fc061fee6ee99564b8b2323ccf69f2c690"},{"name":"main.tf","path":"examples/aws-organizations/main.tf","sha":"2f1aa70e96530de170c9d5375f0bbf6117cb437e"},{"name":"outputs.tf","path":"examples/aws-organizations/outputs.tf","sha":"58e36aac71c1fd04d5552fa840a9b5f149dcc32a"},{"name":"variables.tf","path":"examples/aws-organizations/variables.tf","sha":"59afc28c87bc3c49d11c6faf7e112643f0a95481"}]},{"name":"cloudtrail-custom-key","children":[{"name":"README.md","path":"examples/cloudtrail-custom-key/README.md","sha":"bb376ddaca4b52bef18a5526aa9cb0465574ff7e"},{"name":"main.tf","path":"examples/cloudtrail-custom-key/main.tf","sha":"743174357faa6a56118984f942e3a3d4965e18f8"},{"name":"outputs.tf","path":"examples/cloudtrail-custom-key/outputs.tf","sha":"b6cd4e77d231018a5beb19cd3a9a4eb3f2017d64"},{"name":"variables.tf","path":"examples/cloudtrail-custom-key/variables.tf","sha":"a72f9cabc8968d84ecdd5f2a3cbd5e8e41c064f6"}]},{"name":"cloudtrail","children":[{"name":"README.md","path":"examples/cloudtrail/README.md","sha":"2fbe4b7494d970738d054910d86d0ae31718c8ec"},{"name":"main.tf","path":"examples/cloudtrail/main.tf","sha":"6967ee85f1d118188cc8f80cb66aab09f9cac5e5"},{"name":"outputs.tf","path":"examples/cloudtrail/outputs.tf","sha":"b6cd4e77d231018a5beb19cd3a9a4eb3f2017d64"},{"name":"variables.tf","path":"examples/cloudtrail/variables.tf","sha":"cbeb938286bd999d6072ef3093254e8fd435f529"}]},{"name":"cross-account-iam-roles","children":[{"name":"README.md","path":"examples/cross-account-iam-roles/README.md","sha":"bac6fd37f7f7009454a66e55e8ff377fff36aefb"},{"name":"main.tf","path":"examples/cross-account-iam-roles/main.tf","sha":"5a77161dc3bd69db7794deaceb9cfc3760bc94c4"},{"name":"outputs.tf","path":"examples/cross-account-iam-roles/outputs.tf","sha":"44af3be56d0a80e4d509fcd62c0e6dd8628072fa"},{"name":"variables.tf","path":"examples/cross-account-iam-roles/variables.tf","sha":"749900f2e1e1d18ca039847f30676461c14cb7a8"}]},{"name":"custom-iam-entity","children":[{"name":"README.md","path":"examples/custom-iam-entity/README.md","sha":"7e6c2e15f44a4ddc28ef276da4b323d2fd326a3f"},{"name":"main.tf","path":"examples/custom-iam-entity/main.tf","sha":"2dd0fdb4c2105ca92312001169bfa5cefca0a5fa"},{"name":"outputs.tf","path":"examples/custom-iam-entity/outputs.tf","sha":"835eb64f431386925438cb2f63e48e413faee90c"},{"name":"variables.tf","path":"examples/custom-iam-entity/variables.tf","sha":"098b2744c093aac9a50c36df4a88d12f4a9baa50"}]},{"name":"ebs-encryption-multi-region","children":[{"name":"README.md","path":"examples/ebs-encryption-multi-region/README.md","sha":"6052c04a4f885b2e37658652bd174a59c56273de"},{"name":"main.tf","path":"examples/ebs-encryption-multi-region/main.tf","sha":"447c9f3bc983f9a71824f8d8dbd7f0ce5a0e5d9b"},{"name":"outputs.tf","path":"examples/ebs-encryption-multi-region/outputs.tf","sha":"49520778a1fc9e5e82777cbb5aa0250e032e1817"},{"name":"providers.tf","path":"examples/ebs-encryption-multi-region/providers.tf","sha":"d29764c8ab850d04c2ae58309314c7619d7dd801"},{"name":"variables.tf","path":"examples/ebs-encryption-multi-region/variables.tf","sha":"7693921b9f8ac0a0211b69b8417ac849c6b0a6b2"}]},{"name":"fail2ban","children":[{"name":"README.md","path":"examples/fail2ban/README.md","sha":"6599f8481a3e7666ffe7924707c89b0701d57689"},{"name":"fail2ban-example.json","path":"examples/fail2ban/fail2ban-example.json","sha":"0df4338f82ea084f189152aef764d616c52f2875"},{"name":"main.tf","path":"examples/fail2ban/main.tf","sha":"c3454514556b1bcd7f905138dbc291a3e23b2d18"},{"name":"outputs.tf","path":"examples/fail2ban/outputs.tf","sha":"77a6ab8a992cd106de126f24b2950c1efa499229"},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/fail2ban/user-data/user-data.sh","sha":"460b230fb025451e06e8cdd73f83bb5bfea21110"}]},{"name":"variables.tf","path":"examples/fail2ban/variables.tf","sha":"236006c79b34f4fe3a517dd2ae8b805bfb19b6df"}]},{"name":"github-actions-iam-role","children":[{"name":"main.tf","path":"examples/github-actions-iam-role/main.tf","sha":"6b5f72389bbadc5260b3b4fb4a1b9b9d772c7bfa"},{"name":"outputs.tf","path":"examples/github-actions-iam-role/outputs.tf","sha":"d440f596aefbccbe3b4e76f8262a7201a89688c1"},{"name":"variables.tf","path":"examples/github-actions-iam-role/variables.tf","sha":"550e0459f5df591a403de1ba4b746fdda116bb70"}]},{"name":"guardduty","children":[{"name":"README.md","path":"examples/guardduty/README.md","sha":"23c75950a1b8b33286b79bd5e9d853cee02d62ea"},{"name":"main.tf","path":"examples/guardduty/main.tf","sha":"4b2b8fedf19d112db71aeb8a835c0f8adc2faacc"},{"name":"outputs.tf","path":"examples/guardduty/outputs.tf","sha":"5cdf5798a495a01ce59269dd84fa95c0dc9a548b"},{"name":"providers.tf","path":"examples/guardduty/providers.tf","sha":"d29764c8ab850d04c2ae58309314c7619d7dd801"},{"name":"variables.tf","path":"examples/guardduty/variables.tf","sha":"da5f01602e76f2febb2564e919a411d802943ce6"}]},{"name":"iam-access-analyzer-multi-region","children":[{"name":"README.md","path":"examples/iam-access-analyzer-multi-region/README.md","sha":"51c398bec469b1d95f4e59e2fb1f287fe621bf20"},{"name":"main.tf","path":"examples/iam-access-analyzer-multi-region/main.tf","sha":"5e2d7952e38b7ae8fa006bedc0729b510fa65400"},{"name":"providers.tf","path":"examples/iam-access-analyzer-multi-region/providers.tf","sha":"d29764c8ab850d04c2ae58309314c7619d7dd801"},{"name":"variables.tf","path":"examples/iam-access-analyzer-multi-region/variables.tf","sha":"63a155cedce7a2119429f3e200c4c501c7715489"}]},{"name":"iam-groups","children":[{"name":"README.md","path":"examples/iam-groups/README.md","sha":"7bd21c82fd8f28f7b3155497a0524d86ce17cfdd"},{"name":"main.tf","path":"examples/iam-groups/main.tf","sha":"09a5e9a6d29589345c6729ed42cee8023500d221"},{"name":"outputs.tf","path":"examples/iam-groups/outputs.tf","sha":"5076c13be431d7844e1ce524bcd40076450c051e"},{"name":"variables.tf","path":"examples/iam-groups/variables.tf","sha":"a7790e3207316f9e6216574fe2e0dd50fb39b767"}]},{"name":"iam-user-password-policy","children":[{"name":"README.md","path":"examples/iam-user-password-policy/README.md","sha":"bc62258833767d2e383a130c43d57a11e229af27"},{"name":"main.tf","path":"examples/iam-user-password-policy/main.tf","sha":"6195571cd760e44d41a8984cfd52a3407264d72f"},{"name":"outputs.tf","path":"examples/iam-user-password-policy/outputs.tf","sha":"36e88e92cf2568fb06a8da0453a85bcb4bd199dd"},{"name":"variables.tf","path":"examples/iam-user-password-policy/variables.tf","sha":"7f920bda19b0928773bb37203859a68453a12231"}]},{"name":"iam-users","children":[{"name":"README.md","path":"examples/iam-users/README.md","sha":"f8b65e9756e9f8c8703a854c1363be700b5fe8d9"},{"name":"main.tf","path":"examples/iam-users/main.tf","sha":"9e58a9288ebaa62cacd92dbff376ee68c0239892"},{"name":"outputs.tf","path":"examples/iam-users/outputs.tf","sha":"dfa5ea6a81c8d28ffbfb0bf34e9ee3871eb80619"},{"name":"variables.tf","path":"examples/iam-users/variables.tf","sha":"52c97ebc727f29aa1c7cbc7e3947967a04dd4e52"}]},{"name":"ip-lockdown","children":[{"name":"README.md","path":"examples/ip-lockdown/README.md","sha":"3962ba23a76d8f02e5c0ffc8cb71196991628e38"},{"name":"aws-example","children":[{"name":"README.md","path":"examples/ip-lockdown/aws-example/README.md","sha":"da44a1265bdd321d10b4a6e3471a655da91033bb"},{"name":"main.tf","path":"examples/ip-lockdown/aws-example/main.tf","sha":"3ef69d2bc78e295c4d25b989d3489b5b47d2cdfe"},{"name":"outputs.tf","path":"examples/ip-lockdown/aws-example/outputs.tf","sha":"a175a78c9a10f9f2fd9d7c84f9b304aebc1bdb41"},{"name":"user-data","children":[{"name":"user-data.sh","path":"examples/ip-lockdown/aws-example/user-data/user-data.sh","sha":"c6d308027737a434f4c96bc3eba5bd301897af62"}]},{"name":"variables.tf","path":"examples/ip-lockdown/aws-example/variables.tf","sha":"85be46b79dfe349e32974eccdc9c3206211787ac"}]},{"name":"ip-lockdown-sample.json","path":"examples/ip-lockdown/ip-lockdown-sample.json","sha":"611ce6e3fe9d0cd53682a6edf643e4b02c1a57dc"},{"name":"local-test","children":[{"name":"README.md","path":"examples/ip-lockdown/local-test/README.md","sha":"3f0e1a6483ce3155bb04dbb9a4fd76ed41486d35"},{"name":"docker-compose.yml","path":"examples/ip-lockdown/local-test/docker-compose.yml","sha":"7c8e3a5d1fd40a95ef99b4bba0911c63ed43b530"}]}]},{"name":"kms-grant-multi-region","children":[{"name":"main.tf","path":"examples/kms-grant-multi-region/main.tf","sha":"9b2670e2bb286a42a53e4adbb53294301bae73c9"},{"name":"providers.tf","path":"examples/kms-grant-multi-region/providers.tf","sha":"d29764c8ab850d04c2ae58309314c7619d7dd801"},{"name":"variables.tf","path":"examples/kms-grant-multi-region/variables.tf","sha":"5c82ac63c161e1c7e7191dbb709926da4aebb4d5"}]},{"name":"kms-master-key-multi-region","children":[{"name":"main.tf","path":"examples/kms-master-key-multi-region/main.tf","sha":"1f0ea82d9e79aee33809623ea3028b1a9f7e76a7"},{"name":"outputs.tf","path":"examples/kms-master-key-multi-region/outputs.tf","sha":"c2685a282b5ce295c2dd80a78841711a40e80dcb"},{"name":"providers.tf","path":"examples/kms-master-key-multi-region/providers.tf","sha":"d29764c8ab850d04c2ae58309314c7619d7dd801"},{"name":"variables.tf","path":"examples/kms-master-key-multi-region/variables.tf","sha":"5199b550d4a05ab5920099a9b791a0394c2c1492"}]},{"name":"kms-master-key","children":[{"name":"README.md","path":"examples/kms-master-key/README.md","sha":"821565d831f2afcf7a2ffeea9a0854fabdaae033"},{"name":"main.tf","path":"examples/kms-master-key/main.tf","sha":"b578ec3578adbf7a20780e73083972662ccd3127"},{"name":"outputs.tf","path":"examples/kms-master-key/outputs.tf","sha":"4d5fd0a19ea917beff0241f169b51417ff9935b9"},{"name":"variables.tf","path":"examples/kms-master-key/variables.tf","sha":"c1de5a7b1c0859710d1253b61baf86c4564560e3"}]},{"name":"ntp","children":[{"name":"README.md","path":"examples/ntp/README.md","sha":"b676e802c1d196f6af204d14d143b80864bccd30"},{"name":"ntp-example.json","path":"examples/ntp/ntp-example.json","sha":"019a82b1c01aaabbe5abf7ed114854202275a410"}]},{"name":"os-hardening","children":[{"name":"README.md","path":"examples/os-hardening/README.md","sha":"d311d0932f7e98b236d0dcf3d9c629a7f8b3b107"},{"name":"packer-build.sh","path":"examples/os-hardening/packer-build.sh","sha":"8a0cf99893046f648c04ad62d505746e9c3a5e95"},{"name":"packer","children":[{"name":"amazon-linux.json","path":"examples/os-hardening/packer/amazon-linux.json","sha":"d5f1bfbc81723233bfaa3f99fdff07dcf3b1025a"},{"name":"files","children":[{"name":"etc","children":[{"name":"fstab","path":"examples/os-hardening/packer/files/etc/fstab","sha":"cbf68cec68a92bc54f514dd0d6906f19cea857e6"}]}]}]},{"name":"terraform","children":[{"name":"main.tf","path":"examples/os-hardening/terraform/main.tf","sha":"9b8efb7b2c907b793a3f2c9eb0d77c183def2609"},{"name":"outputs.tf","path":"examples/os-hardening/terraform/outputs.tf","sha":"33083aed25a4ed6e323bf84381b896614814c9d1"},{"name":"variables.tf","path":"examples/os-hardening/terraform/variables.tf","sha":"25d9e4a3ecf236434b71fd2eac179fa27cdb8587"}]}]},{"name":"private-s3-bucket-with-replication","children":[{"name":"README.md","path":"examples/private-s3-bucket-with-replication/README.md","sha":"8e47c9c013750aab08f8200383a9a468af233816"},{"name":"main.tf","path":"examples/private-s3-bucket-with-replication/main.tf","sha":"06000fd72a68af3a885e3eaf552b505d1f7d196b"},{"name":"outputs.tf","path":"examples/private-s3-bucket-with-replication/outputs.tf","sha":"e0ca6c1c51d90124a0f6aa588f2286106766f7e7"},{"name":"variables.tf","path":"examples/private-s3-bucket-with-replication/variables.tf","sha":"ce9cb926cc79a19e527ec6b6b8f918232dad4168"}]},{"name":"private-s3-bucket","children":[{"name":"README.md","path":"examples/private-s3-bucket/README.md","sha":"5214e6225de5e051cb2842fa2eb6e04a92184a10"},{"name":"main.tf","path":"examples/private-s3-bucket/main.tf","sha":"2fac2d7c83fbfe7ccf3c69f229765d544f9d5728"},{"name":"outputs.tf","path":"examples/private-s3-bucket/outputs.tf","sha":"efddeeb33901e91f4f28a438afb3455f2cca5e18"},{"name":"variables.tf","path":"examples/private-s3-bucket/variables.tf","sha":"ce9cb926cc79a19e527ec6b6b8f918232dad4168"}]},{"name":"saml-iam-roles","children":[{"name":"README.md","path":"examples/saml-iam-roles/README.md","sha":"b4ef2b28d5704aec892ea54cc28a61fbb46378c9"},{"name":"main.tf","path":"examples/saml-iam-roles/main.tf","sha":"725f640fc72010e545cf04600d3a8d8f45ec2c64"},{"name":"outputs.tf","path":"examples/saml-iam-roles/outputs.tf","sha":"1bd4fec9529cddfd2d3f61bba60f9dfb8b286c70"},{"name":"saml-metadata.xml","path":"examples/saml-iam-roles/saml-metadata.xml","sha":"88596cfde52242a43559c79216a1c60b2ea12903"},{"name":"variables.tf","path":"examples/saml-iam-roles/variables.tf","sha":"28705aa859940aa4b8027a19fe0b5b4affba939e"}]},{"name":"secrets-manager-resource-policies","children":[{"name":"README.md","path":"examples/secrets-manager-resource-policies/README.md","sha":"289a83c28bd9142fc7bbb4e603a4b25b4c9c1b98"},{"name":"main.tf","path":"examples/secrets-manager-resource-policies/main.tf","sha":"3f6255090706eb80d1fb68e2386c32590c0fd380"},{"name":"variables.tf","path":"examples/secrets-manager-resource-policies/variables.tf","sha":"d6f5c45fbc2173475cec7c4e77ac8f5caed4dc27"}]},{"name":"ssh-grunt","children":[{"name":"iam","children":[{"name":"README.md","path":"examples/ssh-grunt/iam/README.md","sha":"b1ae6d51c6f6d3eeb7df2b51dab8d0d238f53132"},{"name":"main.tf","path":"examples/ssh-grunt/iam/main.tf","sha":"2a2cb5b8b8b5168fdcf67cff2552f61bdfff89e4"},{"name":"outputs.tf","path":"examples/ssh-grunt/iam/outputs.tf","sha":"978b316044d417393b70100a427de1068c4d417f"},{"name":"variables.tf","path":"examples/ssh-grunt/iam/variables.tf","sha":"1ee58afdef7dad43bb3fb221995cc3daf631177b"}]},{"name":"packer","children":[{"name":"README.md","path":"examples/ssh-grunt/packer/README.md","sha":"b44b220f168e6e682bbf5f68065b8269a706fca5"},{"name":"build-binary.sh","path":"examples/ssh-grunt/packer/build-binary.sh","sha":"fe84ead78eb3e87e4855272f28c83d681c58ffff"},{"name":"ssh-grunt-iam.json","path":"examples/ssh-grunt/packer/ssh-grunt-iam.json","sha":"a38a0fdd4db72b49a323ed00956c4971fec9b860"}]}]},{"name":"ssm-healthchecks-iam-permissions","children":[{"name":"README.md","path":"examples/ssm-healthchecks-iam-permissions/README.md","sha":"f1fe555a3aff887a966def0a1d3ccaff3dd826e7"},{"name":"main.tf","path":"examples/ssm-healthchecks-iam-permissions/main.tf","sha":"269701289f3e73e77fc98c035c714ef8eb1e352b"},{"name":"outputs.tf","path":"examples/ssm-healthchecks-iam-permissions/outputs.tf","sha":"52688c3a4f1f8349500505fb8949fa0d21c385a3"},{"name":"variables.tf","path":"examples/ssm-healthchecks-iam-permissions/variables.tf","sha":"217574c100974ae601b2a1478e0ac183d351d4a0"}]}]},{"name":"modules","children":[{"name":"_deprecated","children":[{"name":"account-baseline-app","children":[{"name":"README.md","path":"modules/_deprecated/account-baseline-app/README.md","sha":"289d35b15becbf5164ee355fecd892edf12c60bc"}]},{"name":"account-baseline-root","children":[{"name":"README.md","path":"modules/_deprecated/account-baseline-root/README.md","sha":"0ac4e867ee61387b76475d7eb36bba673a30fd76"}]},{"name":"account-baseline-security","children":[{"name":"README.md","path":"modules/_deprecated/account-baseline-security/README.md","sha":"ace992c3b31b9320aa1d559bbde597cc945c4430"}]},{"name":"custom-iam-group","children":[{"name":"README.md","path":"modules/_deprecated/custom-iam-group/README.md","sha":"e7a0ff783eb1052aa77fe50d7eaa6a06d2d82649"}]}]},{"name":"auto-update","children":[{"name":"README.adoc","path":"modules/auto-update/README.adoc","sha":"1e193ac18cb6a1863518b95d621a7802b09c1fab"},{"name":"core-concepts.md","path":"modules/auto-update/core-concepts.md","sha":"0e4dd35dc4b7320764f203b5cc91e55ecaa9b0be"},{"name":"install-scripts","children":[{"name":"configure-auto-update","path":"modules/auto-update/install-scripts/configure-auto-update","sha":"9557efec90bf62cbcd0360198ec2bf984a8a873b"},{"name":"unattended_upgrades_config.txt","path":"modules/auto-update/install-scripts/unattended_upgrades_config.txt","sha":"abe88fd8a5037ce518bec69a6cac0699cb421d47"},{"name":"yum_cron_config.txt","path":"modules/auto-update/install-scripts/yum_cron_config.txt","sha":"e7ef4273f1b2af0c9c032fadaacd03130ba5ea78"}]},{"name":"install.sh","path":"modules/auto-update/install.sh","sha":"7c19fd0d04b11c358af64149b3169d6b2c5e3b58"}]},{"name":"aws-auth","children":[{"name":"AWS-AUTH-1PASSWORD.md","path":"modules/aws-auth/AWS-AUTH-1PASSWORD.md","sha":"d7a63db66ddf11b485a2850069d52edf6bea37eb"},{"name":"AWS-AUTH-LASTPASS.md","path":"modules/aws-auth/AWS-AUTH-LASTPASS.md","sha":"d9b65d95892c1e2275894eb2ca3dd8f334a3a8b8"},{"name":"README.md","path":"modules/aws-auth/README.md","sha":"10f5164db2016bda84383b598e0262a188a39599"},{"name":"bin","children":[{"name":"aws-auth","path":"modules/aws-auth/bin/aws-auth","sha":"85039ffd1720f9b93a34e8998852bdd3b9502bcc"}]},{"name":"install.sh","path":"modules/aws-auth/install.sh","sha":"ab9611d92d6822ceed981bdff3766724366037f0"}]},{"name":"aws-config-bucket","children":[{"name":"README.md","path":"modules/aws-config-bucket/README.md","sha":"2988d934e16617289522a4ea711ee07589ce96d7"},{"name":"main.tf","path":"modules/aws-config-bucket/main.tf","sha":"3d41ab68188251d2cb7dbe321fb3b55dfd69bdb3"},{"name":"outputs.tf","path":"modules/aws-config-bucket/outputs.tf","sha":"8ac7ab1c4c5ded586bee63ce460b25cd60eb4a18"},{"name":"variables.tf","path":"modules/aws-config-bucket/variables.tf","sha":"ba6b30c18ca75ab991f42abb845ef89af8e9cb6e"}]},{"name":"aws-config-multi-region","children":[{"name":"README.adoc","path":"modules/aws-config-multi-region/README.adoc","sha":"dc4b0dc89afdd92984fceca74f2c2e087645d019"},{"name":"core-concepts.md","path":"modules/aws-config-multi-region/core-concepts.md","sha":"976e6424dcb277f70377f92eb2a10d0c8e595a85"},{"name":"main.tf","path":"modules/aws-config-multi-region/main.tf","sha":"d7ac1d3264074d426ae6685031b5b7611b449e48"},{"name":"outputs.tf","path":"modules/aws-config-multi-region/outputs.tf","sha":"e076d643a4e3e28452332f7cc20ae6667b6cb6ac"},{"name":"variables.autogen.tf","path":"modules/aws-config-multi-region/variables.autogen.tf","sha":"3ea138065b8386950e13b049c9532d185c145f76"},{"name":"variables.tf","path":"modules/aws-config-multi-region/variables.tf","sha":"5d33ad42f818f943993986c0c3bb964eee84f9ba"}]},{"name":"aws-config-rules","children":[{"name":"README.adoc","path":"modules/aws-config-rules/README.adoc","sha":"2b550ac006ee6189aef5221748d03339bcf9806e"},{"name":"core-concepts.md","path":"modules/aws-config-rules/core-concepts.md","sha":"af111230b6262be339d220c7b2308493781fef49"},{"name":"main.tf","path":"modules/aws-config-rules/main.tf","sha":"b5b25b8a6e7bc7a70c5e87d3a6e2ef223171e60d"},{"name":"outputs.tf","path":"modules/aws-config-rules/outputs.tf","sha":"c297ad118d46f79f286d6577770ab46e59555ccb"},{"name":"variables.tf","path":"modules/aws-config-rules/variables.tf","sha":"e0645e3cfa20c357ae31401a32b7ea2d81d30d5b"}]},{"name":"aws-config","children":[{"name":"README.adoc","path":"modules/aws-config/README.adoc","sha":"191a82102e5fc9778d777052fc9efd616ddeb9db"},{"name":"core-concepts.md","path":"modules/aws-config/core-concepts.md","sha":"e5a7b8646bab42398ff7f5224549e528ce8c0d52"},{"name":"main.tf","path":"modules/aws-config/main.tf","sha":"2ef8fad8fd327c5494fa016439e3bd173249f2ca"},{"name":"outputs.tf","path":"modules/aws-config/outputs.tf","sha":"bcd505e4ac4102bc09750adb36c99398a06eb1a6"},{"name":"variables.tf","path":"modules/aws-config/variables.tf","sha":"97c21e72f615ed79b47ea325cf00e9c0495d2bab"}]},{"name":"aws-organizations","children":[{"name":"README.adoc","path":"modules/aws-organizations/README.adoc","sha":"52cda8fa0eaa15b00e5f389ba9dfb73a1f3c9d56"},{"name":"core-concepts.md","path":"modules/aws-organizations/core-concepts.md","sha":"8766c8f36eef9e8992bf13a44f6571261c43995d"},{"name":"main.tf","path":"modules/aws-organizations/main.tf","sha":"f4bff4da26d9be496b792a85b9587081a6eb3794"},{"name":"outputs.tf","path":"modules/aws-organizations/outputs.tf","sha":"feed57b33ab7eb9b100712647942f1a8d7245b3d"},{"name":"variables.tf","path":"modules/aws-organizations/variables.tf","sha":"cf9e1673e458c5c7644b1e94e128eddb6feca0d3"}]},{"name":"cloudtrail-bucket","children":[{"name":"README.md","path":"modules/cloudtrail-bucket/README.md","sha":"acc86c32958e8f6d90944e714a7731a82f404c82"},{"name":"main.tf","path":"modules/cloudtrail-bucket/main.tf","sha":"b4e8a105e9a5dce61b894139a97e5144d88c7e51"},{"name":"outputs.tf","path":"modules/cloudtrail-bucket/outputs.tf","sha":"1e560e9b0cc1c8f40e81d5fe8bbbf1c03258fdae"},{"name":"variables.tf","path":"modules/cloudtrail-bucket/variables.tf","sha":"abe69efe79ef2ad95f6e8264440e23c983c8f3f4"}]},{"name":"cloudtrail","children":[{"name":"README.adoc","path":"modules/cloudtrail/README.adoc","sha":"b3090f9aa7b062f2028af50c3da17a3293ef3cd2"},{"name":"core-concepts.md","path":"modules/cloudtrail/core-concepts.md","sha":"debe79403a177aaf1de5396c85213652dbc85481"},{"name":"main.tf","path":"modules/cloudtrail/main.tf","sha":"f97c846e112702e0eb828116a3266cbb0c2ed024"},{"name":"outputs.tf","path":"modules/cloudtrail/outputs.tf","sha":"d161a32bbcd6f824955c273c49ef9e00bcdb57b3"},{"name":"variables.tf","path":"modules/cloudtrail/variables.tf","sha":"5e2cd8457afba74fcacde56ed828c3130eb04dbb"}]},{"name":"cross-account-iam-roles","children":[{"name":"README.md","path":"modules/cross-account-iam-roles/README.md","sha":"31af5c1ebf70060948de6073188d169fb9c5a87c"},{"name":"main.tf","path":"modules/cross-account-iam-roles/main.tf","sha":"c92047d7d95c60a6f1a6e80d05f4ad21eb5f23d6"},{"name":"outputs.tf","path":"modules/cross-account-iam-roles/outputs.tf","sha":"4e4697d3c627fc668206d03557f8d58b3f391465"},{"name":"variables.tf","path":"modules/cross-account-iam-roles/variables.tf","sha":"ad26db1accff0dd3751f72009aa29284692370a0"}]},{"name":"custom-iam-entity","children":[{"name":"README.md","path":"modules/custom-iam-entity/README.md","sha":"a4dedbd0cbaad6561eaf42774054c4c640cbb478"},{"name":"main.tf","path":"modules/custom-iam-entity/main.tf","sha":"71605479a558f3fd62b0e58bff1ebda19b1d7cf6"},{"name":"outputs.tf","path":"modules/custom-iam-entity/outputs.tf","sha":"b94249803e78991682b8542d8f39e5a728432b97"},{"name":"variables.tf","path":"modules/custom-iam-entity/variables.tf","sha":"a9dc17f7ccdf58c57aaee13764304504c6cd4055"}]},{"name":"ebs-encryption-multi-region","children":[{"name":"README.adoc","path":"modules/ebs-encryption-multi-region/README.adoc","sha":"86b31069c9627391411f7b6cceed08e813a7a37e"},{"name":"main.tf","path":"modules/ebs-encryption-multi-region/main.tf","sha":"8f74a90b006638b657187845e84becc63546cfee"},{"name":"outputs.tf","path":"modules/ebs-encryption-multi-region/outputs.tf","sha":"0263a12a0cf37116db77ec5ac43667a76bac0706"},{"name":"variables.autogen.tf","path":"modules/ebs-encryption-multi-region/variables.autogen.tf","sha":"e016bd3d20f933e3b802d5facfd9665055f5140b"},{"name":"variables.tf","path":"modules/ebs-encryption-multi-region/variables.tf","sha":"4bb22b9bb519462a429baea8ffea9d1a3991be26"}]},{"name":"ebs-encryption","children":[{"name":"README.md","path":"modules/ebs-encryption/README.md","sha":"f9f23a71b7725648a9fdc9300de92d38014e6f63"},{"name":"main.tf","path":"modules/ebs-encryption/main.tf","sha":"b2ace130274d8f88ca442288cbfc4386eabc9ce0"},{"name":"outputs.tf","path":"modules/ebs-encryption/outputs.tf","sha":"6caa6eba337ae7aa9ad7db82dbd2cf6223f42cb9"},{"name":"variables.tf","path":"modules/ebs-encryption/variables.tf","sha":"d47c23a0c98c7561fcf0d95fa22fc40b34182bf9"}]},{"name":"fail2ban","children":[{"name":"README.md","path":"modules/fail2ban/README.md","sha":"e4cd7c70b170022b2e306289d4e8b949c58dd6ab"},{"name":"install-scripts","children":[{"name":"cloudwatch-metric.conf","path":"modules/fail2ban/install-scripts/cloudwatch-metric.conf","sha":"b2fb301180aeb253f5168a6fedd3e5c44b6938ff"},{"name":"configure-fail2ban","path":"modules/fail2ban/install-scripts/configure-fail2ban","sha":"013f563aaae09316e59eb1682e53738a66aa48d4"},{"name":"fail2ban.local","path":"modules/fail2ban/install-scripts/fail2ban.local","sha":"ea80bf8058a1f9bb1a80a59031981b2a37445750"},{"name":"filters.sshd.amazon.conf","path":"modules/fail2ban/install-scripts/filters.sshd.amazon.conf","sha":"093bb1baf88a1e283a43b7dd7d04c64992abecc6"},{"name":"jail.amazon.local","path":"modules/fail2ban/install-scripts/jail.amazon.local","sha":"1284b66ca5a007b77a40c27b66662425e7fe8c91"},{"name":"jail.amazon2.local","path":"modules/fail2ban/install-scripts/jail.amazon2.local","sha":"8f0285c493c406aa0db98f40b8bf9aa238f52353"},{"name":"jail.ubuntu.local","path":"modules/fail2ban/install-scripts/jail.ubuntu.local","sha":"b3485d20a2b1fad7949167d30eff2b4caf357d81"}]},{"name":"install.sh","path":"modules/fail2ban/install.sh","sha":"8f7b536f08506dabc2f6beb6cd5a50f7282168aa"},{"name":"user-data-scripts","children":[{"name":"configure-fail2ban-cloudwatch.sh","path":"modules/fail2ban/user-data-scripts/configure-fail2ban-cloudwatch.sh","sha":"5c112c70c078b769f3ae31e71334499d0e5be64a"}]}]},{"name":"github-actions-iam-role","children":[{"name":"README.md","path":"modules/github-actions-iam-role/README.md","sha":"295142b48d9430e2579c234a2f385405fcb079de"},{"name":"main.tf","path":"modules/github-actions-iam-role/main.tf","sha":"39e82c59b82965054bd95cce7383732f0f1b7f45"},{"name":"outputs.tf","path":"modules/github-actions-iam-role/outputs.tf","sha":"250c983710c438ae022187a43f73f1f9fec00b61"},{"name":"variables.tf","path":"modules/github-actions-iam-role/variables.tf","sha":"d6215f0803fb2af7fe8f3ab3ebfec420ce5231a9"}]},{"name":"guardduty-multi-region","children":[{"name":"README.adoc","path":"modules/guardduty-multi-region/README.adoc","sha":"692d7135fa34922062bfa772b405afc21b3c6ea7"},{"name":"main.tf","path":"modules/guardduty-multi-region/main.tf","sha":"a18ffe91e1f17be889c313156f6da3248b2e118b"},{"name":"outputs.tf","path":"modules/guardduty-multi-region/outputs.tf","sha":"0c2d2b518a4a61c71785a136187708e76d5b6bf8"},{"name":"variables.autogen.tf","path":"modules/guardduty-multi-region/variables.autogen.tf","sha":"05bf9410cb4878450e9e67b90b202437a7458a04"},{"name":"variables.tf","path":"modules/guardduty-multi-region/variables.tf","sha":"1487cf2e1ebd7ae87152a0b40ffa9f2c27271557"}]},{"name":"guardduty","children":[{"name":"README.adoc","path":"modules/guardduty/README.adoc","sha":"940d62d35069bdda503cac175a01bd1743f53494"},{"name":"core-concepts.md","path":"modules/guardduty/core-concepts.md","sha":"df82af9ce24cd9d73e4ca09688bf35a66d38c91a"},{"name":"main.tf","path":"modules/guardduty/main.tf","sha":"294df3dc32666232f8eb768e37836145c99e1096"},{"name":"outputs.tf","path":"modules/guardduty/outputs.tf","sha":"0fd6fdc76d8bc1bb4c544028c802248999d309f7"},{"name":"variables.tf","path":"modules/guardduty/variables.tf","sha":"e6bac32a169d2f30b27c339ed3caf36b38146171"}]},{"name":"iam-access-analyzer-multi-region","children":[{"name":"README.adoc","path":"modules/iam-access-analyzer-multi-region/README.adoc","sha":"d87068a71e5a6149ba32dcc1ba33070d8b83aeaa"},{"name":"core-concepts.md","path":"modules/iam-access-analyzer-multi-region/core-concepts.md","sha":"6bbaac3d7e62744e3fe3f511cd4ae78b212d08a8"},{"name":"main.tf","path":"modules/iam-access-analyzer-multi-region/main.tf","sha":"6e5bd96f790c2c79852e70d2adc4ee20449cc7ae"},{"name":"outputs.tf","path":"modules/iam-access-analyzer-multi-region/outputs.tf","sha":"0a4379e38beae72541e7e975f297584db7e98b04"},{"name":"variables.autogen.tf","path":"modules/iam-access-analyzer-multi-region/variables.autogen.tf","sha":"5fe91b51970b05ebc2fdbf4542a806e8c3f792f4"},{"name":"variables.tf","path":"modules/iam-access-analyzer-multi-region/variables.tf","sha":"6e8d81aac5af0cba584e6d0884e03cfbc23ba07f"}]},{"name":"iam-groups","children":[{"name":"README.md","path":"modules/iam-groups/README.md","sha":"07820342d38caf90b08a1ff0df904298ed132c8f"},{"name":"_docs","children":[{"name":"iam-user-access-to-billing.png","path":"modules/iam-groups/_docs/iam-user-access-to-billing.png","sha":"063f6cf8dc766b4d44942de89660e8ab9e1f3d63"},{"name":"my-account.png","path":"modules/iam-groups/_docs/my-account.png","sha":"387320200ed756ce4191afef87f0ab76e2c3d89a"}]},{"name":"main.tf","path":"modules/iam-groups/main.tf","sha":"179ac7371a08fd80432bfe64b1e4dc813247d81c"},{"name":"outputs.tf","path":"modules/iam-groups/outputs.tf","sha":"0fc97269b51e6c51647aa5420198d1d11c5afa37"},{"name":"variables.tf","path":"modules/iam-groups/variables.tf","sha":"b44cce3a58cf651cfa37ead33156b3b794021a40"}]},{"name":"iam-policies","children":[{"name":"README.md","path":"modules/iam-policies/README.md","sha":"0297e14a7dfdf5727d9be5ab4f47dcf67357b247"},{"name":"main.tf","path":"modules/iam-policies/main.tf","sha":"8cdc6c4fa0e72419a5636301b05501cffa8f261d"},{"name":"outputs.tf","path":"modules/iam-policies/outputs.tf","sha":"19511cfc28b22103cb164c6df8b5b530e7e3e172"},{"name":"variables.tf","path":"modules/iam-policies/variables.tf","sha":"8801af9087c945960705d082a2325200f78dfceb"}]},{"name":"iam-user-password-policy","children":[{"name":"README.md","path":"modules/iam-user-password-policy/README.md","sha":"5bea6ba56fc796be5b860549156a3a251735fc2a"},{"name":"main.tf","path":"modules/iam-user-password-policy/main.tf","sha":"a5c4546bbfdc4d7e989ccf50ccf958c88bb96345"},{"name":"outputs.tf","path":"modules/iam-user-password-policy/outputs.tf","sha":"825547bd9d41fed1cc1b3506c17f81c48b1bfd1a"},{"name":"variables.tf","path":"modules/iam-user-password-policy/variables.tf","sha":"568582c249e3cfd7899ea23b8b58e43328c9d100"}]},{"name":"iam-users","children":[{"name":"README.md","path":"modules/iam-users/README.md","sha":"ea820bd205fdb8ca28bb0e2eccc29700b99a2b94"},{"name":"main.tf","path":"modules/iam-users/main.tf","sha":"9849c627aad5a685f9da52a39d6ddc383ca981da"},{"name":"outputs.tf","path":"modules/iam-users/outputs.tf","sha":"b319eacce6916f4904b15d8ff5ea5be09afc29e2"},{"name":"variables.tf","path":"modules/iam-users/variables.tf","sha":"892e7b2aaa5179e83a5e3126dbf2551fd421b133"}]},{"name":"ip-lockdown","children":[{"name":"README.md","path":"modules/ip-lockdown/README.md","sha":"7ec92da38b5b06af9e61ab164bb6b4b0470ed92a"},{"name":"install.sh","path":"modules/ip-lockdown/install.sh","sha":"ce61af763bee9ad29754220ae24521f22c3a956f"},{"name":"ip-lockdown","path":"modules/ip-lockdown/ip-lockdown","sha":"93a0e1f5876e7de5778c595e8801d64986cb118b"}]},{"name":"kms-cmk-replica","children":[{"name":"README.md","path":"modules/kms-cmk-replica/README.md","sha":"9e9827df4990a6967edbcab6f35214ba229d7b18"},{"name":"main.tf","path":"modules/kms-cmk-replica/main.tf","sha":"e4eebc8b19bb3338cb8fcc186ce1b4695882b40e"},{"name":"outputs.tf","path":"modules/kms-cmk-replica/outputs.tf","sha":"28066251cbac14ae30a24d83f4ab38a550ce08ba"},{"name":"variables.tf","path":"modules/kms-cmk-replica/variables.tf","sha":"3de5459e12a3fc271230c8be243dbdbb9c6ded47"}]},{"name":"kms-grant-multi-region","children":[{"name":"README.adoc","path":"modules/kms-grant-multi-region/README.adoc","sha":"7c33dc779f289c34d0c72ecce7a4a60d99c38098"},{"name":"core-concepts.md","path":"modules/kms-grant-multi-region/core-concepts.md","sha":"3eb1725fa927a84cc2a0341335d150bf5c6e70f5"},{"name":"main.tf","path":"modules/kms-grant-multi-region/main.tf","sha":"0738f7e7eb923d17ec0d06f4a084b391266328f0"},{"name":"outputs.tf","path":"modules/kms-grant-multi-region/outputs.tf","sha":"b9d84078afacb154536292bddba4afbd6c9158c2"},{"name":"variables.autogen.tf","path":"modules/kms-grant-multi-region/variables.autogen.tf","sha":"185d6c42c1ab4843292b2c911e057303ae971739"},{"name":"variables.tf","path":"modules/kms-grant-multi-region/variables.tf","sha":"505b2d0cb9ecf78f0364e845cab72bf0c28365d5"}]},{"name":"kms-master-key-multi-region","children":[{"name":"README.adoc","path":"modules/kms-master-key-multi-region/README.adoc","sha":"75402e428cc30fee27dc5dd469788cf1d71320eb"},{"name":"core-concepts.md","path":"modules/kms-master-key-multi-region/core-concepts.md","sha":"8ba58b9a40c3aad18e2b804f53c6439b549b756d"},{"name":"main.tf","path":"modules/kms-master-key-multi-region/main.tf","sha":"f985176537beed7d9ce1f5672f081dd796f4286d"},{"name":"outputs.tf","path":"modules/kms-master-key-multi-region/outputs.tf","sha":"a47481aa5718ff67a44b86192edf897c160e06ed"},{"name":"variables.autogen.tf","path":"modules/kms-master-key-multi-region/variables.autogen.tf","sha":"fd024d55097a7eee5fbb6ffc65b376fbdfe57c89"},{"name":"variables.tf","path":"modules/kms-master-key-multi-region/variables.tf","sha":"b1740fb059927c65f7afd76f902ba616a921a138"}]},{"name":"kms-master-key","children":[{"name":"README.md","path":"modules/kms-master-key/README.md","sha":"1b43a005494f12b05551adb020a31726f28e10d3"},{"name":"main.tf","path":"modules/kms-master-key/main.tf","sha":"33b547ed031533f37aec6c34c1fb3fa085c24bb4"},{"name":"outputs.tf","path":"modules/kms-master-key/outputs.tf","sha":"4d0dbba81e8186243d96a8325a5f643d87543451"},{"name":"variables.tf","path":"modules/kms-master-key/variables.tf","sha":"ec5e19663b361ef9f58448b5b8ae1911073c0881"}]},{"name":"ntp","children":[{"name":"README.md","path":"modules/ntp/README.md","sha":"31112a11cff027ba074d454f5a23c5ce3e839c11"},{"name":"install.sh","path":"modules/ntp/install.sh","sha":"a8b042233bc89629c31b82a9433c013b709b8d82"}]},{"name":"os-hardening","children":[{"name":"README.md","path":"modules/os-hardening/README.md","sha":"3e864b0e9208eb6809adf41968c51e02fc233ee1","toggled":true},{"name":"_docs","children":[{"name":"Helpful Email.md","path":"modules/os-hardening/_docs/Helpful Email.md","sha":"246a0b80b29f5ff3d2b2f4c5c170fc927e2d9dd7"}]},{"name":"ami-builder","children":[{"name":"files","children":[{"name":"user-data.sh.template","path":"modules/os-hardening/ami-builder/files/user-data.sh.template","sha":"4a3c87a19e1a4caa20b9b425b2a02101566d1166"}]},{"name":"main.tf","path":"modules/os-hardening/ami-builder/main.tf","sha":"49c7e4fdac93990831b090727804c4ae216066c7"},{"name":"outputs.tf","path":"modules/os-hardening/ami-builder/outputs.tf","sha":"8ce2ee598124ca50dd530a33aa60f5d1452a4a2b"},{"name":"variables.tf","path":"modules/os-hardening/ami-builder/variables.tf","sha":"d760f34eeae322790865c1cb30dfe20d0225328f"}]},{"name":"partition-scripts","children":[{"name":"README.md","path":"modules/os-hardening/partition-scripts/README.md","sha":"b55df29c7a3d6dc3ecbbbfe4ab4b8749f053f00b"},{"name":"bin","children":[{"name":"cleanup-volume","path":"modules/os-hardening/partition-scripts/bin/cleanup-volume","sha":"c7cbf3ecebd915235238557d27a1ce25e6fc10fa"},{"name":"partition-volume","path":"modules/os-hardening/partition-scripts/bin/partition-volume","sha":"f4f8566a1ef6aa4ff0c0268bd28721488aa6dfc4"}]},{"name":"install.sh","path":"modules/os-hardening/partition-scripts/install.sh","sha":"606776c068260836e8612a681ff4e3edc8abdb41"}]}],"toggled":true},{"name":"private-s3-bucket","children":[{"name":"README.md","path":"modules/private-s3-bucket/README.md","sha":"cd44b2d3e4627ff00fffd217bd3ec36341a72a36"},{"name":"main.tf","path":"modules/private-s3-bucket/main.tf","sha":"005255d098f8ac23cba57edf700a0168e34baba4"},{"name":"mfa-delete-script","children":[{"name":"mfa-delete.sh","path":"modules/private-s3-bucket/mfa-delete-script/mfa-delete.sh","sha":"7dbcc65412467a036756562024cfc84ad128b215"}]},{"name":"outputs.tf","path":"modules/private-s3-bucket/outputs.tf","sha":"b3c780d841a1dab914a71f59381efc6583cc01a0"},{"name":"variables.tf","path":"modules/private-s3-bucket/variables.tf","sha":"6270b16a350afb1ba05d63ef31d134c8e6d4e7aa"}]},{"name":"saml-iam-roles","children":[{"name":"README.md","path":"modules/saml-iam-roles/README.md","sha":"5ebc8c20f781a0f0b5654decdcf9bd607fee65b3"},{"name":"main.tf","path":"modules/saml-iam-roles/main.tf","sha":"e9e43297457fc0f201cbd9f879190b24f7b01268"},{"name":"outputs.tf","path":"modules/saml-iam-roles/outputs.tf","sha":"c579901907b216c55e4c815d28f0a22171a960e6"},{"name":"variables.tf","path":"modules/saml-iam-roles/variables.tf","sha":"1f3f26ade9fd75d8e66ba12649f45d075b5e0f2b"}]},{"name":"secrets-manager-resource-policies","children":[{"name":"README.md","path":"modules/secrets-manager-resource-policies/README.md","sha":"b894ce3171c28ae91acbfe6bdcec35615c599bbb"},{"name":"main.tf","path":"modules/secrets-manager-resource-policies/main.tf","sha":"e063dbabd7d8fec039fd30fef048ba6bcb53a98a"},{"name":"outputs.tf","path":"modules/secrets-manager-resource-policies/outputs.tf","sha":"8b237f325d54b84ac2453e8945f61cdf0d24b41b"},{"name":"variables.tf","path":"modules/secrets-manager-resource-policies/variables.tf","sha":"2b45ef099c805c1265e5dc611c138de4a40141eb"}]},{"name":"ssh-grunt-selinux-policy","children":[{"name":"README.md","path":"modules/ssh-grunt-selinux-policy/README.md","sha":"53f02f57185efebc35d6ebfe156ce73d02a5f112"},{"name":"install.sh","path":"modules/ssh-grunt-selinux-policy/install.sh","sha":"3de871d61a9990e7f2c130f23afaf00daeb6bbef"},{"name":"ssh-grunt.pp","path":"modules/ssh-grunt-selinux-policy/ssh-grunt.pp","sha":"7c7050f812cd0e3cb34e37b88c35fb09f369be7d"},{"name":"ssh-grunt.te","path":"modules/ssh-grunt-selinux-policy/ssh-grunt.te","sha":"3317a71feaa633662a00b1dc05b1176cb85c9793"}]},{"name":"ssh-grunt","children":[{"name":".dockerignore","path":"modules/ssh-grunt/.dockerignore","sha":"a725465aee245635a2bd129af54858ed32c84cb8"},{"name":"Dockerfile","path":"modules/ssh-grunt/Dockerfile","sha":"196dc492dafc4980f07c0ea0a3a4647a56198a1b"},{"name":"README.adoc","path":"modules/ssh-grunt/README.adoc","sha":"c6bb05207d3884b1e70620408d69175027a7f989"},{"name":"_ci","children":[{"name":"build-and-test.sh","path":"modules/ssh-grunt/_ci/build-and-test.sh","sha":"903993de2d7bcde19d472fa5e510ee862d4b10c3"},{"name":"test.sh","path":"modules/ssh-grunt/_ci/test.sh","sha":"235603944316e81f1da1cc0248b80beecf99cb27"}]},{"name":"_docs","children":[{"name":"houston-upload-ssh-key.png","path":"modules/ssh-grunt/_docs/houston-upload-ssh-key.png","sha":"e32519497262f9796a4ea46c53953923975cbd7d"},{"name":"iam-upload-ssh-key.png","path":"modules/ssh-grunt/_docs/iam-upload-ssh-key.png","sha":"8bb1e793185eb0b4822023552899874394342f21"}]},{"name":"core-concepts.md","path":"modules/ssh-grunt/core-concepts.md","sha":"8c7b359b4fbfd52aa18124efe06f1304edbf2db2"},{"name":"docker-compose.yml","path":"modules/ssh-grunt/docker-compose.yml","sha":"74a2c67f6b9dc838ff3bd9c9c5aa68c813db1f0d"},{"name":"go.mod","path":"modules/ssh-grunt/go.mod","sha":"bda6dbbf16a6c96f758ec164f01791e147d7768e"},{"name":"go.sum","path":"modules/ssh-grunt/go.sum","sha":"3fb7ee290aabdc716f9e233293037bd9fcc32d12"},{"name":"scripts","children":[{"name":"build-linux-binary.sh","path":"modules/ssh-grunt/scripts/build-linux-binary.sh","sha":"2d91cbed3db40f419e6a440ce2735b9d3f2d048b"},{"name":"run.sh","path":"modules/ssh-grunt/scripts/run.sh","sha":"050027e034cd03e53625986eb0f331c043492cf6"}]},{"name":"src","children":[{"name":"cli.go","path":"modules/ssh-grunt/src/cli.go","sha":"d12bfb946f3c5268afbc9ac012134e831b2a3ec7"},{"name":"cli_test.go","path":"modules/ssh-grunt/src/cli_test.go","sha":"3925077baf4f54a539d135de17956f4f252ab5cf"},{"name":"collections.go","path":"modules/ssh-grunt/src/collections.go","sha":"aa9b67f00f57088f9bf4e129dcc53003524dd0a7"},{"name":"cron.go","path":"modules/ssh-grunt/src/cron.go","sha":"4ceb8efd0cdf51b5170bb152b6824fc54f8d429c"},{"name":"cron_test.go","path":"modules/ssh-grunt/src/cron_test.go","sha":"c56766eda2ee2201589796292fd0bb6416a6e0b3"},{"name":"ec2_instance_connect.go","path":"modules/ssh-grunt/src/ec2_instance_connect.go","sha":"99c31ddd2ee34d18dd9e676ec22eef5eebc3187f"},{"name":"errors.go","path":"modules/ssh-grunt/src/errors.go","sha":"1175435b45a980a5ff23dd4bdc880b4d63b24d79"},{"name":"file.go","path":"modules/ssh-grunt/src/file.go","sha":"eb991fd15ac2c3660313e6d4c5669b36ccc9cc21"},{"name":"groups.go","path":"modules/ssh-grunt/src/groups.go","sha":"49e569a80abb6306ab0f7fd79c810d2e2ad8ab3a"},{"name":"groups_test.go","path":"modules/ssh-grunt/src/groups_test.go","sha":"b060ded1c37d1b636b7dc59d5071049e640d00e7"},{"name":"houston.go","path":"modules/ssh-grunt/src/houston.go","sha":"d307bc1372ec78219d20222e972c1e3892fd29b0"},{"name":"houston_test.go","path":"modules/ssh-grunt/src/houston_test.go","sha":"82a9b2d2d41e09b6949897ed989a483fc7e0a650"},{"name":"iam.go","path":"modules/ssh-grunt/src/iam.go","sha":"dafbc8fbb732d2d6212cade786eb13d7215b9862"},{"name":"iam_test.go","path":"modules/ssh-grunt/src/iam_test.go","sha":"0382c08562fc329876267cf944195f3d8c8738be"},{"name":"logger.go","path":"modules/ssh-grunt/src/logger.go","sha":"93095ba8216709b3178fcc44a76421a765f4e302"},{"name":"main.go","path":"modules/ssh-grunt/src/main.go","sha":"a89d9402d32d371dc9b945ab9c72996808d17b85"},{"name":"shell.go","path":"modules/ssh-grunt/src/shell.go","sha":"7f49eeee4119efde0bd58d7c78fd4ef785dc5f6c"},{"name":"ssh.go","path":"modules/ssh-grunt/src/ssh.go","sha":"8e6b62d6c33279aaf5af6cabacd0afc4d186ca97"},{"name":"ssh_test.go","path":"modules/ssh-grunt/src/ssh_test.go","sha":"d0dee4b55d3cfc7a1c06bed3cfedeeae07b660c5"},{"name":"string.go","path":"modules/ssh-grunt/src/string.go","sha":"fc61ca9625f9d654c2b3576ff932db1b90ae9dfe"},{"name":"string_test.go","path":"modules/ssh-grunt/src/string_test.go","sha":"752aaaa776d25ff8a3e694588edb3e7c0ce4eb27"},{"name":"sync.go","path":"modules/ssh-grunt/src/sync.go","sha":"7c2f9ff292b484a7ca1ab14e1bbd558cd24553f2"},{"name":"sync_test.go","path":"modules/ssh-grunt/src/sync_test.go","sha":"09dd89b492cc7373c49b8b2fc16b17914065340f"},{"name":"url.go","path":"modules/ssh-grunt/src/url.go","sha":"0af5ddc5f3e27af95d6f6ddd41acf0c229962f7f"},{"name":"url_test.go","path":"modules/ssh-grunt/src/url_test.go","sha":"95e062eaaca09900949e0352fffc7b6f9a3524cc"},{"name":"users.go","path":"modules/ssh-grunt/src/users.go","sha":"6c3a8a22006a91656fcc5fd31d684271cdf129e3"},{"name":"users_test.go","path":"modules/ssh-grunt/src/users_test.go","sha":"e695204896bae7436e20a6615a484ae4cc6cf2f7"}]}]},{"name":"ssh-iam","children":[{"name":"README.md","path":"modules/ssh-iam/README.md","sha":"4aa06d6a729e53384b6d2a43c06ee38807092f32"}]},{"name":"ssm-healthchecks-iam-permissions","children":[{"name":"README.md","path":"modules/ssm-healthchecks-iam-permissions/README.md","sha":"0a97288d14b005662ae642819eeadb2aaff24534"},{"name":"main.tf","path":"modules/ssm-healthchecks-iam-permissions/main.tf","sha":"664b884793145b1c9f68c1da7a58650ed21dcdb3"},{"name":"variables.tf","path":"modules/ssm-healthchecks-iam-permissions/variables.tf","sha":"36778c58999e05f20468d118f22e8c9d754b1a4d"}]},{"name":"tls-cert-private","children":[{"name":"Dockerfile","path":"modules/tls-cert-private/Dockerfile","sha":"bc6b1c28764936758a47ceedccf790b56200d6cf"},{"name":"README.md","path":"modules/tls-cert-private/README.md","sha":"c6996ec25d7d9b1ab4f79d8164a14e86e1ac844f"},{"name":"docker-compose.yml","path":"modules/tls-cert-private/docker-compose.yml","sha":"f872026e8d51ceaab2e1c11cc9cf9c35ba81f29c"},{"name":"files","children":[{"name":"openssl.cnf","path":"modules/tls-cert-private/files/openssl.cnf","sha":"2542542c80ab180c47d3e0a27dbded65bed572de"}]},{"name":"scripts","children":[{"name":"generate-ca-keypair.sh","path":"modules/tls-cert-private/scripts/generate-ca-keypair.sh","sha":"395ee97c0e499c660efac5c5cf1f79dfcdbb69f8"},{"name":"generate-tls-keypair.sh","path":"modules/tls-cert-private/scripts/generate-tls-keypair.sh","sha":"f1c3577437fd589087704a9c003de416cb87d232"},{"name":"main.sh","path":"modules/tls-cert-private/scripts/main.sh","sha":"dc7af965ffb783bbef449010818e69294fa2ef75"}]}]}],"toggled":true},{"name":"terraform-cloud-enterprise-private-module-registry-placeholder.tf","path":"terraform-cloud-enterprise-private-module-registry-placeholder.tf","sha":"ae586c0fe830819580e1009d41a9074f16e65bed"},{"name":"test","children":[{"name":"README.md","path":"test/README.md","sha":"b44e2152ea21d65a8c51bb58321e18ec7527c22e"},{"name":"common","children":[{"name":"test_helpers.go","path":"test/common/test_helpers.go","sha":"aa7ea914a7ee084653fe6c7cbf0149d67db9a20b"}]},{"name":"go.mod","path":"test/go.mod","sha":"a342107f3af54b23aaddcbda6d4cf5d0a377e8a9"},{"name":"go.sum","path":"test/go.sum","sha":"9d1b3c898ae1c311f398d6ba069fbebbdc843d01"},{"name":"landingzone","children":[{"name":"aws_config_rules_test.go","path":"test/landingzone/aws_config_rules_test.go","sha":"e198464d094ef43a2ff5dc85da38c6cfc3d92fa8"},{"name":"aws_config_test.go","path":"test/landingzone/aws_config_test.go","sha":"622a46b0733a9018e87642187aa19a10f473b48a"},{"name":"aws_organizations_test.go","path":"test/landingzone/aws_organizations_test.go","sha":"7f4e93e798860d91f590c22cfa2efde0bf4777ac"},{"name":"ebs_encryption_multi_region_test.go","path":"test/landingzone/ebs_encryption_multi_region_test.go","sha":"d871d48ac13e4b36e9f05eccf90e9462d2c985e7"},{"name":"guardduty_test.go","path":"test/landingzone/guardduty_test.go","sha":"e6a63db172bfd239017385805fe7e8a1b7502bd3"},{"name":"iam_access_analyzer_multiregion_test.go","path":"test/landingzone/iam_access_analyzer_multiregion_test.go","sha":"bc8233bf962282e84b1a3bcf1fc88a0267531e7a"},{"name":"kms_grant_multiregion_test.go","path":"test/landingzone/kms_grant_multiregion_test.go","sha":"dacdaaef67b5b2b849d6c1bc54bccb3f89e1f008"},{"name":"kms_master_key_multiregion_test.go","path":"test/landingzone/kms_master_key_multiregion_test.go","sha":"6c1146b64cb38991b07e19d107b3371666a2cdf9"},{"name":"test_helpers.go","path":"test/landingzone/test_helpers.go","sha":"36d75ca20f1d1040a91d85c71b2133b92acfab3f"}]},{"name":"security","children":[{"name":"auto_update_test.go","path":"test/security/auto_update_test.go","sha":"b0bf3c446844977c5eeec5f43b49de7c6788f47a"},{"name":"cloudtrail_test.go","path":"test/security/cloudtrail_test.go","sha":"944ac0b5c5aa56a9a2ae09c729063a52164fbb21"},{"name":"cross_account_iam_roles_test.go","path":"test/security/cross_account_iam_roles_test.go","sha":"8d17070460824787a4619f2d585b0cebd7f6ad37"},{"name":"custom_iam_entity_test.go","path":"test/security/custom_iam_entity_test.go","sha":"f0c38f5b0d671fd740e8530b28c94e5fe5219d26"},{"name":"fail2ban_test.go","path":"test/security/fail2ban_test.go","sha":"f6425c375c96455e39c85d0df8b830beff839791"},{"name":"github_actions_iam_role_test.go","path":"test/security/github_actions_iam_role_test.go","sha":"a9cd953165bb27889ceadbae553aa116ca8cfd08"},{"name":"iam_groups_test.go","path":"test/security/iam_groups_test.go","sha":"7beb1ffcf37b1a778f61b8d26767fd7a85bfba2b"},{"name":"iam_ssm_test.go","path":"test/security/iam_ssm_test.go","sha":"28a81aab9873bb6bd02d2f37bdc3ef9c7f27b3c5"},{"name":"iam_user_password_policy_test.go","path":"test/security/iam_user_password_policy_test.go","sha":"5a44f18c469c936fa51b4e9d7911404e1ab76a0f"},{"name":"iam_users_test.go","path":"test/security/iam_users_test.go","sha":"1cd395b72942f05e03959978a72a782d0dd530bd"},{"name":"ip-lockdown-test-scripts","children":[{"name":"allow-several-users.sh","path":"test/security/ip-lockdown-test-scripts/allow-several-users.sh","sha":"2f75dbe0880ed0907b43db58b6ac030a0d0e9bd4"},{"name":"common.sh","path":"test/security/ip-lockdown-test-scripts/common.sh","sha":"cdfe11aca76607a4feaf254a394f32273b738c5c"},{"name":"index.html","path":"test/security/ip-lockdown-test-scripts/index.html","sha":"557db03de997c86a4a028e1ebd3a1ceb225be238"},{"name":"restrict-all-users.sh","path":"test/security/ip-lockdown-test-scripts/restrict-all-users.sh","sha":"a37c1ffc90f2532e7cc3f9f5a859b75c98661dc6"},{"name":"restrict-one-user.sh","path":"test/security/ip-lockdown-test-scripts/restrict-one-user.sh","sha":"4214e1c15102f4568d1e995aa82add46ee430237"},{"name":"sanity-check.sh","path":"test/security/ip-lockdown-test-scripts/sanity-check.sh","sha":"542ed72f4f0952ace67c9cbf2e5ac07e81e6870c"}]},{"name":"ip_lockdown_test.go","path":"test/security/ip_lockdown_test.go","sha":"7c560698928bacec9590ecc770c71daf969643a7"},{"name":"kms_master_key_test.go","path":"test/security/kms_master_key_test.go","sha":"751dfa23eaa391b567f023c6d1a12a4400a55c28"},{"name":"ntp_test.go","path":"test/security/ntp_test.go","sha":"372edab033e653c151b1c2e3b10d9bc13229515c"},{"name":"os_hardening_test.go","path":"test/security/os_hardening_test.go","sha":"ced303f74cd6908bbd8837cc99f317293707ab30"},{"name":"private_s3_bucket_test.go","path":"test/security/private_s3_bucket_test.go","sha":"677eabc59ad7faa3dd04d0fa7ecb78c1967cded8"},{"name":"saml_iam_roles_test.go","path":"test/security/saml_iam_roles_test.go","sha":"efbe2f3e6e9b0da73d1fb58fccc5f5fc1427a61f"},{"name":"secrets_manager_resource_policies_test.go","path":"test/security/secrets_manager_resource_policies_test.go","sha":"07f69b66238517d1f8af61eb9751248372997b70"},{"name":"ssh_grunt_iam_test.go","path":"test/security/ssh_grunt_iam_test.go","sha":"a7d9809f1cdb10fe63db762726dc1a0fd86286e3"},{"name":"test_helpers.go","path":"test/security/test_helpers.go","sha":"31d39e85b352b770cef5a5a00aaa31f659e21e0f"},{"name":"test_helpers_aws_auth.go","path":"test/security/test_helpers_aws_auth.go","sha":"461efcc040ff5024b9fa0762ffcde92081fac163"},{"name":"tls_cert_private_test.go","path":"test/security/tls_cert_private_test.go","sha":"70b2c873f20876497b4a1a0a030871e037dca995"}]},{"name":"upgrades","children":[{"name":"upgrade_test.go","path":"test/upgrades/upgrade_test.go","sha":"513d765d89dc45ae83dffe0f5833617d4c927ffa"}]},{"name":"validation","children":[{"name":"validate_all_modules_and_examples_test.go","path":"test/validation/validate_all_modules_and_examples_test.go","sha":"53877e64494aad3d4063e01c8009eee731e667c3"}]}]}]},"detailsContent":"<h1 class=\"preview__body--title\" id=\"os-hardening\">OS Hardening</h1><div class=\"preview__body--border\"></div><p>This is a Gruntwork Script Module meant to be used with <a href=\"http://packer.io\" class=\"preview__body--description--blue\" target=\"_blank\">Packer</a> to build an AMI of a hardened Linux\nOS. At present, the only supported Linux distribution is Amazon Linux. If you wish to add another distribution, please\ncontact support@gruntwork.io.</p>\n<p>Our OS hardening is based primarily on the guidelines described in in the <a href=\"https://benchmarks.cisecurity.org/downloads/benchmarks/\" class=\"preview__body--description--blue\" target=\"_blank\">Center for Internet Security Benchmarks</a>, which are freely downloadable. For Amazon Linux, we used the\n<strong>CIS Amazon Linux Benchmark, v2.0.0 06-02-2016</strong>.</p>\n<p>Note that we have not yet implemented the entire CIS Benchmark. At present, the primary implemented OS hardening feature\nis mounting multiple partitions. We hope to implement more CIS recommendations over time.</p>\n<h2 class=\"preview__body--subtitle\" id=\"main-components-of-this-module\">Main Components of this Module</h2>\n<p>There are two major components to this module:</p>\n<ul>\n<li><a href=\"/repos/v0.46.2/module-security/modules/os-hardening/ami-builder\" class=\"preview__body--description--blue\">ami-builder</a>: This is a Terraform template that launches an EC2 Instance with Packer pre-installed.</li>\n<li><a href=\"/repos/v0.46.2/module-security/modules/os-hardening/partition-scripts\" class=\"preview__body--description--blue\">partition-scripts</a>: This is a set of bash scripts that create multiple disk partitions, format them\nas ext4, and mount them to various paths with various mount options such as <code>noexec</code> or <code>nosuid</code>. These scripts are\nmeant to be run in a Packer template that uses the Packer <a href=\"https://www.packer.io/docs/builders/amazon-chroot.html\" class=\"preview__body--description--blue\" target=\"_blank\">amazon-chroot</a>\nbuilder.</li>\n</ul>\n<p>Fundamentally, to generate an AMI you must:</p>\n<ol>\n<li>Create a Packer template <code>amazon-linux.json</code> that uses the partition-scripts.</li>\n<li>Launch the ami-builder EC2 Instance.</li>\n<li>Copy your Packer template onto the ami-builder EC2 Instance (e.g. with <code>scp</code>).</li>\n<li>SSH into the ami-builder EC2 Instance and run <code>packer build amazon-linux.json</code> to build the AMI.</li>\n<li>Terminate the ami-builder EC2 Instance.</li>\n</ol>\n<p>We recognize that is a lot of manual steps to build a single AMI, so check out the <a href=\"/repos/v0.46.2/module-security/examples/os-hardening\" class=\"preview__body--description--blue\">os-hardening example</a>\nfor a pre-built Packer template plus a script (<code>packer-build.sh</code>) that will automate all the above steps.</p>\n<h3 class=\"preview__body--subtitle\" id=\"why-do-i-need-to-launch-a-separate-ec-2-instance-to-run-packer\">Why do I need to launch a separate EC2 Instance to run Packer?</h3>\n<p>This is because we're using the Packer <a href=\"https://www.packer.io/docs/builders/amazon-chroot.html\" class=\"preview__body--description--blue\" target=\"_blank\">amazon-chroot</a> builder.\nSee below for additional details on what this is and how to use it.</p>\n<h2 class=\"preview__body--subtitle\" id=\"how-to-use-this-module\">How to Use this Module</h2>\n<p><strong>The best way to use this module is to substantially copy the <a href=\"/repos/v0.46.2/module-security/examples/os-hardening\" class=\"preview__body--description--blue\">os-hardening example code</a>.\nUnlike most Gruntwork examples, the example for this module contains a full Packer build file plus a wrapper script to\ncreate the AMI with a single command and may be viewed as a "canonical" way to instantiate the os-hardening modules.</strong></p>\n<h3 class=\"preview__body--subtitle\" id=\"how-to-set-your-ebs-volume-size-and-configure-the-file-system-partitions-you-want\">How to Set Your EBS Volume Size and Configure The File System Partitions You Want</h3>\n<p>Before building the AMI with Packer, you may wish to customize the particular file systems and partitions that your\nhardened OS will use. Follow these steps:</p>\n<ol>\n<li>\n<p>Set the value of the <code>ebs_volume_size</code> variable in the example Packer Template (e.g. <code>amazon-linux.json</code>) to the\ndesired EBS Volume size (in GB).</p>\n</li>\n<li>\n<p>Edit the Packer Template so that the following scripts specify the desired partition paths\nand sizes:</p>\n<ul>\n<li><code>partition-volume</code>: For each desired partition, add an argument like <code>--partition '/home:4G'</code>. For additional\ndetails see <a href=\"/repos/v0.46.2/module-security/modules/os-hardening/partition-scripts/bin/partition-volume\" class=\"preview__body--description--blue\">partition-volume</a>. Note that for the last <code>--partition</code> entry only,\nyou may specify <code>*</code> for the size to tell the script to create the largest possible partition based on remaining\ndisk space. Also, make sure your partition sizes don't exceed the space available on your EBS Volume!</li>\n<li><code>cleanup-volume</code>: For each desired partition, add an argument like <code>--mount-point '/home'</code>. For additional details see\n<a href=\"/repos/v0.46.2/module-security/modules/os-hardening/partition-scripts/bin/cleanup-volume\" class=\"preview__body--description--blue\">cleanup-volume</a></li>\n</ul>\n<p>Note that you will redundantly pass the same list of partition paths to each of the above scripts, but only\n<code>partition-volume</code> needs both the mount point <em>and</em> the desired partition size.</p>\n</li>\n<li>\n<p>Edit the <code>files/etc/fstab</code> file to match the partitions from the previous step. Specify any mount options as desired.</p>\n</li>\n</ol>\n<p>That's it! The Packer template will take care of the rest.</p>\n<h3 class=\"preview__body--subtitle\" id=\"how-to-build-the-ami-with-packer\">How to Build the AMI with Packer</h3>\n<p>Now we're ready to build the actual AMI. Note: The <a href=\"/repos/v0.46.2/module-security/examples/os-hardening\" class=\"preview__body--description--blue\">os-hardening example</a> contains a script\nthat automates all these steps, but, for the sake of understanding, we'll describe them individually below:</p>\n<ol>\n<li>\n<p>Launch the <a href=\"/repos/v0.46.2/module-security/modules/os-hardening/ami-builder\" class=\"preview__body--description--blue\">ami-builder</a> EC2 Instance. We will execute Packer from this EC2 Instance.</p>\n</li>\n<li>\n<p>On your local machine run <code>rsync</code> so that your local directory is continually synced to the ami-builder:</p>\n<pre><span class=\"hljs-keyword\">while</span> <span class=\"hljs-keyword\">true</span>; <span class=\"hljs-keyword\">do</span> rsync -azv ./packer-templates/ ec2-user<span class=\"hljs-variable\">@54</span>.<span class=\"hljs-number\">212.196</span>.<span class=\"hljs-number\">166</span><span class=\"hljs-symbol\">:~/ami-builder</span>; sleep <span class=\"hljs-number\">1</span>; done\n</pre>\n<p>Be sure to replace the IP address above with the IP address of your EC2 Instance.</p>\n</li>\n<li>\n<p>From the ami-builder EC2 Instance, run Packer:</p>\n<pre><span class=\"hljs-attr\">cd</span> <span class=\"hljs-string\">/home/ec2-user/ami-builder</span>\n<span class=\"hljs-attr\">sudo</span> <span class=\"hljs-string\">su</span>\n<span class=\"hljs-attr\">packer</span> <span class=\"hljs-string\">build amazon-linux.json</span>\n</pre>\n<p>Note that it is important to actually use <code>sudo su</code> versus just <code>sudo</code> since the $PATH variables are different for\nthe <code>root</code> user versus the <code>ec2-user</code> user.</p>\n<p>The AMI will now build.</p>\n</li>\n<li>\n<p>When finished, terminate the ami-builder EC2 Instance.</p>\n</li>\n</ol>\n<h3 class=\"preview__body--subtitle\" id=\"how-to-launch-an-ami-with-an-encrypted-ebs-volume\">How to Launch an AMI with an Encrypted EBS Volume</h3>\n<p>As of Packer 0.12.3, Packer supports the <code>encrypt_boot</code> property for the amazon-chroot builder! See <a href=\"https://github.com/mitchellh/packer/pull/4584\" class=\"preview__body--description--blue\" target=\"_blank\">Pull Request #4584</a>.\nThis will allow us to build an AMI as above, except that once the AMI is ready, Packer will automatically copy the\nunencrypted <a href=\"http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/EBSSnapshots.html\" class=\"preview__body--description--blue\" target=\"_blank\">Snapshot</a> as an encrypted Snapshot,\ncreate a new AMI based on the encrypted Snapshot, and delete the original AMI and its underlying unecncrypted Snapshot.</p>\n<p>Until Packer 0.12.3 is released, you can still set <code>encrypt_boot</code> to true and earlier versions of Packer will simply\nignore this property. In the meantime, consider running an EC2 Instance with the root volume unencrypted, but with\nadditional volumes mounted as encrypted volumes.</p>\n<h3 class=\"preview__body--subtitle\" id=\"using-your-hardened-os-as-a-base-ami\">Using Your Hardened OS as a "Base AMI"</h3>\n<p>A best practice we encourage is to first build your hardened OS Image using these modules and the <a href=\"/repos/v0.46.2/module-security/examples/os-hardening\" class=\"preview__body--description--blue\">os-hardening example</a>.\nYou can now view this AMI as your "base AMI", and all other Packer builds can be built on top of this AMI. For example,\nyou might have:</p>\n<ul>\n<li>Base AMI: Hardened OS (built from stock Amazon Linux)</li>\n<li>Bastion Host: Built from Base AMI</li>\n<li>MongoDB Host: Built from Base AMI</li>\n</ul>\n<p>In the above example, the Bastion Host and MongoDB Host Packer builds will "just work" with a single exception: By default,\nPacker uploads all scripts defined in the <a href=\"https://www.packer.io/docs/provisioners/shell.html\" class=\"preview__body--description--blue\" target=\"_blank\">Remote Shell Provisioner</a>\nto <code>/tmp</code> and then executes them. But our hardened OS most likely has the <code>noexec</code> option set for the <code>/tmp</code> file system,\nwhich means that no code can be executed from <code>/tmp</code> by design!</p>\n<p>To fix this, you must set the <a href=\"https://www.packer.io/docs/provisioners/shell.html#remote_folder\" class=\"preview__body--description--blue\" target=\"_blank\">remote_folder</a> property,\nto a folder that <em>is</em> executable. For example, here we set <code>remote_folder</code> to <code>/home/ec2-user</code>:</p>\n<pre><span class=\"hljs-string\">\"provisioners\"</span>: [{\n <span class=\"hljs-string\">\"type\"</span>: <span class=\"hljs-string\">\"shell\"</span>,\n <span class=\"hljs-string\">\"remote_folder\"</span>: <span class=\"hljs-string\">\"/home/ec2-user\"</span>,\n <span class=\"hljs-string\">\"inline\"</span>: [\n <span class=\"hljs-string\">\"sudo yum update -y\"</span>\n ]\n}]\n</pre>\n<h2 class=\"preview__body--subtitle\" id=\"how-this-module-works\">How this Module Works</h2>\n<p>Much of the design for this module is motivated by our need to support multiple <a href=\"http://www.tldp.org/LDP/intro-linux/html/sect_03_01.html\" class=\"preview__body--description--blue\" target=\"_blank\">partitions</a>\non a single volume, an OS hardening best practice.</p>\n<h3 class=\"preview__body--subtitle\" id=\"the-packer-amazon-ebs-builder\">The Packer amazon-ebs builder</h3>\n<p>Almost all Packer builds for AWS use the <a href=\"https://www.packer.io/docs/builders/amazon-ebs.html\" class=\"preview__body--description--blue\" target=\"_blank\">amazon-ebs</a> builder. Packer\ntemplates that use this builder work as follows:</p>\n<ol>\n<li>Packer launches a brand new EC2 Instance and waits to SSH in.</li>\n<li>Packer executes a series of provisioners (e.g. upload files, run shell scripts).</li>\n<li>When finished, Packer shuts down the EC2 instance.</li>\n<li>Packer takes a snapshot.</li>\n<li>When the snapshot is complete, Packer creates an AMI and terminates the EC2 Instance.</li>\n</ol>\n<p>The primary advantage of the amazon-ebs Packer builder is simplicity and isolation. Each Packer build launches a completely\nfresh EC2 Instance. The primary downsides are (1) Packer builds are slow because you have to launch a completely new\nEC2 instance for each build, and (2) it is not possible to make any file system changes to the root partition because\nyou can't unmount the very partition on which the OS itself is running.</p>\n<h3 class=\"preview__body--subtitle\" id=\"the-packer-amazon-chroot-builder\">The Packer amazon-chroot builder</h3>\n<p>To address the shortcomings of the amazon-ebs builder, Packer also has the <a href=\"https://www.packer.io/docs/builders/amazon-chroot.html\" class=\"preview__body--description--blue\" target=\"_blank\">amazon-chroot</a>\nbuilder. Packer templates that use this builder work as follows:</p>\n<ol>\n<li>Out-of-band from Packer, someone launches an EC2 Instance (the "host system").</li>\n<li>From the host system, run <code>packer build <packer-template-file></code>.</li>\n<li>Packer creates an EBS Volume based on the Snapshot that's part of the source AMI specified in the Packer template,\nattaches it to the host system, and mounts it.</li>\n<li>Packer executes the <code>chroot</code> command against the path where the EBS Volume has been mounted, which starts a process\nthat now sees <code>/path/to/ebs-volume</code> as the <code>/</code> directory.</li>\n<li>Packer executes any provisioners in the Packer template. Because most provisioners are running in the <code>chroot</code>\nenvironment, they will execute directly on the EBS Volume.</li>\n<li>When all provisioners are complete, Packer detaches the volume, takes a snapshot, and creates an AMI from the snapshot.</li>\n</ol>\n<h4 id=\"the-packer-remote-shell-provisioner\">The Packer Remote Shell Provisioner</h4>\n<p>Most Packer builds use the <a href=\"https://www.packer.io/docs/provisioners/shell.html\" class=\"preview__body--description--blue\" target=\"_blank\">remote-shell</a> provisioner to apply\nconfiguration. It's called the remote shell provisioner because it executes shell commands on the "remote" EC2 Instance.\nWhen using the amazon-ebs builder, that means the newly launched EC2 Instance runs the shell commands. When using the\namazon-chroot builder, that means the commands are run from within the <code>chroot</code> environment.</p>\n<p>That is, Packer will first run <code>chroot /path/to/ebs-volume</code> and <em>then</em> execute all commands. An individual program has no\nknowledge that it's running in a special environment. It will simply access the typical file system paths. But we, the\nomniscient operator know that in reality what this program thinks is <code>/</code> is actually <code>/path/to/ebs-volume</code>.</p>\n<p>This way, we can configure our EC2 Instance as we typically do in a Packer build, except that all configuration commands\nare actually modifying the attached EBS Volume, not our root file system.</p>\n<h4 id=\"the-packer-local-shell-provisioner\">The Packer Local Shell Provisioner</h4>\n<p>The Packer <a href=\"https://www.packer.io/docs/provisioners/shell-local.html\" class=\"preview__body--description--blue\" target=\"_blank\">local-shell</a> provisioner executes shell commands\nfrom your "local" machine.</p>\n<p>When using the amazon-ebs builder, that means shell commands run from your local machine.</p>\n<p>When using the amazon-chroot builder, that means the commands are run from the EC2 Instance where you launched Packer.\nThis is significant because it means we can execute Packer commands from the host system against the attached EBS Volume.\nThis allows us to, for example, delete partitions from the attached EBS Volume and add new partitions. It is the only way\nto use Packer to create an AMI with multiple partitions.</p>\n<h2 class=\"preview__body--subtitle\" id=\"module-design-decisions\">Module Design Decisions</h2>\n<p>This section discusses some design decisions made when creating this module.</p>\n<h3 class=\"preview__body--subtitle\" id=\"which-tool-we-used-to-partition-the-disks\">Which Tool We Used to Partition the Disks</h3>\n<p>Our choice of tooling was influenced in large part by whether EBS Volumes were originally partitioned to support the\nlegacy "MBR" format, or the newer GUID Partition Table (GPT) format.</p>\n<p>The partition format of a block device refers to how the first few blocks on the disk are structured and where the boot\nloader code resides. Historically, the MBR format has been in wide use, but its primary limitation is that it does not\npermit a disk size greater than 2 TB. For this reason, a newer partition table format, GPT, was invented that supports\nup to 9.4 Zetabytes! Because Amazon EBS Volumes sometimes need to exceed 2 TB, the GPT format was a natural choice and\nis what all modern AMIs use for their underlying EBS Volumes.</p>\n<p>But it turns out that not all Linux disk partition management tools support the GPT format. For example, the venerable\n<code>fdisk</code> has only "experimental" support for GPT. For that reason, we opted to use the newer <code>gdisk</code>.</p>\n<p>But <code>gdisk</code> works with an interactive prompt, whereas we want to execute full commands as part of our Packer build. For\nthis reason, we use <code>sgdisk</code>, which implements all the same functionality of <code>gdisk</code> but as a pure command-line tool\nand not an interactive tool.</p>\n<h3 class=\"preview__body--subtitle\" id=\"managing-partitions-with-gdisk-vs-lvm\">Managing Partitions with <code>gdisk</code> vs. LVM</h3>\n<p>Initially, we experimented with using the LVM (Logical Volume Manager) tool to manage our partitions. LVM is a software\ntool that applies a unique file system format to a large disk partition and then allows software-based management of LVM\npartitions. The primary benefit to using a layer like LVM is that you can dynamically resize disk partitions (including\nroot!) without taking your disk offline.</p>\n<p>This approach was originally inspired by the presentation <a href=\"https://www.youtube.com/watch?v=8h_Y-L1Q8xI&t=1165s\" class=\"preview__body--description--blue\" target=\"_blank\">OS Hardening and Packer</a>,\nwhere the speaker makes extensive use of LVM with RHEL and the Packer amazon-chroot builder.</p>\n<p>But LVM requires that the <code>/boot</code> directory be mounted to a separate file system, which in turn requires that <code>/</code> and\n<code>/boot</code> be on separate disk partitions. Since the default boot loader configuration for the Amazon Linux EBS Volume\nexpects both <code>/</code> and <code>/boot</code> on a single partition (partition #1, to be exact), separating these two directories meant\nthat we needed to reload the boot loader.</p>\n<p>However, this proved unworkable. Amazon Linux uses an older version of GRUB for its boot loader, and GRUB was unable to find\nthe "BIOS partition" of the disk where it should write part of the boot loader configuration. After many attempts, we\neventually gave up on this direction and instead settled for using traditional "on disk" volumes formatted with <code>gdisk</code>.</p>\n<p>It's likely that these issues are specific to Amazon Linux. Also, the only practical consequence of this is that disk\npartitions on EBS Volumes cannot be dynamically resized without stopping the instance and separately mounting the EBS\nVolume. But since we anticipate most users will use an immutable infrastructure anyway, we felt that asking users who\nneeded additional space to build a new AMI was not unreasonable.</p>\n<h2 class=\"preview__body--subtitle\" id=\"gotchas\">Gotchas</h2>\n<ul>\n<li>Per the <a href=\"https://www.packer.io/docs/builders/amazon-chroot.html\" class=\"preview__body--description--blue\" target=\"_blank\">Packer docs for the amazon-chroot builder</a>, your\nprovisioning scripts must not leave any processes running or Packer will be unable to unmount the filesystem.</li>\n</ul>\n<h2 class=\"preview__body--subtitle\" id=\"todo\">TODO</h2>\n<ul>\n<li>Consider setting up new CloudWatch metrics to report available space on multiple disk partitions, not just the root\ndisk partition.</li>\n</ul>\n","repoName":"module-security","repoRef":"v0.66.0","serviceDescriptor":{"serviceName":"ssh-grunt","serviceRepoName":"module-security","serviceRepoOrg":"gruntwork-io","serviceMainReadmePath":"/modules/ssh-grunt","cloudProviders":["aws"],"description":"Manage SSH access to EC2 Instances using groups in AWS IAM or your Identity Provider (e.g., ADFS, Google, Okta, etc).","imageUrl":"grunt.png","licenseType":"subscriber","technologies":["Terraform","Go"],"compliance":[],"tags":[""]},"serviceCategoryName":"SSH access","fileName":"README.md","filePath":"/modules/os-hardening","title":"Repo Browser: ssh-grunt","description":"Browse the repos in the Gruntwork Infrastructure as Code Library."}