Summary
The shared Terraform provider plugin cache set up by profile::terraformer::plugin_cache (TF_PLUGIN_CACHE_DIR=/var/cache/terraform/plugins) is not writable by peer members of the admin group. Whichever admin user runs terraform first creates the provider dirs; a second admin user then gets Permission denied writing into them.
Observed on ip-10-1-1-168: works for aleks, fails for taha.
taha@ip-10-1-1-168:.../registry.terraform.io/hashicorp/aws$ mkdir tmp
mkdir: cannot create directory ‘tmp’: Permission denied
Root cause
The manifest's design assumption is stated in its own comment:
setgid so new entries inherit the admin group; the default ACL below adds the group-write that the umask would otherwise strip from nested dirs.
That assumption is incorrect. The default ACL is applied, but each newly-created provider dir's access mask comes out r-x, which clamps the effective group:admin permission back down to r-x:
$ getfacl /var/cache/terraform/plugins/registry.terraform.io/hashicorp/aws
# owner: aleks
# group: admin
# flags: -s-
group::rwx #effective:r-x
group:admin:rwx #effective:r-x
mask::r-x
default:group:admin:rwx
default:mask::rwx
Note the access mask::r-x vs default:mask::rwx. POSIX rule: a directory created under a parent that has a default ACL gets its access mask = default mask ∩ the group bits of the mode passed to mkdir. Terraform calls mkdir(…, 0777); with umask 022 the effective create mode is 0755 → group bits r-x → mask clamped to r-x. So the default ACL does not, and cannot, protect group-write against umask 022 — the umask re-clamps the mask on every dir Terraform creates.
Two compounding issues in the current manifest:
- The
terraformer-plugin-cache-acl exec is guarded by unless and only runs at provision time, so it never repairs the mask on dirs Terraform creates afterward.
- The
profile.d export sets TF_PLUGIN_CACHE_DIR but not a umask, so every interactive run uses the default 022.
Proposed fix
Set umask 002 for the context that runs Terraform, so mkdir requests 0775 → group bits rwx → mask rwx → group:admin effective rwx. Combined with the existing setgid bit this is self-sustaining and the ACL exec becomes redundant.
Simplest change: add umask 002 to the managed /etc/profile.d/terraform-plugin-cache.sh:
content => "# Managed by Puppet (profile::terraformer::plugin_cache)\numask 002\nexport TF_PLUGIN_CACHE_DIR=${cache_dir}\n",
Note profile.d only covers interactive login shells — if Terraform is ever invoked from cron/systemd on this host, set the umask in that unit/job too. Keeping the default-ACL exec is harmless as defense-in-depth, but it's the umask that actually fixes it.
One-time repair of the current live host
sudo chmod -R g+w /var/cache/terraform
sudo setfacl -R -m m::rwx /var/cache/terraform # reset the clamped access masks
Summary
The shared Terraform provider plugin cache set up by
profile::terraformer::plugin_cache(TF_PLUGIN_CACHE_DIR=/var/cache/terraform/plugins) is not writable by peer members of theadmingroup. Whichever admin user runsterraformfirst creates the provider dirs; a second admin user then getsPermission deniedwriting into them.Observed on
ip-10-1-1-168: works foraleks, fails fortaha.Root cause
The manifest's design assumption is stated in its own comment:
That assumption is incorrect. The default ACL is applied, but each newly-created provider dir's access mask comes out
r-x, which clamps the effectivegroup:adminpermission back down tor-x:Note the access
mask::r-xvsdefault:mask::rwx. POSIX rule: a directory created under a parent that has a default ACL gets its access mask = default mask ∩ the group bits of the mode passed tomkdir. Terraform callsmkdir(…, 0777); with umask 022 the effective create mode is0755→ group bitsr-x→ mask clamped tor-x. So the default ACL does not, and cannot, protect group-write against umask 022 — the umask re-clamps the mask on every dir Terraform creates.Two compounding issues in the current manifest:
terraformer-plugin-cache-aclexec is guarded byunlessand only runs at provision time, so it never repairs the mask on dirs Terraform creates afterward.profile.dexport setsTF_PLUGIN_CACHE_DIRbut not a umask, so every interactive run uses the default 022.Proposed fix
Set
umask 002for the context that runs Terraform, somkdirrequests0775→ group bitsrwx→ maskrwx→group:admineffectiverwx. Combined with the existing setgid bit this is self-sustaining and the ACL exec becomes redundant.Simplest change: add
umask 002to the managed/etc/profile.d/terraform-plugin-cache.sh:Note
profile.donly covers interactive login shells — if Terraform is ever invoked from cron/systemd on this host, set the umask in that unit/job too. Keeping the default-ACL exec is harmless as defense-in-depth, but it's the umask that actually fixes it.One-time repair of the current live host