simp-rake-helpers 5.11.2 → 5.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +43 -0
- data/CONTRIBUTING.md +1 -1
- data/Gemfile +5 -1
- data/README.md +1 -1
- data/lib/simp/command_utils.rb +21 -0
- data/lib/simp/componentinfo.rb +17 -0
- data/lib/simp/local_gpg_signing_key.rb +184 -81
- data/lib/simp/rake.rb +3 -10
- data/lib/simp/rake/build/build.rb +43 -27
- data/lib/simp/rake/build/constants.rb +5 -1
- data/lib/simp/rake/build/pkg.rb +167 -51
- data/lib/simp/rake/build/tar.rb +1 -1
- data/lib/simp/rake/helpers/version.rb +1 -1
- data/lib/simp/rake/pkg.rb +5 -1
- data/lib/simp/rake/pupmod/helpers.rb +2 -0
- data/lib/simp/rake/rubygem.rb +5 -1
- data/lib/simp/relchecks.rb +1 -1
- data/lib/simp/rpm.rb +13 -125
- data/lib/simp/rpm_signer.rb +321 -0
- data/spec/acceptance/00_pkg_rpm_custom_scriptlets_spec.rb +18 -19
- data/spec/acceptance/10_pkg_rpm_spec.rb +46 -48
- data/spec/acceptance/50_local_gpg_signing_key_spec.rb +7 -3
- data/spec/acceptance/55_build_pkg_signing_spec.rb +293 -42
- data/spec/acceptance/files/testpackage/README +8 -0
- data/spec/acceptance/files/testpackage/spec/classes/init_spec.rb +1 -0
- data/spec/acceptance/files/testpackage/spec/files/mock_something.rb +3 -0
- data/spec/acceptance/files/testpackage/utils/convert_v1_to_v2.rb +3 -0
- data/spec/acceptance/nodesets/default.yml +34 -109
- data/spec/acceptance/support/build_project_helpers.rb +32 -8
- data/spec/lib/simp/ci/gitlab_spec.rb +12 -13
- data/spec/lib/simp/command_utils_spec.rb +29 -0
- data/spec/lib/simp/componentinfo_spec.rb +10 -4
- data/spec/lib/simp/local_gpg_signing_key_spec.rb.beaker-only +115 -18
- data/spec/lib/simp/rake/build/helpers_spec.rb +3 -0
- data/spec/lib/simp/rake/build/rpmdeps_spec.rb +1 -2
- data/spec/lib/simp/rake/pupmod/fixtures/othermod/Gemfile +1 -10
- data/spec/lib/simp/rake/pupmod/fixtures/simpmod/README.md +2 -2
- data/spec/lib/simp/rake_spec.rb +2 -1
- data/spec/lib/simp/relchecks_check_rpm_changelog_spec.rb +20 -10
- data/spec/lib/simp/relchecks_compare_latest_tag_spec.rb +18 -18
- data/spec/lib/simp/rpm_signer_spec.rb +98 -0
- data/spec/lib/simp/rpm_spec.rb +1 -7
- data/spec/spec_helper.rb +1 -1
- data/spec/spec_helper_acceptance.rb +16 -3
- metadata +13 -69
- data/.travis.yml +0 -60
- data/spec/acceptance/20_pkg_rpm_upgrade_spec.rb +0 -236
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-2.1/CHANGELOG +0 -2
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-2.1/Rakefile +0 -3
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-2.1/build/rpm_metadata/custom/overrides +0 -14
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-2.1/build/rpm_metadata/requires +0 -1
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-2.1/metadata.json +0 -33
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-3.0/CHANGELOG +0 -2
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-3.0/Rakefile +0 -3
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-3.0/build/rpm_metadata/custom/overrides +0 -14
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-3.0/build/rpm_metadata/requires +0 -1
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-3.0/metadata.json +0 -33
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-1.0/CHANGELOG +0 -2
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-1.0/Rakefile +0 -3
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-1.0/build/rpm_metadata/requires +0 -1
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-1.0/metadata.json +0 -33
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-2.0/CHANGELOG +0 -2
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-2.0/Rakefile +0 -3
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-2.0/build/rpm_metadata/requires +0 -1
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-2.0/metadata.json +0 -33
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-2.2/CHANGELOG +0 -2
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-2.2/Rakefile +0 -3
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-2.2/build/rpm_metadata/custom/overrides +0 -14
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-2.2/build/rpm_metadata/requires +0 -1
- data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-2.2/metadata.json +0 -33
- data/spec/acceptance/files/mock_packages/pupmod-puppetlabs-stdlib.spec +0 -32
- data/spec/acceptance/files/mock_packages/pupmod-simp-foo.spec +0 -32
- data/spec/acceptance/files/mock_packages/pupmod-simp-simplib.spec +0 -32
- data/spec/acceptance/files/mock_packages/rpmbuild.sh +0 -25
- data/spec/acceptance/files/mock_packages/simp-adapter.spec +0 -43
- data/spec/acceptance/files/mock_packages/simp-adapter/etc/simp/adapter_config.yaml +0 -3
- data/spec/acceptance/files/mock_packages/simp-adapter/usr/local/sbin/simp_rpm_helper +0 -495
- data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-1.0/CHANGELOG +0 -2
- data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-1.0/Rakefile +0 -3
- data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-1.0/build/rpm_metadata/requires +0 -2
- data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-1.0/data/os/CentOS.yaml +0 -2
- data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-1.0/data/os/RedHat.yaml +0 -2
- data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-1.0/hiera.yaml +0 -14
- data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-1.0/manifests/init.pp +0 -2
- data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-1.0/metadata.json +0 -37
- data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-2.0/CHANGELOG +0 -5
- data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-2.0/Rakefile +0 -3
- data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-2.0/build/rpm_metadata/requires +0 -2
- data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-2.0/data/os/CentOS.yaml +0 -2
- data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-2.0/data/os/RedHat.yaml +0 -2
- data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-2.0/hiera.yaml +0 -14
- data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-2.0/manifests/init.pp +0 -3
- data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-2.0/metadata.json +0 -37
- data/spec/lib/simp/ci/files/job_broken_link_nodeset/spec/acceptance/suites/default/nodesets +0 -1
- data/spec/lib/simp/ci/files/job_invalid_nodeset/spec/acceptance/suites/default/nodesets +0 -1
- data/spec/lib/simp/ci/files/job_invalid_suite/spec/acceptance/suites/default/nodesets +0 -1
- data/spec/lib/simp/ci/files/job_missing_nodeset/spec/acceptance/suites/default/nodesets +0 -1
- data/spec/lib/simp/ci/files/job_missing_suite_and_nodeset/spec/acceptance/suites/default/nodesets +0 -1
- data/spec/lib/simp/ci/files/multiple_invalid_jobs/spec/acceptance/suites/default/nodesets +0 -1
- data/spec/lib/simp/ci/files/multiple_valid_jobs/spec/acceptance/suites/default/nodesets +0 -1
- data/spec/lib/simp/ci/files/no_gitlab_config_with_tests/spec/acceptance/suites/default/nodesets +0 -1
- data/spec/lib/simp/ci/files/no_gitlab_config_without_tests/spec/acceptance/suites/default/nodesets +0 -1
- data/spec/lib/simp/ci/files/suite_skeleton_only/spec/acceptance/nodesets/default.yml +0 -1
- data/spec/lib/simp/ci/files/suite_skeleton_only/spec/acceptance/suites/default/nodesets +0 -1
- data/spec/lib/simp/ci/files/valid_job_nodeset_dir_link/spec/acceptance/suites/default/nodesets +0 -1
- data/spec/lib/simp/ci/files/valid_job_nodeset_link/spec/acceptance/suites/default/nodesets/default.yml +0 -1
- data/spec/lib/simp/files/build/testpackage.spec +0 -1
- data/spec/lib/simp/rake/pupmod/fixtures/simpmod/spec/acceptance/nodesets/default.yml +0 -1
- data/spec/lib/simp/rake/pupmod/fixtures/simpmod/spec/acceptance/suites/default/nodesets +0 -1
data/lib/simp/rake/build/tar.rb
CHANGED
@@ -62,7 +62,7 @@ module Simp::Rake::Build
|
|
62
62
|
else
|
63
63
|
required_rpms['noarch'] << 'simp-rsync-skeleton'
|
64
64
|
required_rpms['noarch'] << 'simp-environment-skeleton'
|
65
|
-
required_rpms['noarch'] << 'simp-
|
65
|
+
required_rpms['noarch'] << 'simp-selinux-policy'
|
66
66
|
end
|
67
67
|
|
68
68
|
rpm_dir = File.join(@build_dir,'SIMP','RPMS')
|
data/lib/simp/rake/pkg.rb
CHANGED
@@ -235,7 +235,11 @@ module Simp::Rake
|
|
235
235
|
%(-D '_sourcedir #{@rpm_srcdir}'),
|
236
236
|
%(-D '_rpmdir #{@pkg_dir}'),
|
237
237
|
%(-D '_srcrpmdir #{@pkg_dir}'),
|
238
|
-
%(-D '_build_name_fmt %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm')
|
238
|
+
%(-D '_build_name_fmt %%{NAME}-%%{VERSION}-%%{RELEASE}.%%{ARCH}.rpm'),
|
239
|
+
|
240
|
+
# needed on EL8 to disable the aggressive brp_mangle_shebangs script
|
241
|
+
# that results in invalid script shebangs; does nothing in EL7
|
242
|
+
%(-D '__brp_mangle_shebangs /usr/bin/true')
|
239
243
|
]
|
240
244
|
rpm_opts << '-v' if @verbose
|
241
245
|
rpm_opts << "-D 'lua_debug 1'" if (ENV.fetch('SIMP_RAKE_PKG_LUA_verbose','no') =='yes')
|
@@ -290,6 +290,7 @@ class Simp::Rake::Pupmod::Helpers < ::Rake::TaskLib
|
|
290
290
|
# That will give Travis a way of warning us if the changelog
|
291
291
|
# will prevent the rpm from building.
|
292
292
|
task :changelog_annotation, [:quiet] do |t,args|
|
293
|
+
warning('DEPRECATED: use pkg:create_tag_changelog')
|
293
294
|
quiet = true if args[:quiet].to_s == 'true'
|
294
295
|
puts changelog_annotation( quiet )
|
295
296
|
end
|
@@ -332,6 +333,7 @@ class Simp::Rake::Pupmod::Helpers < ::Rake::TaskLib
|
|
332
333
|
- doc directory
|
333
334
|
EOM
|
334
335
|
task :compare_latest_tag, [:tags_source, :ignore_owner, :verbose] do |t,args|
|
336
|
+
warning('DEPRECATED: use pkg:compare_latest_tag')
|
335
337
|
require 'json'
|
336
338
|
|
337
339
|
tags_source = args[:tags_source].nil? ? 'origin' : args[:tags_source]
|
data/lib/simp/rake/rubygem.rb
CHANGED
@@ -49,7 +49,11 @@ module Simp::Rake
|
|
49
49
|
task :install_gem => [:clean, :gem] do
|
50
50
|
Dir.chdir @rakefile_dir
|
51
51
|
Dir.glob("dist/#{@package}*.gem") do |pkg|
|
52
|
-
|
52
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new('2.6')
|
53
|
+
sh %Q{bundle exec gem install --no-document #{pkg}}
|
54
|
+
else
|
55
|
+
sh %Q{bundle exec gem install --no-ri --no-rdoc #{pkg}}
|
56
|
+
end
|
53
57
|
end
|
54
58
|
end
|
55
59
|
end
|
data/lib/simp/relchecks.rb
CHANGED
@@ -87,7 +87,7 @@ class Simp::RelChecks
|
|
87
87
|
# determine mission-impacting files that have changed
|
88
88
|
files_changed = `git diff tags/#{last_tag} --name-only`.strip.split("\n")
|
89
89
|
files_changed.delete_if do |file|
|
90
|
-
file[0] == '.' or file == 'Rakefile' or file =~ /^Gemfile|^spec\/|^doc\/|^rakelib
|
90
|
+
file[0] == '.' or file == 'Rakefile' or file =~ /^Gemfile|^spec\/|^doc\/|^rakelib\/|.*\.md\Z/
|
91
91
|
end
|
92
92
|
|
93
93
|
if files_changed.empty?
|
data/lib/simp/rpm.rb
CHANGED
@@ -14,7 +14,6 @@ module Simp
|
|
14
14
|
require 'pty'
|
15
15
|
require 'rake'
|
16
16
|
|
17
|
-
@@gpg_keys = Hash.new
|
18
17
|
attr_reader :verbose, :lua_debug, :packages
|
19
18
|
|
20
19
|
if Gem.loaded_specs['rake'].version >= Gem::Version.new('0.9')
|
@@ -402,20 +401,20 @@ module Simp
|
|
402
401
|
end
|
403
402
|
|
404
403
|
if version_results[:exit_status] != 0
|
405
|
-
raise
|
406
|
-
#{indent('Error getting RPM info:', 2)}
|
407
|
-
#{indent(version_results[:stderr].strip, 5)}
|
408
|
-
#{indent("Run '#{rpm_version_query.gsub("\n",'\\n')} #{query_source}' to recreate the issue.", 2)}
|
409
|
-
EOE
|
404
|
+
raise <<~EOE
|
405
|
+
#{indent('Error getting RPM info for #{query_source}:', 2)}
|
406
|
+
#{indent(version_results[:stderr].strip, 5)}
|
407
|
+
#{indent("Run '#{rpm_version_query.gsub("\n",'\\n')} #{query_source}' to recreate the issue.", 2)}
|
408
|
+
EOE
|
410
409
|
end
|
411
410
|
|
412
411
|
unless signature_results.nil?
|
413
412
|
if signature_results[:exit_status] != 0
|
414
|
-
raise
|
415
|
-
#{indent('Error getting RPM signature:', 2)}
|
416
|
-
#{indent(signature_results[:stderr].strip, 5)}
|
417
|
-
#{indent("Run '#{rpm_signature_query.gsub("\n",'\\n')} #{query_source}' to recreate the issue.", 2)}
|
418
|
-
EOE
|
413
|
+
raise <<~EOE
|
414
|
+
#{indent('Error getting RPM signature for #{query_source}:', 2)}
|
415
|
+
#{indent(signature_results[:stderr].strip, 5)}
|
416
|
+
#{indent("Run '#{rpm_signature_query.gsub("\n",'\\n')} #{query_source}' to recreate the issue.", 2)}
|
417
|
+
EOE
|
419
418
|
else
|
420
419
|
signature = signature_results[:stdout].strip
|
421
420
|
end
|
@@ -498,120 +497,9 @@ EOE
|
|
498
497
|
end
|
499
498
|
end
|
500
499
|
|
501
|
-
#
|
502
|
-
|
503
|
-
|
504
|
-
# for it.
|
505
|
-
def self.load_key(gpg_key)
|
506
|
-
keydir = gpg_key
|
507
|
-
File.directory?(keydir) || fail("Error: Could not find '#{keydir}'")
|
508
|
-
|
509
|
-
gpg_key = File.basename(gpg_key)
|
510
|
-
|
511
|
-
if @@gpg_keys[gpg_key]
|
512
|
-
return @@gpg_keys[gpg_key]
|
513
|
-
end
|
514
|
-
|
515
|
-
gpg_name = nil
|
516
|
-
gpg_password = nil
|
517
|
-
begin
|
518
|
-
File.read("#{keydir}/gengpgkey").each_line do |ln|
|
519
|
-
name_line = ln.split(/^\s*Name-Email:/)
|
520
|
-
if name_line.length > 1
|
521
|
-
gpg_name = name_line.last.strip
|
522
|
-
end
|
523
|
-
|
524
|
-
passwd_line = ln.split(/^\s*Passphrase:/)
|
525
|
-
if passwd_line.length > 1
|
526
|
-
gpg_password = passwd_line.last.strip
|
527
|
-
end
|
528
|
-
end
|
529
|
-
rescue Errno::ENOENT
|
530
|
-
end
|
531
|
-
|
532
|
-
if gpg_name.nil?
|
533
|
-
puts "Warning: Could not find valid e-mail address for use with GPG."
|
534
|
-
puts "Please enter e-mail address to use:"
|
535
|
-
gpg_name = $stdin.gets.strip
|
536
|
-
end
|
537
|
-
|
538
|
-
if gpg_password.nil?
|
539
|
-
if File.exist?(%(#{keydir}/password))
|
540
|
-
gpg_password = File.read(%(#{keydir}/password)).chomp
|
541
|
-
end
|
542
|
-
|
543
|
-
if gpg_password.nil?
|
544
|
-
puts "Warning: Could not find a password in '#{keydir}/password'!"
|
545
|
-
puts "Please enter your GPG key password:"
|
546
|
-
system 'stty -echo'
|
547
|
-
gpg_password = $stdin.gets.strip
|
548
|
-
system 'stty echo'
|
549
|
-
end
|
550
|
-
end
|
551
|
-
|
552
|
-
gpg_key_size = nil
|
553
|
-
gpg_key_id = nil
|
554
|
-
%x(gpg --homedir=#{keydir} --list-keys #{gpg_name} 2>&1).each_line do |line|
|
555
|
-
head,data = line.split(/\s+/)
|
556
|
-
if head == 'pub'
|
557
|
-
gpg_key_size,gpg_key_id = data.split('/')
|
558
|
-
break
|
559
|
-
end
|
560
|
-
end
|
561
|
-
|
562
|
-
if !gpg_key_size || !gpg_key_id
|
563
|
-
fail("Error getting GPG Key metadata")
|
564
|
-
end
|
565
|
-
|
566
|
-
@@gpg_keys[gpg_key] = {
|
567
|
-
:dir => keydir,
|
568
|
-
:name => gpg_name,
|
569
|
-
:key_id => gpg_key_id,
|
570
|
-
:key_size => gpg_key_size,
|
571
|
-
:password => gpg_password
|
572
|
-
}
|
573
|
-
end
|
574
|
-
|
575
|
-
# Signs the given RPM with the given gpg_key (see Simp::RPM.load_key for
|
576
|
-
# details on the value of this parameter).
|
577
|
-
def self.signrpm(rpm, gpg_key)
|
578
|
-
gpgkey = load_key(gpg_key)
|
579
|
-
|
580
|
-
gpg_sig = nil
|
581
|
-
%x(rpm -Kv #{rpm}).each_line do |line|
|
582
|
-
if line =~ /key\sID\s(.*):/
|
583
|
-
gpg_sig = $1.strip
|
584
|
-
end
|
585
|
-
end
|
586
|
-
|
587
|
-
unless gpg_sig == gpgkey[:key_id]
|
588
|
-
signcommand = "rpm " +
|
589
|
-
"--define '%_signature gpg' " +
|
590
|
-
"--define '%__gpg %{_bindir}/gpg' " +
|
591
|
-
"--define '%_gpg_name #{gpgkey[:name]}' " +
|
592
|
-
"--define '%_gpg_path #{gpgkey[:dir]}' " +
|
593
|
-
"--resign #{rpm}"
|
594
|
-
begin
|
595
|
-
PTY.spawn(signcommand) do |read, write, pid|
|
596
|
-
begin
|
597
|
-
while !read.eof? do
|
598
|
-
read.expect(/pass\s?phrase:.*/) do |text|
|
599
|
-
write.puts(gpgkey[:password])
|
600
|
-
write.flush
|
601
|
-
end
|
602
|
-
end
|
603
|
-
rescue Errno::EIO
|
604
|
-
# This ALWAYS happens in Ruby 1.8.
|
605
|
-
end
|
606
|
-
Process.wait(pid)
|
607
|
-
end
|
608
|
-
|
609
|
-
raise "Failure running #{signcommand}" unless $?.success?
|
610
|
-
rescue Exception => e
|
611
|
-
puts "Error occured while attempting to sign #{rpm}, skipping."
|
612
|
-
puts e
|
613
|
-
end
|
614
|
-
end
|
500
|
+
# Returns the version of RPM installed on the system
|
501
|
+
def self.version
|
502
|
+
%x{rpm --version}.strip.split.last
|
615
503
|
end
|
616
504
|
end
|
617
505
|
end
|
@@ -0,0 +1,321 @@
|
|
1
|
+
require 'find'
|
2
|
+
require 'parallel'
|
3
|
+
require 'simp/rpm'
|
4
|
+
require 'simp/command_utils'
|
5
|
+
|
6
|
+
module Simp; end
|
7
|
+
|
8
|
+
# Class to sign RPMs. Uses 'gpg' and 'rpm' executables.
|
9
|
+
class Simp::RpmSigner
|
10
|
+
require 'expect'
|
11
|
+
require 'pty'
|
12
|
+
|
13
|
+
extend Simp::CommandUtils
|
14
|
+
|
15
|
+
@@gpg_keys = Hash.new
|
16
|
+
|
17
|
+
# Kill the GPG agent operating with the specified key dir, if
|
18
|
+
# rpm version 4.13.0 or later.
|
19
|
+
#
|
20
|
+
# Beginning with version 4.13.0, rpm stands up a gpg-agent when
|
21
|
+
# a signing operation is requested.
|
22
|
+
def self.kill_gpg_agent(gpg_keydir)
|
23
|
+
return if Gem::Version.new(Simp::RPM.version) < Gem::Version.new('4.13.0')
|
24
|
+
|
25
|
+
%x(gpg-agent --homedir #{gpg_keydir} -q >& /dev/null)
|
26
|
+
if $? && ($?.exitstatus == 0)
|
27
|
+
# gpg-agent is running for specified keydir, so query it for its pid
|
28
|
+
output = %x{echo 'GETINFO pid' | gpg-connect-agent --homedir=#{gpg_keydir}}
|
29
|
+
if $? && ($?.exitstatus == 0)
|
30
|
+
pid = output.lines.first[1..-1].strip.to_i
|
31
|
+
begin
|
32
|
+
Process.kill(0, pid)
|
33
|
+
Process.kill(15, pid)
|
34
|
+
rescue Errno::ESRCH
|
35
|
+
# No longer running, so nothing to do!
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Loads metadata for a GPG key found in gpg_keydir.
|
42
|
+
#
|
43
|
+
# The GPG key is to be used to sign RPMs. If the required metadata cannot be
|
44
|
+
# retrieved from files found in the gpg_keydir, the user will be prompted
|
45
|
+
# for it.
|
46
|
+
#
|
47
|
+
# @param gpg_keydir The full path of the directory where the key resides
|
48
|
+
# @param verbose Whether to log debug information.
|
49
|
+
#
|
50
|
+
# @raise If the 'gpg' executable cannot be found, the GPG key directory
|
51
|
+
# does not exist or GPG key metadata cannot be determined via 'gpg'
|
52
|
+
#
|
53
|
+
def self.load_key(gpg_keydir, verbose = false)
|
54
|
+
which('gpg') || raise("ERROR: Cannot sign RPMs without 'gpg'")
|
55
|
+
File.directory?(gpg_keydir) || raise("ERROR: Could not find GPG keydir '#{gpg_keydir}'")
|
56
|
+
|
57
|
+
gpg_key = File.basename(gpg_keydir)
|
58
|
+
|
59
|
+
if @@gpg_keys[gpg_key]
|
60
|
+
return @@gpg_keys[gpg_key]
|
61
|
+
end
|
62
|
+
|
63
|
+
gpg_name = nil
|
64
|
+
gpg_password = nil
|
65
|
+
begin
|
66
|
+
File.read("#{gpg_keydir}/gengpgkey").each_line do |ln|
|
67
|
+
name_line = ln.split(/^\s*Name-Email:/)
|
68
|
+
if name_line.length > 1
|
69
|
+
gpg_name = name_line.last.strip
|
70
|
+
end
|
71
|
+
|
72
|
+
passwd_line = ln.split(/^\s*Passphrase:/)
|
73
|
+
if passwd_line.length > 1
|
74
|
+
gpg_password = passwd_line.last.strip
|
75
|
+
end
|
76
|
+
end
|
77
|
+
rescue Errno::ENOENT
|
78
|
+
end
|
79
|
+
|
80
|
+
if gpg_name.nil?
|
81
|
+
puts "Warning: Could not find valid e-mail address for use with GPG."
|
82
|
+
puts "Please enter e-mail address to use:"
|
83
|
+
gpg_name = $stdin.gets.strip
|
84
|
+
end
|
85
|
+
|
86
|
+
if gpg_password.nil?
|
87
|
+
if File.exist?(%(#{gpg_keydir}/password))
|
88
|
+
gpg_password = File.read(%(#{gpg_keydir}/password)).chomp
|
89
|
+
end
|
90
|
+
|
91
|
+
if gpg_password.nil?
|
92
|
+
puts "Warning: Could not find a password in '#{gpg_keydir}/password'!"
|
93
|
+
puts "Please enter your GPG key password:"
|
94
|
+
system 'stty -echo'
|
95
|
+
gpg_password = $stdin.gets.strip
|
96
|
+
system 'stty echo'
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
gpg_key_size = nil
|
101
|
+
gpg_key_id = nil
|
102
|
+
cmd = "gpg --with-colons --homedir=#{gpg_keydir} --list-keys '<#{gpg_name}>' 2>&1"
|
103
|
+
puts "Executing: #{cmd}" if verbose
|
104
|
+
%x(#{cmd}).each_line do |line|
|
105
|
+
# See https://github.com/CSNW/gnupg/blob/master/doc/DETAILS
|
106
|
+
# Index Content
|
107
|
+
# 0 record type
|
108
|
+
# 2 key length
|
109
|
+
# 4 keyID
|
110
|
+
fields = line.split(':')
|
111
|
+
if fields[0] && (fields[0] == 'pub')
|
112
|
+
gpg_key_size = fields[2].to_i
|
113
|
+
gpg_key_id = fields[4]
|
114
|
+
break
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
if !gpg_key_size || !gpg_key_id
|
119
|
+
raise("Error getting GPG key ID or Key size metadata for #{gpg_name}")
|
120
|
+
end
|
121
|
+
|
122
|
+
@@gpg_keys[gpg_key] = {
|
123
|
+
:dir => gpg_keydir,
|
124
|
+
:name => gpg_name,
|
125
|
+
:key_id => gpg_key_id,
|
126
|
+
:key_size => gpg_key_size,
|
127
|
+
:password => gpg_password
|
128
|
+
}
|
129
|
+
end
|
130
|
+
|
131
|
+
# Signs the given RPM with the GPG key found in gpg_keydir
|
132
|
+
#
|
133
|
+
# @param rpm Fully qualified path to an RPM to be signed.
|
134
|
+
# @param gpg_keydir The full path of the directory where the key resides.
|
135
|
+
# @param options Options Hash
|
136
|
+
#
|
137
|
+
# @options options :digest_algo Digest algorithm to use in RPM
|
138
|
+
# signing operation; defaults to 'sha256'
|
139
|
+
# @options options :timeout_seconds Timeout in seconds for an individual
|
140
|
+
# RPM signing operation; defaults to 60.
|
141
|
+
# @options options :verbose Whether to log debug information;
|
142
|
+
# defaults to false.
|
143
|
+
#
|
144
|
+
# @return Whether package signing operation succeeded
|
145
|
+
# @raise RuntimeError if 'rpmsign' executable cannot be found, the 'gpg
|
146
|
+
# 'executable cannot be found, the GPG key directory does not exist or
|
147
|
+
# the GPG key metadata cannot be determined via 'gpg'
|
148
|
+
def self.sign_rpm(rpm, gpg_keydir, options={})
|
149
|
+
# This may be a little confusing...Although we're using 'rpm --resign'
|
150
|
+
# in lieu of 'rpmsign --addsign', they are equivalent and the presence
|
151
|
+
# of 'rpmsign' is a legitimate check that the 'rpm --resign' capability
|
152
|
+
# is available (i.e., rpm-sign package has been installed).
|
153
|
+
which('rpmsign') || raise("ERROR: Cannot sign RPMs without 'rpmsign'.")
|
154
|
+
|
155
|
+
digest_algo = options.key?(:digest_algo) ? options[:digest_algo] : 'sha256'
|
156
|
+
timeout_seconds = options.key?(:timeout_seconds) ? options[:timeout_seconds] : 60
|
157
|
+
verbose = options.key?(:verbose) ? options[:verbose] : false
|
158
|
+
|
159
|
+
gpgkey = load_key(gpg_keydir, verbose)
|
160
|
+
|
161
|
+
gpg_sign_cmd_extra_args = nil
|
162
|
+
if Gem::Version.new(Simp::RPM.version) >= Gem::Version.new('4.13.0')
|
163
|
+
gpg_sign_cmd_extra_args = "--define '%_gpg_sign_cmd_extra_args --pinentry-mode loopback --verbose'"
|
164
|
+
end
|
165
|
+
|
166
|
+
signcommand = [
|
167
|
+
'rpm',
|
168
|
+
"--define '%_signature gpg'",
|
169
|
+
"--define '%__gpg %{_bindir}/gpg'",
|
170
|
+
"--define '%_gpg_name #{gpgkey[:name]}'",
|
171
|
+
"--define '%_gpg_path #{gpgkey[:dir]}'",
|
172
|
+
"--define '%_gpg_digest_algo #{digest_algo}'",
|
173
|
+
gpg_sign_cmd_extra_args,
|
174
|
+
"--resign #{rpm}"
|
175
|
+
].compact.join(' ')
|
176
|
+
|
177
|
+
success = false
|
178
|
+
begin
|
179
|
+
if verbose
|
180
|
+
puts "Signing #{rpm} with #{gpgkey[:name]} from #{gpgkey[:dir]}:\n #{signcommand}"
|
181
|
+
end
|
182
|
+
|
183
|
+
require 'timeout'
|
184
|
+
# With rpm-sign-4.14.2-11.el8_0 (EL 8.0), if rpm cannot start the
|
185
|
+
# gpg-agent daemon, it will just hang. We need to be able to detect
|
186
|
+
# the problem and report the failure.
|
187
|
+
Timeout::timeout(timeout_seconds) do
|
188
|
+
|
189
|
+
status = nil
|
190
|
+
PTY.spawn(signcommand) do |read, write, pid|
|
191
|
+
begin
|
192
|
+
while !read.eof? do
|
193
|
+
# rpm version >= 4.13.0 will stand up a gpg-agent and so the
|
194
|
+
# prompt for the passphrase will only actually happen if this is
|
195
|
+
# the first RPM to be signed with the key after the gpg-agent is
|
196
|
+
# started and the key's passphrase has not been cleared from the
|
197
|
+
# agent's cache.
|
198
|
+
read.expect(/pass\s?phrase:.*/) do |text|
|
199
|
+
write.puts(gpgkey[:password])
|
200
|
+
write.flush
|
201
|
+
end
|
202
|
+
end
|
203
|
+
rescue Errno::EIO
|
204
|
+
# Will get here once input is no longer needed, which can be
|
205
|
+
# immediately, if a gpg-agent is already running and the
|
206
|
+
# passphrase for the key is loaded in its cache.
|
207
|
+
end
|
208
|
+
|
209
|
+
Process.wait(pid)
|
210
|
+
status = $?
|
211
|
+
end
|
212
|
+
|
213
|
+
if status && !status.success?
|
214
|
+
raise "Failure running <#{signcommand}>"
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
puts "Successfully signed #{rpm}" if verbose
|
219
|
+
success = true
|
220
|
+
|
221
|
+
rescue Timeout::Error
|
222
|
+
$stderr.puts "Failed to sign #{rpm} in #{timeout_seconds} seconds."
|
223
|
+
rescue Exception => e
|
224
|
+
$stderr.puts "Error occurred while attempting to sign #{rpm}:"
|
225
|
+
$stderr.puts e
|
226
|
+
end
|
227
|
+
|
228
|
+
success
|
229
|
+
end
|
230
|
+
|
231
|
+
# Signs any RPMs found within the entire rpm_dir directory tree with
|
232
|
+
# the GPG key found in gpg_keydir
|
233
|
+
#
|
234
|
+
# @param rpm_dir A directory or directory glob pattern specifying 1 or
|
235
|
+
# more directories containing RPM files to sign.
|
236
|
+
# @param gpg_keydir The full path of the directory where the key resides
|
237
|
+
# @param options Options Hash
|
238
|
+
#
|
239
|
+
# @options options :digest_algo Digest algorithm to use in RPM
|
240
|
+
# signing operation; defaults to
|
241
|
+
# 'sha256'
|
242
|
+
# @options options :force Force RPMs that are already signed
|
243
|
+
# to be resigned; defaults to false.
|
244
|
+
# @options options :max_concurrent Maximum number of concurrent RPM
|
245
|
+
# signing operations; defaults to 1.
|
246
|
+
# @options options :progress_bar_title Title for the progress bar logged to
|
247
|
+
# the console during the signing process;
|
248
|
+
# defaults to 'sign_rpms'.
|
249
|
+
# @options options :timeout_seconds Timeout in seconds for an individual
|
250
|
+
# RPM signing operation; defauls to 60.
|
251
|
+
# @options options :verbose Whether to log debug information;
|
252
|
+
# defaults to false.
|
253
|
+
#
|
254
|
+
# @return Hash of RPM signing results or nil if no RPMs found in rpm_dir
|
255
|
+
# * Each Hash key is the path to a RPM
|
256
|
+
# * Each Hash value is the status of the signing operation: :signed,
|
257
|
+
# :unsigned, :skipped_already_signed
|
258
|
+
#
|
259
|
+
# @raise RuntimeError if 'rpmsign' executable cannot be found, the 'gpg'
|
260
|
+
# executable cannot be found, the GPG key directory does not exist,
|
261
|
+
# the GPG key metadata cannot be determined via 'gpg' or any RPM signing
|
262
|
+
# operation failed
|
263
|
+
#
|
264
|
+
def self.sign_rpms(rpm_dir, gpg_keydir, options = {})
|
265
|
+
opts = {
|
266
|
+
:digest_algo => 'sha256',
|
267
|
+
:force => false,
|
268
|
+
:max_concurrent => 1,
|
269
|
+
:progress_bar_title => 'sign_rpms',
|
270
|
+
:timeout_seconds => 60,
|
271
|
+
:verbose => false
|
272
|
+
}.merge(options)
|
273
|
+
|
274
|
+
rpm_dirs = Dir.glob(rpm_dir)
|
275
|
+
to_sign = []
|
276
|
+
|
277
|
+
rpm_dirs.each do |rpm_dir|
|
278
|
+
Find.find(rpm_dir) do |rpm|
|
279
|
+
next unless File.readable?(rpm)
|
280
|
+
to_sign << rpm if rpm =~ /\.rpm$/
|
281
|
+
end
|
282
|
+
end
|
283
|
+
|
284
|
+
return nil if to_sign.empty?
|
285
|
+
|
286
|
+
results = []
|
287
|
+
begin
|
288
|
+
results = Parallel.map(
|
289
|
+
to_sign,
|
290
|
+
:in_processes => opts[:max_concurrent],
|
291
|
+
:progress => opts[:progress_bar_title]
|
292
|
+
) do |rpm|
|
293
|
+
_result = nil
|
294
|
+
|
295
|
+
begin
|
296
|
+
if opts[:force] || !Simp::RPM.new(rpm).signature
|
297
|
+
_result = [ rpm, sign_rpm(rpm, gpg_keydir, opts) ]
|
298
|
+
_result[1] = _result[1] ? :signed : :unsigned
|
299
|
+
else
|
300
|
+
puts "Skipping signed package #{rpm}" if opts[:verbose]
|
301
|
+
_result = [ rpm, :skipped_already_signed ]
|
302
|
+
end
|
303
|
+
rescue Exception => e
|
304
|
+
# can get here if rpm is malformed and Simp::RPM.new fails
|
305
|
+
$stderr.puts "Failed to sign #{rpm}:\n#{e.message}"
|
306
|
+
_result = [ rpm, :unsigned ]
|
307
|
+
end
|
308
|
+
|
309
|
+
_result
|
310
|
+
end
|
311
|
+
ensure
|
312
|
+
kill_gpg_agent(gpg_keydir)
|
313
|
+
end
|
314
|
+
|
315
|
+
results.to_h
|
316
|
+
end
|
317
|
+
|
318
|
+
def self.clear_gpg_keys_cache
|
319
|
+
@@gpg_keys.clear
|
320
|
+
end
|
321
|
+
end
|