diff --git a/Gemfile b/Gemfile index 4f7a9532d..f1011944a 100644 --- a/Gemfile +++ b/Gemfile @@ -39,6 +39,7 @@ group :test do end group :acceptance do + gem 'minitar-cli' gem 'serverspec' end diff --git a/lib/pdk/module/build.rb b/lib/pdk/module/build.rb index 89465134e..46fd304ce 100644 --- a/lib/pdk/module/build.rb +++ b/lib/pdk/module/build.rb @@ -220,8 +220,30 @@ def build_package FileUtils.rm_f(package_file) Dir.chdir(target_dir) do - Zlib::GzipWriter.open(package_file) do |package_fd| - Minitar.pack(release_name, package_fd) + begin + gz = Zlib::GzipWriter.new(File.open(package_file, 'wb')) + tar = Minitar::Output.new(gz) + Find.find(release_name) do |entry| + entry_meta = { + name: entry, + } + + orig_mode = File.stat(entry).mode + min_mode = Minitar.dir?(entry) ? 0o755 : 0o644 + + entry_meta[:mode] = orig_mode | min_mode + + if entry_meta[:mode] != orig_mode + PDK.logger.debug(_('Updated permissions of packaged \'%{entry}\' to %{new_mode}') % { + entry: entry, + new_mode: (entry_meta[:mode] & 0o7777).to_s(8), + }) + end + + Minitar.pack_file(entry_meta, tar) + end + ensure + tar.close end end end diff --git a/spec/acceptance/build_spec.rb b/spec/acceptance/build_spec.rb index 3e9ac3b24..fe8eaad85 100644 --- a/spec/acceptance/build_spec.rb +++ b/spec/acceptance/build_spec.rb @@ -9,6 +9,7 @@ 'version' => '0.1.0', 'author' => 'testuser', 'summary' => 'a test module', + 'license' => 'Apache-2.0', 'source' => 'https://github.com/testuser/puppet-build', 'project_page' => 'https://testuser.github.io/puppet-build', 'issues_url' => 'https://github.com/testuser/puppet-build/issues', @@ -25,6 +26,10 @@ File.open('metadata.json', 'w') do |f| f.puts metadata.to_json end + + # Deliberately set some problematic file modes + File.chmod(0o640, 'metadata.json') + File.chmod(0o700, 'spec') end after(:all) do @@ -37,8 +42,26 @@ its(:stderr) { is_expected.not_to match(%r{WARN|ERR}) } its(:stderr) { is_expected.to match(%r{Build of #{metadata['name']} has completed successfully}) } - describe file(File.join('pkg', "#{metadata['name']}-#{metadata['version']}.tar.gz")) do + pkg_file = File.join('pkg', "#{metadata['name']}-#{metadata['version']}.tar.gz") + + describe file(pkg_file) do it { is_expected.to be_file } + + describe command("minitar list -l #{pkg_file}") do + its(:exit_status) { is_expected.to eq(0) } + its(:stdout) do + is_expected.to satisfy('show that all the files in the tarball have sane modes') do |output| + output.split("\n").all? do |line| + pattern = if line.start_with?('d') + %r{\Adrwxr.xr.x } # directories should be at least 0755 + else + %r{\A-rw.r..r.. } # files should be at least 0644 + end + line =~ pattern + end + end + end + end end end end