Gruntwork Newsletter, May 2020
Once a month, we send out a newsletter to all Gruntwork customers that describes all the updates we’ve made in the last month, news in the…
Once a month, we send out a newsletter to all Gruntwork customers that describes all the updates we’ve made in the last month, news in the DevOps industry, and important security updates. Note that many of the links below go to private repos in the Gruntwork Infrastructure as Code Library and Reference Architecture that are only accessible to customers.
In the last couple months, we’ve released a guide to using Gruntwork with Terraform Cloud and Terraform Enterprise, created a new module for Amazon’s Elastic File Store (EFS), added PrivateLink support to keep AWS API calls within your VPC network, added support for managing secrets in Terragrunt using Mozilla SOPS, did a podcast interview with SE Radio, and made a huge number of other fixes and improvements.
As always, if you have any questions or need help, email us at support@gruntwork.io!
Gruntwork Updates

How to use Gruntwork with Terraform Cloud and Terraform Enterprise
Motivation:**** Gruntwork customers love saving time by using the Gruntwork IaC Library to do the heavy lifting of building production-grade cloud infrastructure. Many in the Terraform community have enjoyed using Terragrunt for its ability to keep your code and variables, CLI args, etc DRY, and for better support when applying changes across multiple accounts/modules/environments. HashiCorp customers love using Terraform Cloud (TFC) and/or Terraform Enterprise (TFE) for its browser-based controls, support for teams, and remote execution features. Fortunately, in this case, you can have your cake, and eat it too! Gruntwork and Terragrunt are compatible with Terraform Cloud and Terraform Enterprise.
Solution: We’ve written a blog post that shows you how to use Gruntwork’s Terrraform modules with TFC/TFE and even how to integrate Terragrunt with TFC/TFE. We’ve also updated our guide, How to Use the Gruntwork Infrastructure as Code Library, with all the details you need to set the integration up for yourself. Take a look and let us know what you think!

New module: Amazon Elastic File System (EFS)
Motivation: Amazon’s Elastic File System (EFS) gives you a managed, scalable, elastic NFS file system in the cloud. It’s an easy way to create a hard-disk that’s shared across many EC2 instances, but we did not have any module to deploy and manage EFS as code.
Solution: We’ve added a new efs
module to module-data-storage
! This makes it easy to use EFS in just a few lines of code:
module "efs" { source = "git::git@github.com:gruntwork-io/module-data-storage.git//modules/efs?ref=v0.12.15"
name = "example-efs" vpc_id = data.aws_vpc.default.id subnet_ids = data.aws_subnet_ids.default.ids }
A huge thank you to Jesse Bye for contributing this new module!
What to do about it: Try out the new efs
module and let us know what you think!

New module: PrivateLink for VPCs
Motivation: By default, any API calls you make to AWS go over the public Internet, even if you make those API calls from within a VPC in your AWS account. You can keep those API calls more private by routing them entirely within your VPC using VPC Endpoints (which are built into the Gruntwork VPC modules), but VPC Endpoints only support S3 and DynamoDB. For all other AWS services, you need to use PrivateLink, a separate (paid) service, which our VPC module did not support.
Solution: We’ve added a new vpc-interface-endpoint
module to module-vpc
which you can use to enable PrivateLink for AWS services in your VPC. Here’s an example of how to use the module to enable PrivateLink for all calls to AWS EC2 APIs:
module "vpc" { source = "git::git@github.com:gruntwork-io/module-vpc.git//modules/vpc-app?ref=v0.8.7"
vpc_name = "example-vpc" aws_region = "us-east-1" cidr_block = "10.0.0.0/16" }
module "vpc_endpoint_ec2_example" { source = "git::git@github.com:gruntwork-io/module-vpc.git//modules/vpc-interface-endpoint?ref=v0.8.7"
vpc_id = module.vpc.vpc_id subnet_ids = module.vpc.private_app_subnet_ids
# Enable PrivateLink for EC2 enable_ec2_endpoint = true }
Note that using PrivateLink incurs an extra fee per hour per AZ where PrivateLink is deployed and per GB of data processed, so make sure to check the pricing page before enabling it for all services!
What to do about it: If you want an extra layer of privacy for your AWS API calls, try out the new vpc-interface-endpoint
module and let us know what you think!

Manage secrets in Terragrunt using Mozilla SOPS
Motivation: Terraform does not have great native features for managing secrets (see this issue, which has been open for ~6 years).
Solution: We’ve added support for Mozilla SOPS to Terragrunt. SOPS allows you to securely store secrets in JSON or YAML files encrypted via AWS KMS, GCP KMS, Azure Key Vault, or PGP. For example, you might have a secrets.yml
with the contents:
db: user: ENC[AES256_GCM,data:CwE4O1s=,iv:2k=,aad:o=,tag:w==] password: ENC[AES256_GCM,data:p673w==,iv:YY=,aad:UQ=,tag:A=]
Note that the user
and password
are encrypted with one of the mechanisms supported by SOPS, which means it is safe to check this file into version control. You use the new sops_decrypt_file
helper in your terragrunt.hcl
files to automatically read the file and decrypt the contents, allowing you to pass those values to your Terraform code:
locals { secrets = yamldecode(sops_decrypt_file("secrets.yml")) }
inputs = { user = local.secrets.db.user password = local.secrets.db.password }
This approach allows you to avoid putting any plain text secrets directly in version control, while still managing everything as code. Note that any secrets you pass to Terraform may be stored in its state file in plain text, so make sure you store that state file in an encrypted format too (e.g., using S3 encryption)!
What to do about it: Check out the sops_decrypt_file
documentation, give the new helper a try, and let us know what you think!

SE Radio podcast interview: Infrastructure as Code Best Practices
Motivation: The team at Software Engineering (SE) Radio wanted to know more about infrastructure as code.
Solution: Gruntwork co-founder Yevgeniy (Jim) Brikman did a podcast interview with SE Radio on Infrastructure as Code Best Practices. The discussion covers similarities and differences between conventional software engineering and code-driven infrastructure; factoring code into modules; layering; terraform code organization for micro-services; releases and tagging; code reviews; unit testing infrastructure; deployment of infrastructure; ownership and code structure models; and open source and re-usable libraries.
What to do about it: Listen to the Infrastructure as Code Best Practices Podcast and leave your thoughts in the comments.

Open Source Updates
Terragrunt
- v0.23.3:
hclfmt
now supports formatting a single file as opposed to an entire directory tree. Use--terragrunt-hclfmt-file
to specify the single file you wish to format. - v0.23.4: This release upgraded the internal terraform functions to the latest version (
v0.12.24
). Previously unavailable functions such astrim
,try
, andcan
are now available.hclfmt
has also been upgraded to handle formatting files with heredoc syntax correctly. - v0.23.5: This release introduces an optimization for retrieving dependencies, where each dependency will be retrieved concurrently.
- v0.23.6: Fixed formatting in
--help
text for Terragrunt. - v0.23.7: This introduces a new command
graph-dependencies
which can be used to get a graph representation of the dependency relations between all the modules. - v0.23.8: This fixes a bug where the relative paths used for
read_terragrunt_config
were broken when used in a module that was pulled in withdependency
blocks. - v0.23.9: This fixes a bug where setting
--terragrunt-source
on a module with dependencies updated the source of both the current module and the dependency. Starting this version, when using--terragrunt-source
on a module with a dependency the dependency's terraform source will be updated to the combined path using//
as an anchor. - v0.23.10:
generate
blocks now support an optional attributedisable_signature
, which, whentrue
, will avoid emitting the signature line at the top of the generated file. - v0.23.11: Terragrunt will now correctly omit
-var
and-var-file
arguments when you rundestroy
with a plan file. - v0.23.12: Terragrunt will now auto retry on the error
TooManyUpdates error for SSM param
. - v0.23.13:
get_env
can now be made to force an environment variable to be defined. When used with a single argument, the function will error if the environment variable returns empty string. This release also introduces a new helper function,get_terraform_command
which can be used to see what the current executed command byterragrunt
is. - v0.23.14: The automated S3 bucket created by terragrunt with the
remote_state
block will now properly handle new accounts that do not have the default s3 KMS key created. - v0.23.15: This release introduces a new function (
get_terraform_cli_args
) to introspect terraform args in your terragrunt config. This can be used to conditionally adjust your hooks based on what args are passed in (e.g.plan --destroy
vs.plan
). - v0.23.16: This release introduces a new
--terragrunt-parallelism
CLI argument that you can use to limit parallelism when executingxxx-all
commands (e.g. ,apply-all
). This is useful if, for example, you are runningapply-all
on a large number of modules, and starting to hit cloud provider rate limits as a result. - v0.23.17: Fix indentation in the
--help
text of Terragrunt. - v0.23.18: This release introduces a new function
sops_decrypt_file
, which will decrypt an encrypted file using SOPS.
Terratest
- v0.26.1: Previously
IsPodAvailable
was not accounting for readiness of the containers. This could lead to returningtrue
when the pod was not ready for accepting connections. This release updates the function to only returntrue
if all the containers in the Pod are ready. - v0.26.2: The
EmptyS3Bucket
/EmptyS3BucketE
functions now also clean up delete markers. - v0.26.3: The check made in
IsMinikubeE
is now more robust to different flavors of Minikube. - v0.26.4: Flow through
OutputMaxLineSize
to all terraform calls. - v0.26.5: Added
docker.Inspect
anddocker.InspectE
methods to rundocker inspect
and return the results in a convenientstruct
. Addeddocker.RunAndGetID
anddocker.RunAndGetIDE
methods to rundocker run
and return the ID of the started container. - v0.26.6:
terratest_log_parser
now buffers input lines so that it can support parsing long lines. - v0.27.0: You no longer need to provide
OutputMaxLineSize
to respective command options when you have long outputs. As such the option has been removed from the respective structs. - v0.27.1: The
ContainerInspect
struct returned bydocker.Inspect
now includes health check data. - v0.27.2: You can now pass in additional arguments to the
helm.RenderTemplate
andhelm.RenderTemplateE
functions. - v0.27.3: You can now customize the logger used by the functions in terratest. Any type that implements the function
Logf(t testing.TestingT, format string, args ...interface{})
can be used for logging by wrapping it in theLogger
type usinglogger.New
. See the provided loggers in thelogging
package for more info.
cloud-nuke
- v0.1.17:
cloud-nuke
now supports nuking S3 buckets. Note that you can exclude certain buckets from consideration by tagging them with the tag keycloud-nuke-excluded
and valuetrue
. This release also introduces a new CLI arg--exclude-resource-type
for removing certain resource types from consideration. For example, to avoid nuking s3 buckets entirely, you can pass incloud-nuke aws --exclude-resource-type s3
. Usecloud-nuke aws --list-resource-types
to see all the supported resource types. - v0.1.18: You can now set the log level using the
--log-level
param.Also,cloud-nuke
now fetches S3 bucket info concurrently, which should speed the process up by 5-10x.
kubergrunt
- v0.5.13: Starting this release, we will publish sha256 checksums with our binaries.
terraform-google-gke
- v0.4.3: Added a new optional variable to the
gke-cluster
module calledservices_secondary_range_name
that allows you to specify the name of the secondary range within the subnetwork for the services to use.
terraform-google-network
- v0.3.0: This release fixes a configuration problem with the VPC NAT routing by referencing the private subnetwork instead of the public one.
- v0.4.0: This release replaces the deprecated
enable_flow_logs
parameter from thevpc-network
module in favor of the newlog_config
parameter.
terraform-aws-nomad
- v0.6.0: We have switched Nomad to using
systemd
instead ofsupervisord
, assystemd
is now available on all major Linux distros. - v0.6.1: Updated the example Packer template in
nomad-consul.json
to useclean_resource_name
instead ofclean_ami_name
, as the latter was deprecated in Packer 1.5+. - v0.6.2: Updated the example Packer template in
nomad-consul.json
to configure Docker to start at boot. - v0.6.3: The
nomad-cluster
module will now respect asnapshot_id
setting passed in via theebs_block_devices
input variable.
fetch
- v0.3.8: You can now specify an optional
--progress
flag to havefetch
show progress during downloads. This is especially useful for large downloads. - v0.3.9: This rolls back the change from
v0.3.6
. This means that you can now pass empty values again to--branch
,--tag
, and--commit
, as long as one of those is non-empty, andfetch
will handle it correctly.
Gruntwork Installer
- v0.0.25: Switch from
local readonly
tolocal -r
, which is the proper way to declare local, read-only variables in Bash. - v0.0.26: Fix bugs in how
gruntwork-install
parses, passes around, and logs--module-param
arguments to ensure whitespace is handled correctly. - v0.0.27: Minor fixes to ensure scripts pass shellcheck.
package-terraform-utilities
- v0.1.8: Added a new module called
executable-dependency
that can be used to install an executable if it's not installed already. This is useful if your Terraform code depends on external dependencies, such asterraform-aws-eks
, which depends onkubergrunt
. - v0.2.0:
enabled-aws-regions
has been removed as there is now a new data source in theaws
provider that has the same functionality. Replace usage of the module with theaws_regions
data source

Other updates
module-data-storage
- v0.12.11: You can now configure the read replicas with separate settings from the primary. In particular, you can use the new
parameter_group_name_for_read_replicas
input variable to set a separate parameter group for read replicas andallow_connections_from_security_groups_to_read_replicas
andallow_connections_from_cidr_blocks_to_read_replicas
to configure a separate security group for read replicas. - v0.12.12: You can now provide an existing DB subnet group to use with the RDS clusters instead of creating a new one.
- v0.12.13: You can now pass in an optional list of IAM roles to attach to the Aurora cluster using the new
cluster_iam_roles
input variable.
terraform-aws-eks
- v0.17.1:
eks-cluster-workers
now supports thecreate_resources
parameter, which whenfalse
, will turn off all the resources in the module. - v0.17.2: Fix bug where the cluster autoscaler in IRSA mode was unable to get the necessary IAM permissions to access the ASG.
- v0.18.0: This release removes the
fargate_only
flag oneks-cluster-control-plane
module and replaces it with the more descriptive and accurateschedule_control_plane_services_on_fargate
. Refer to the release notes for more details. - v0.19.0: This release includes an internal implementation change for the fargate profiles to simplify the authentication mechanism when migrating the control plane services to Fargate. Note that if you were using
schedule_control_plane_services_on_fargate = true
, you will now need to usekubergrunt
version0.5.12
or greater. - v0.19.1: The EKS cluster creation timeout is now 60 minutes.
- v0.19.2: The outputs for
eks-k8s-cluster-autoscaler-iam-policy
are now computed in a manner that is more robust to loss of credentials during anapply
. - v0.19.3: When upgrading from Kubernetes version 1.13 to 1.15, the
coredns
containers get updated to the latest version. In the newer versions ofcoredns
, the configuration has a backwards incompatible change that was previously unhandled in the upgrade scripts. This release fixes that issue such that it will reformat the configuration to match expectations of latercoredns
versions. - v0.19.4: Fix
eks-cluster-workers
to use properly usevar.custom_tags_security_group
to allow custom tags for SG. - v0.19.5: You can now specify the docker repository to use for sourcing the cluster-autoscaler. Recent versions of the cluster-autoscaler is now region sensitive and you must pull from the corresponding repository. Refer to the release notes for more information.
- v0.19.6: You can now disable module calls to
eks-cluster-managed-workers
by settingcreate_resources = false
. This allows you to implement conditional logic to turn on or off a module block in your terraform module. - v0.19.7:
eks-cluster-control-plane
module will now automatically download and installkubergrunt
if it is not available in the target system. This behavior can be disabled by setting the input variableauto_install_kubergrunt
tofalse
.
package-static-assets
- v0.6.2: Resolve source of perpetual diff when using the cloudfront default certificate.
- v0.6.3: You can now control the suffix appended to the access logs S3 bucket using the new optional input variable
access_logs_bucket_suffix
.
module-cache
- v0.9.2: You can now specify a custom KMS key to encrypt data at rest in
redis
using the newkms_key_id
input variable.
package-lambda
- v0.7.5: You can now specify a permissions boundary on the IAM role created for
lambda-edge
. - v0.7.6: Apply tags to all resources created by the
lambda
,lambda-edge
, andscheduled-lambda-job
modules. - v0.7.7: Both
lambda
andlambda-edge
now support settingreserved_concurrent_executions
on the underlying Lambda function. - v0.8.0: The
lambda
module is now more robust to partial failures in the module. Previously you could end up in a state where you couldn'tapply
ordestroy
the module if it only partially applied the resources due to output errors. This release addresses that by changing the output logic.
module-security
- v0.27.2: This release introduces a new module
kms-master-key-multi-region
, which can be used to manage KMS CMKs across all enabled regions of an account. - v0.28.0: Account baseline modules now support managing KMS Customer Master Keys. Also, you can now specify multiple IAM roles for managing cross account access IAM groups.
- v0.28.1: Since AWS provider 2.0, setting
num_days_after_which_delete_log_data = 0
no longer works and leads to a provider schema error. This meant that there was no way to configure S3 buckets to never delete data. Starting with this release, you can now prevent deletion of data in S3 foraws-config
andcloudtrail
by setting the respective variables tonull
. - v0.28.2: This fixes our automation process so that binaries will be attached to releases.
- v0.28.3: All the parameters passed to the
customer_master_keys
variable of thekms-master-key
module are now optional instead of required. The module will now only add IAM policy statements for the parameters that are actually set. - v0.28.4: You can now grant Service Principals (e.g., “s3.amazonaws.com”) access to your KMS CMKs by setting the
cmk_service_principals
parameter and specifying the actions those Service Principals will be allowed to do via a newservice_principal_actions
input variable. - v0.28.5: Fix dynamic statement creation in
kms-master-key
so that the optional released in v0.28.3 works properly. - v0.28.6: The behavior of
ssh-grunt
has changed such that IAM users will be sync’d even if there is a duplicate user name. Previously,ssh-grunt
would throw an error and stop processing other users. - v0.28.7: This release includes updates to several modules, including
ssh-grunt
,cloudtrail
,kms-master-key
, and the*-multi-region
modules. See the release notes for details. - v0.29.0: Refactor of AWS Config to better support multi-account, multi-region configurations. AWS Config can now be centralized to a single S3 bucket in a central account, and SNS notifications can be centralized to a single SNS topic per region.
- v0.30.0: In v0.29.0, we updated
account-baseline-app
andaccount-baseline-security
to allow for centralizing Config output in a single bucket. In this release, we take the same approach withaccount-baseline-root
. It now supports using config bucket in security account. Additionally, theiam-policies
module now allows sts:TagSession for the automation users. - v0.31.0: The
cloudtrail
module now supports reusing an existing KMS key in your account, as opposed to creating a new one. To use an existing key, set thekms_key_already_exists
variable totrue
and provide the ARN of the key to the variablekms_key_arn
.
module-load-balancer
- v0.19.0: This release introduces support for requesting, and automatically verifying, multiple ACM certificates.
- v0.20.0: This release includes support for programmatically looking up Route53 hosted zones by name when their IDs are not supplied as input variables. It also introduces 3 new default variables to help keep your input configuration clean.
module-aws-monitoring
- v0.19.1: Fix a bug in the
rds_disk_space_available
alarm where it would be enabled, incorrectly, for Aurora instances. - v0.19.2: Fix a bug in the
alb-alarms
module where for "low" thresholds (e.g., low request count) it was usingGreaterThanThreshold
instead ofLessThanThreshold
. - v0.20.0: The
cloudwatch-dashboard
module now supports managing multiple dashboards in one module. - v0.21.0: The
install.sh
scripts for thecloudwatch-log-aggregation-scripts
,syslog
, andcloudwatch-memory-disk-metrics-scripts
modules were unnecessarily usingeval
to execute scripts used in the install steps. This led to unexpected behavior, such as--module-param
arguments being shell expanded. We've removed the calls toeval
and replaced with a straight call to the underlying scripts.
package-openvpn
- v0.9.12: Fixes a bug in the
openvpn-server
module which if the Elastic IP associated with the OpenVPN Server was deleted, Terraform would throw an invalid index error.
module-vpc
- v0.8.6: New module that allows to create a VPC Interface Endpoint to connect services within your VPC without needing to create NAT Gateways neither private gateway. Previously, only VPC Gateway Endpoints (S3 and DynamoDB) were permitted.
module-ci
- v0.18.5: The ECS Deploy Runner stack now supports passing in a limited selection of command arguments to the underlying terraform/terragrunt commands.
- v0.18.6:
Dockerfile
forinfrastructure-deploy-script
now includes bitbucket.org inknown_hosts
list. Also fix bug wherev0.18.5
was incompatible with previous versions ofinfrastructure-deployer
. - v0.19.0: The CLI arg for setting the log level in
infrastructure-deployer
andinfrastructure-deploy-script
has been renamed to--log-level
instead of--loglevel
. Theinfrastructure-deploy-script
no longer supports passing in the private SSH key via CLI args. You must pass it in with the environment variableDEPLOY_SCRIPT_SSH_PRIVATE_KEY
.install-jenkins
will automatically disable jenkins so that it won't start on boot. This ensures that jenkins will not be started unless it has been successfully configured withrun-jenkins
. - v0.20.0:
ecs-deploy-runner
now supports specifying multiple container images, and choosing a container image based on a user defined name. This allows you to configure and use different Docker containers for different purposes of your infrastructure pipeline. - v0.20.1:
build-packer-artifact
now supports building a packer template from a git repository. See the updated docs for more info.
module-server
- v0.8.2: The
single-server
module now applies the tags passed in via thetags
input variable to the EIP and IAM Role resources it creates.
package-messaging
- v0.3.2: You can now add tags to the SNS topic created by the
sns
module.
cis-compliance-aws
- v0.4.1:
aws-securityhub
no longer depends on python to get enabled regions, and instead uses a terraform native data source.
module-ecs
- v0.19.1: You can now configure the platform version of ECS Fargate using the
platform_version
variable.
module-asg
- v0.8.7: You can now enable encryption in the
server-group
module for the root block device by using theroot_block_device_encrypted
input variable.
DevOps News
EKS now supports Kubernetes version 1.16; 1.13 is deprecated
What happened: EKS now supports Kubernetes 1.16 and Kubernetes 1.13 is now considered deprecated.
Why this matters: Kubernetes 1.16 includes support for volume resizing, Windows GMSA, and Finalizer Protection for Service LoadBalancers. Also, custom resource definitions and admission webhooks have both graduated to generally available. As for Kubernetes 1.13, since EKS only supports the 3 most recent releases, 1.13 is now officially deprecated in EKS and will no longer be supported by June 30, 2020, so if you’re still using it, make sure to update ASAP!
What to do about it: We are updating terraform-aws-eks
with support for 1.16 as we speak: follow PR #160 for details. Once that PR is merged, you are safe to upgrade. If you’re still on 1.13, you should update ASAP!
EFS updates: faster read operations and ECS/Fargate integration
What happened:**** AWS has made two big improvements to its Elastic File System (EFS) Service: it now supports up to 35,000 read operations per second (a 400% increase) and ECS and Fargate tasks can now mount EFS file systems.
What to do about it: Check out the documentation for EFS limits and mounting EFS Volumes for details. Also, give our new efs
module announced earlier in the newsletter a try!
Vault 1.4 has been released
What happened: HashiCorp has released Vault 1.4.
Why it matters: Some of the highlights of Vault 1.4 include:
- Integrated Storage: This feature, which allows you to run Vault without a separate storage engine (e.g., Consul), is now generally available.
- Transform Secrets Engine (Vault Enterprise only): Transform Secrets Engine performs secure data transformation for protecting secrets that reside in untrusted or semi-trusted systems outside of Vault.
- Vault Helm Chart: Run Vault Enterprise via the Helm Chart hosting on Kubernetes.
What to do about it: Try the new version out and let us know what you think!
Security Updates
Below is a list of critical security updates that may impact your services. We notify Gruntwork customers of these vulnerabilities as soon as we know of them via the Gruntwork Security Alerts mailing list. It is up to you to scan this list and decide which of these apply and what to do about them, but most of these are severe vulnerabilities, and we recommend patching them ASAP.
Rails / Ruby
- CVE-2020–8163: Potential remote code execution of user-provided local names in Rails < 5.0.1. There was a vulnerability in versions of Rails prior to 5.0.1 that would allow an attacker who controlled the
locals
argument of arender
call. This vulnerability has been assigned the CVE identifier CVE-2020–8163. We recommend that users of Rails < 5.0.1 upgrade to a version ≥= 5.0.1. More information: https://groups.google.com/forum/#!topic/rubyonrails-security/hWuKcHyoKh0 - CVE-2020–8161 Directory traversal in Rack::Directory. There was a possible directory traversal vulnerability in the Rack::Directory app that is bundled with Rack. We recommend that users of Rack::Directory < 2.2.0 upgrade to a version ≥= 2.2.0. More information: https://groups.google.com/forum/#!msg/rubyonrails-security/IOO1vNZTzPA/Ylzi1UYLAAAJ