Skip to content

Commit 8eced40

Browse files
committed
Enforce owner/group of Go installations
This now recreates a Go installation if any of its files or directories have the wrong owner or group.
1 parent 72fd1c4 commit 8eced40

File tree

3 files changed

+82
-21
lines changed

3 files changed

+82
-21
lines changed

CHANGELOG.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,15 @@ This version of dp-golang enables [`tar`]’s `--no-same-owner` and
2626
`--no-same-permissions` flags, which cause files to be extracted as the user
2727
running Puppet, or as the user/group specified in the Puppet code.
2828

29-
**This will not fix existing installs** unless you update the Go version, or
30-
otherwise prompt Puppet to reinstall.
31-
3229
[`tar`]: https://www.man7.org/linux/man-pages/man1/tar.1.html
3330

31+
### Changes
32+
33+
As part of the security fix mentioned above, it became necessary to be more
34+
agressive about ensuring that the owner and group of files in the installation
35+
are correct. This now deletes and recreates any Go installation it finds that
36+
has a file or directory with the wrong owner or group.
37+
3438
## Release 1.2.6
3539

3640
* Synced with [PDK][].

manifests/from_tarball.pp

Lines changed: 35 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@
4646
String[1] $mode = '0755',
4747
Stdlib::Unixpath $state_file = golang::state_file($go_dir),
4848
) {
49+
$encoded_go_dir = $go_dir.regsubst('/', '_', 'G')
50+
$archive_path = "/tmp/puppet-golang${encoded_go_dir}.tar.gz"
51+
4952
if $ensure != any_version {
5053
# Used to ensure that the installation is updated when $source changes.
5154
$file_ensure = $ensure ? {
@@ -70,6 +73,38 @@
7073
}
7174
}
7275

76+
if $ensure == present or $ensure == any_version {
77+
# Remove Go installation if any of its files have the wrong user or group.
78+
# This will cause it to be replaced with a fresh installation.
79+
exec { "dp/golang check ownership of ${go_dir}":
80+
command => ['rm', '-rf', $go_dir],
81+
environment => [
82+
"GO_DIR=${go_dir}",
83+
"OWNER=${owner}",
84+
"GROUP=${group}",
85+
],
86+
path => ['/usr/local/bin', '/usr/bin', '/bin'],
87+
onlyif => 'find "$GO_DIR" "(" "(" -not -user "$OWNER" ")" -or "(" -not -group "$GROUP" ")" ")" -print -quit | grep .',
88+
before => File[$go_dir],
89+
notify => Archive[$archive_path],
90+
}
91+
}
92+
93+
# File[$state_file] changing should only trigger an update when ensure is
94+
# present, and not any_version.
95+
if $ensure == present {
96+
# If the $go_dir/bin directory exists, archive won't update it. Also, we
97+
# want to remove any files that are not present in the new version.
98+
exec { "dp/golang refresh go installation at ${go_dir}":
99+
command => ['rm', '-rf', $go_dir],
100+
path => ['/usr/local/bin', '/usr/bin', '/bin'],
101+
refreshonly => true,
102+
subscribe => File[$state_file],
103+
before => File[$go_dir],
104+
notify => Archive[$archive_path],
105+
}
106+
}
107+
73108
$directory_ensure = $ensure ? {
74109
'present' => directory,
75110
'any_version' => directory,
@@ -85,24 +120,6 @@
85120
}
86121

87122
if $ensure == present or $ensure == any_version {
88-
$encoded_go_dir = $go_dir.regsubst('/', '_', 'G')
89-
$archive_path = "/tmp/puppet-golang${encoded_go_dir}.tar.gz"
90-
91-
# Only trigger an update when ensure is present, and not any_version.
92-
if $ensure == present {
93-
# If the $go_dir/bin directory exists, archive won't update it. Also, we
94-
# want to remove any files that are not present in the new version.
95-
exec { "dp/golang refresh go installation at ${go_dir}":
96-
command => ['rm', '-rf', $go_dir],
97-
path => ['/usr/local/bin', '/usr/bin', '/bin'],
98-
user => $facts['identity']['user'],
99-
refreshonly => true,
100-
subscribe => File[$state_file],
101-
before => File[$go_dir],
102-
notify => Archive[$archive_path],
103-
}
104-
}
105-
106123
include archive
107124

108125
archive { $archive_path:

spec/acceptance/golang_from_tarball_spec.rb

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,46 @@
187187
end
188188
end
189189

190+
context 'after chowning bin/go' do
191+
File.chown(0, 0, "#{home}/user/go-install/bin/go")
192+
193+
it 'reinstalls Go' do
194+
apply_manifest(<<~"PUPPET", expect_changes: true)
195+
golang::from_tarball { '#{home}/user/go-install':
196+
source => '#{source_url}',
197+
owner => 'user',
198+
group => 'user',
199+
mode => '0700',
200+
}
201+
PUPPET
202+
end
203+
204+
describe file("#{home}/user/go-install") do
205+
it { is_expected.to be_directory }
206+
its(:mode) { is_expected.to eq '700' }
207+
its(:owner) { is_expected.to eq 'user' }
208+
its(:group) { is_expected.to eq 'user' }
209+
end
210+
211+
describe file("#{home}/user/go-install/bin/go") do
212+
it { is_expected.to be_file }
213+
its(:mode) { is_expected.to eq '755' }
214+
its(:owner) { is_expected.to eq 'user' }
215+
its(:group) { is_expected.to eq 'user' }
216+
end
217+
218+
it 'does nothing' do
219+
apply_manifest(<<~"PUPPET", catch_changes: true)
220+
golang::from_tarball { '#{home}/user/go-install':
221+
source => '#{source_url}',
222+
owner => 'user',
223+
group => 'user',
224+
mode => '0700',
225+
}
226+
PUPPET
227+
end
228+
end
229+
190230
context 'cleans up' do
191231
it 'uninstalls Go' do
192232
idempotent_apply(<<~"PUPPET")

0 commit comments

Comments
 (0)