simp-rake-helpers 5.11.6 → 5.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +28 -0
  3. data/CONTRIBUTING.md +1 -1
  4. data/README.md +1 -1
  5. data/lib/simp/command_utils.rb +21 -0
  6. data/lib/simp/local_gpg_signing_key.rb +128 -79
  7. data/lib/simp/rake.rb +3 -17
  8. data/lib/simp/rake/build/pkg.rb +102 -40
  9. data/lib/simp/rake/helpers/version.rb +1 -1
  10. data/lib/simp/rake/pkg.rb +5 -1
  11. data/lib/simp/rake/pupmod/helpers.rb +2 -0
  12. data/lib/simp/rake/rubygem.rb +5 -1
  13. data/lib/simp/rpm.rb +10 -127
  14. data/lib/simp/rpm_signer.rb +321 -0
  15. data/spec/acceptance/00_pkg_rpm_custom_scriptlets_spec.rb +18 -19
  16. data/spec/acceptance/10_pkg_rpm_spec.rb +46 -48
  17. data/spec/acceptance/50_local_gpg_signing_key_spec.rb +7 -3
  18. data/spec/acceptance/55_build_pkg_signing_spec.rb +293 -42
  19. data/spec/acceptance/files/testpackage/README +8 -0
  20. data/spec/acceptance/files/testpackage/spec/classes/init_spec.rb +1 -0
  21. data/spec/acceptance/files/testpackage/spec/files/mock_something.rb +3 -0
  22. data/spec/acceptance/files/testpackage/utils/convert_v1_to_v2.rb +3 -0
  23. data/spec/acceptance/nodesets/default.yml +15 -2
  24. data/spec/acceptance/support/build_project_helpers.rb +32 -8
  25. data/spec/lib/simp/command_utils_spec.rb +29 -0
  26. data/spec/lib/simp/local_gpg_signing_key_spec.rb.beaker-only +115 -18
  27. data/spec/lib/simp/rake/pupmod/fixtures/simpmod/README.md +2 -2
  28. data/spec/lib/simp/rpm_signer_spec.rb +98 -0
  29. data/spec/lib/simp/rpm_spec.rb +0 -6
  30. metadata +12 -67
  31. data/.travis.yml +0 -41
  32. data/spec/acceptance/20_pkg_rpm_upgrade_spec.rb +0 -236
  33. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-2.1/CHANGELOG +0 -2
  34. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-2.1/Rakefile +0 -3
  35. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-2.1/build/rpm_metadata/custom/overrides +0 -14
  36. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-2.1/build/rpm_metadata/requires +0 -1
  37. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-2.1/metadata.json +0 -33
  38. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-3.0/CHANGELOG +0 -2
  39. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-3.0/Rakefile +0 -3
  40. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-3.0/build/rpm_metadata/custom/overrides +0 -14
  41. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-3.0/build/rpm_metadata/requires +0 -1
  42. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-3.0/metadata.json +0 -33
  43. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-1.0/CHANGELOG +0 -2
  44. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-1.0/Rakefile +0 -3
  45. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-1.0/build/rpm_metadata/requires +0 -1
  46. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-1.0/metadata.json +0 -33
  47. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-2.0/CHANGELOG +0 -2
  48. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-2.0/Rakefile +0 -3
  49. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-2.0/build/rpm_metadata/requires +0 -1
  50. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-2.0/metadata.json +0 -33
  51. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-2.2/CHANGELOG +0 -2
  52. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-2.2/Rakefile +0 -3
  53. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-2.2/build/rpm_metadata/custom/overrides +0 -14
  54. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-2.2/build/rpm_metadata/requires +0 -1
  55. data/spec/acceptance/files/custom_scriptlet_triggers/pupmod-old-package-2.2/metadata.json +0 -33
  56. data/spec/acceptance/files/mock_packages/pupmod-puppetlabs-stdlib.spec +0 -32
  57. data/spec/acceptance/files/mock_packages/pupmod-simp-foo.spec +0 -32
  58. data/spec/acceptance/files/mock_packages/pupmod-simp-simplib.spec +0 -32
  59. data/spec/acceptance/files/mock_packages/rpmbuild.sh +0 -25
  60. data/spec/acceptance/files/mock_packages/simp-adapter.spec +0 -43
  61. data/spec/acceptance/files/mock_packages/simp-adapter/etc/simp/adapter_config.yaml +0 -3
  62. data/spec/acceptance/files/mock_packages/simp-adapter/usr/local/sbin/simp_rpm_helper +0 -495
  63. data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-1.0/CHANGELOG +0 -2
  64. data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-1.0/Rakefile +0 -3
  65. data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-1.0/build/rpm_metadata/requires +0 -2
  66. data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-1.0/data/os/CentOS.yaml +0 -2
  67. data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-1.0/data/os/RedHat.yaml +0 -2
  68. data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-1.0/hiera.yaml +0 -14
  69. data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-1.0/manifests/init.pp +0 -2
  70. data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-1.0/metadata.json +0 -37
  71. data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-2.0/CHANGELOG +0 -5
  72. data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-2.0/Rakefile +0 -3
  73. data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-2.0/build/rpm_metadata/requires +0 -2
  74. data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-2.0/data/os/CentOS.yaml +0 -2
  75. data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-2.0/data/os/RedHat.yaml +0 -2
  76. data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-2.0/hiera.yaml +0 -14
  77. data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-2.0/manifests/init.pp +0 -3
  78. data/spec/acceptance/files/package_upgrades/pupmod-simp-testpackage-2.0/metadata.json +0 -37
  79. data/spec/lib/simp/ci/files/job_broken_link_nodeset/spec/acceptance/suites/default/nodesets +0 -1
  80. data/spec/lib/simp/ci/files/job_invalid_nodeset/spec/acceptance/suites/default/nodesets +0 -1
  81. data/spec/lib/simp/ci/files/job_invalid_suite/spec/acceptance/suites/default/nodesets +0 -1
  82. data/spec/lib/simp/ci/files/job_missing_nodeset/spec/acceptance/suites/default/nodesets +0 -1
  83. data/spec/lib/simp/ci/files/job_missing_suite_and_nodeset/spec/acceptance/suites/default/nodesets +0 -1
  84. data/spec/lib/simp/ci/files/multiple_invalid_jobs/spec/acceptance/suites/default/nodesets +0 -1
  85. data/spec/lib/simp/ci/files/multiple_valid_jobs/spec/acceptance/suites/default/nodesets +0 -1
  86. data/spec/lib/simp/ci/files/no_gitlab_config_with_tests/spec/acceptance/suites/default/nodesets +0 -1
  87. data/spec/lib/simp/ci/files/no_gitlab_config_without_tests/spec/acceptance/suites/default/nodesets +0 -1
  88. data/spec/lib/simp/ci/files/suite_skeleton_only/spec/acceptance/nodesets/default.yml +0 -1
  89. data/spec/lib/simp/ci/files/suite_skeleton_only/spec/acceptance/suites/default/nodesets +0 -1
  90. data/spec/lib/simp/ci/files/valid_job_nodeset_dir_link/spec/acceptance/suites/default/nodesets +0 -1
  91. data/spec/lib/simp/ci/files/valid_job_nodeset_link/spec/acceptance/suites/default/nodesets/default.yml +0 -1
  92. data/spec/lib/simp/files/build/testpackage.spec +0 -1
  93. data/spec/lib/simp/rake/pupmod/fixtures/simpmod/spec/acceptance/nodesets/default.yml +0 -1
  94. data/spec/lib/simp/rake/pupmod/fixtures/simpmod/spec/acceptance/suites/default/nodesets +0 -1
@@ -0,0 +1,8 @@
1
+ The following scripts with problematic shebangs have their execute bits set in
2
+ order to trigger the brp-mangle-shebangs script during an RPM build in EL8:
3
+
4
+ * spec/classes/init_spec.rb: #!/usr/bin/env rspec => #!/usr/bin/rspec
5
+ * spec/files/mock_something.rb: #!/usr/bin/env ruby => #!/usr/bin/ruby
6
+ * utils/convert_v1_to_v2.rb: #!/usr/bin/env ruby => #!/usr/bin/ruby
7
+
8
+ *** Do not change their execute bits in Git! ***
@@ -0,0 +1 @@
1
+ #!/usr/bin/env rspec
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ #This is a mock executable for something
3
+ puts 'hello world'
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env ruby
2
+ # convert from version 1 to version 2
3
+ puts "Running #{File.basename(__FILE__)}"
@@ -29,11 +29,24 @@ CONFIG:
29
29
  password: root
30
30
  auth_methods:
31
31
  - password
32
+ docker_preserve_image: true
33
+ # This is necessary for pretty much all containers
32
34
  docker_cap_add:
33
35
  - AUDIT_WRITE
34
- docker_preserve_image: true
35
36
  mount_folders:
36
37
  host_files:
37
38
  host_path: ./
38
39
  container_path: /host_files
39
- opts: 'z'
40
+ # All items below this point are required for systemd
41
+ cgroup:
42
+ host_path: /sys/fs/cgroup
43
+ container_path: /sys/fs/cgroup
44
+ opts: 'ro'
45
+ dockeropts:
46
+ HostConfig:
47
+ Tmpfs:
48
+ '/run': 'rw,noexec,nosuid,nodev,size=65536k'
49
+ '/run/lock': 'rw,noexec,nosuid,nodev,size=65536k'
50
+ '/tmp': 'rw,exec,nosuid,nodev,size=65536k'
51
+ '/sys/fs/cgroup/systemd': 'rw,size=65536k'
52
+ '/var/log/journal': 'rw,noexec,nodev,nosuid,size=65536k'
@@ -57,16 +57,40 @@ module Simp::BeakerHelpers::SimpRakeHelpers::BuildProjectHelpers
57
57
  # Scans a host path for the 'SIMP Development' GPG key and returns its Key ID
58
58
  #
59
59
  # @param [Host, String, Symbol] host Beaker host
60
- # @param [Hash{Symbol=>String}] opts Beaker options Hash for `#on` ({})
61
- # @param [String] proj_dir Absolute path to the parent project directory
60
+ # @param [String] key_dir Absolute path to GPG key dir
62
61
  # @param [Hash{Symbol=>String}] opts Beaker options Hash for `#on` ({})
63
62
  # @return [String] GPG dev signing Key ID
64
63
  #
65
- def dev_signing_key_id(host, proj_dir, opts = {})
66
- key_dir = distribution_dir(host, proj_dir, opts) + '/build_keys/dev'
67
- res = on(host, %(#{run_cmd} "gpg --list-keys --fingerprint --homedir='#{key_dir}' 'SIMP Development'"))
68
- lines = res.stdout.lines.select { |x| x =~ %r{Key fingerprint =} }
69
- raise "No 'SIMP Development' GPG keys found under ''" if lines.empty?
70
- lines.first.strip.split(%r{\s+})[-4..-1].join.downcase
64
+ def dev_signing_key_id(host, key_dir, opts = {})
65
+ # NOTE: This search uses a substring match on 'SIMP Development'.
66
+ res = on(host, %(#{run_cmd} "gpg --with-colons --fingerprint --homedir='#{key_dir}' 'SIMP Development'"), opts)
67
+ pub_lines = res.stdout.lines.select { |x| x.start_with?('pub') }
68
+ raise "No 'SIMP Development' GPG keys found in '#{key_dir}'" if pub_lines.empty?
69
+ pub_lines.first.split(':')[4].downcase
70
+ end
71
+
72
+ # Returns true when a gpg-agent daemon using the specified GPG home directory
73
+ # (aka key directory) is running.
74
+ #
75
+ # @param [Host, String, Symbol] host Beaker host
76
+ # @param [String] gpg_homedir Absolute path to GPG home dir
77
+ def gpg_agent_running?(host, gpg_homedir)
78
+
79
+ # This check is being used in tests to verify no gpg-agent for gpg_homedir
80
+ # is running. On slow VMs, the gpg-agent can take some time to shutdown.
81
+ # So wait up to 20 seconds for gpg-agent to shutdown before finalizing
82
+ # gpg-agent status to be reported.
83
+
84
+ retries = 20
85
+ agent_exists = true
86
+ while (agent_exists || (retries > 0))
87
+ result = on(host, "pgrep -c -f 'gpg-agent.*homedir.*#{gpg_homedir}'", :accept_all_exit_codes => true)
88
+ agent_exists = (result.stdout.strip != '0')
89
+ break unless agent_exists
90
+ sleep 1
91
+ retries -= 1
92
+ end
93
+
94
+ agent_exists
71
95
  end
72
96
  end
@@ -0,0 +1,29 @@
1
+ require 'simp/command_utils'
2
+ require 'spec_helper'
3
+
4
+ describe Simp::CommandUtils do
5
+ RSpec.configure do |c|
6
+ c.include Simp::CommandUtils
7
+ end
8
+
9
+ describe '.which' do
10
+ it 'should return location of command that exists' do
11
+ expect(Facter::Core::Execution).to receive(:which).with('ls').and_return('/usr/bin/ls')
12
+ expect( which('ls') ).to eq('/usr/bin/ls')
13
+ end
14
+
15
+ it 'should return nil if command does not exist by default' do
16
+ expect( which('/does/not/exist/command') ).to be nil
17
+ end
18
+
19
+ it 'should fail if command does not exist if fail=true' do
20
+ expect{ which('/does/not/exist/command', true) }.to raise_error(
21
+ RuntimeError, /Warning: Command \/does\/not\/exist\/command not found/)
22
+ end
23
+
24
+ it 'should cache commands' do
25
+ allow(Facter::Core::Execution).to receive(:which).with('ls').and_return('/path1/ls', '/path2/ls')
26
+ expect( which('ls') ).to eq('/path1/ls')
27
+ end
28
+ end
29
+ end
@@ -1,14 +1,24 @@
1
1
  require 'simp/local_gpg_signing_key'
2
2
  require 'spec_helper'
3
3
  require 'fileutils'
4
+ require 'timeout'
4
5
  require 'tmpdir'
5
6
 
7
+
8
+ def get_key_id(keydir, key_email)
9
+ key_id = nil
10
+ key_info = `gpg --with-colons --homedir=#{keydir} --list-keys '<#{key_email}>' 2>&1 | grep ^pub:`
11
+ unless key_info.strip.empty?
12
+ key_id = key_info.split(':')[4]
13
+ end
14
+ end
15
+
6
16
  describe Simp::LocalGpgSigningKey do
7
17
  include FileUtils
8
18
 
9
19
  before :all do
10
20
  TMP_DIR = Dir.mktmpdir('spec_test__simp_local_gpg_signing_key')
11
- TMP_DEV_DIR = File.join(TMP_DIR, 'dev')
21
+ TMP_DEV_KEYDIR = File.join(TMP_DIR, 'dev')
12
22
  OPTS = {verbose: ENV['VERBOSE'].to_s =~ /^(yes|true)$/ }
13
23
 
14
24
  mkdir_p TMP_DIR
@@ -24,9 +34,17 @@ describe Simp::LocalGpgSigningKey do
24
34
  ENV['GPG_AGENT_INFO'] = ORIGINAL_GPG_AGENT_INFO
25
35
  end
26
36
 
37
+ let(:gpg_keydir) { TMP_DEV_KEYDIR }
38
+ let(:gpg_email_name) { 'gatekeeper@simp.development.key' }
39
+ let(:opts) { OPTS }
40
+
27
41
  shared_examples_for 'it just generated a local gpg signing key' do
28
- it 'creates a local gpg-agent' do
29
- expect(agent_info.reject{|x| x.nil?}.keys).to include(:info, :socket, :pid)
42
+ it 'has the key in the keyring' do
43
+ expect(get_key_id(gpg_keydir, gpg_email_name)).to_not be_nil
44
+ end
45
+
46
+ it 'had created a local gpg-agent' do
47
+ expect(agent_info.reject{|x| x.nil?}.keys).to include(:socket, :pid)
30
48
  end
31
49
 
32
50
  it 'had a gpg-agent socket' do
@@ -35,62 +53,141 @@ describe Simp::LocalGpgSigningKey do
35
53
  end
36
54
 
37
55
  it 'has killed the local gpg-agent' do
56
+ begin
57
+ # it may take some time for the local gpg-agent to die
58
+ Timeout::timeout(30) do
59
+ done = !File.exist?(agent_info[:socket])
60
+ until(done)
61
+ sleep(2)
62
+ done = !File.exist?(agent_info[:socket])
63
+ end
64
+ end
65
+ rescue Timeout::Error
66
+ puts "agent_info = #{agent_info}"
67
+ puts "gpg-agent processes running:\n#{`pgrep -f gpg-agent`}"
68
+ end
69
+
38
70
  expect(File.exist?(agent_info[:socket])).to be false
39
71
  end
40
72
  end
41
73
 
42
-
43
74
  shared_examples_for 'a valid gpg signing key environment' do
44
- it 'has a local GPG signing key' do
45
- Dir.chdir(TMP_DEV_DIR) { expect(Dir['*']).to include('RPM-GPG-KEY-SIMP-Dev') }
75
+ it 'has an exported local GPG signing key' do
76
+ Dir.chdir(gpg_keydir) { expect(Dir['*']).to include('RPM-GPG-KEY-SIMP-Dev') }
46
77
  end
47
78
 
48
- it 'has a populated a gpg-agent directory' do
49
- Dir.chdir(TMP_DEV_DIR) do |_dir|
50
- expect(Dir['*'].sort).to include(
51
- 'gengpgkey',
52
- 'pubring.gpg',
53
- )
54
- end
79
+ it 'has a keygen params file with info required for package signing' do
80
+ params_file = File.join(gpg_keydir, 'gengpgkey')
81
+ expect(File.exist?(params_file)).to be true
82
+
83
+ content = File.read(params_file)
84
+ expect(content).to match(/^Passphrase: .*$/)
85
+ expect(content).to match(/^Name-Email: #{gpg_email_name}$/)
55
86
  end
56
87
  end
57
88
 
58
89
  shared_examples_for 'it encountered an unexpired local gpg signing key' do
59
90
  it 'reuses an unexpired local gpg signing key' do
60
- expect{described_class.new(TMP_DEV_DIR,OPTS).ensure_key}.to output(
91
+ expect{described_class.new(gpg_keydir,opts).ensure_key}.to output(
61
92
  /^GPG key \(gatekeeper@simp\.development\.key\) will expire in 14 days\./
62
93
  ).to_stdout
94
+
95
+ expect(get_key_id(gpg_keydir, gpg_email_name)).to eq original_key_id
63
96
  end
64
97
 
65
98
  it 'reuses an unexpired local gpg signing key' do
66
- expect{described_class.new(TMP_DEV_DIR,OPTS).ensure_key}.to output(
99
+ expect{described_class.new(gpg_keydir,opts).ensure_key}.to output(
67
100
  /^GPG key \(gatekeeper@simp\.development\.key\) will expire in 14 days\./
68
101
  ).to_stdout
102
+
103
+ expect(get_key_id(gpg_keydir, gpg_email_name)).to eq original_key_id
69
104
  end
70
105
  end
71
106
 
72
107
  context '#ensure_key' do
73
108
  before :all do
74
- rm_rf TMP_DEV_DIR
109
+ rm_rf TMP_DEV_KEYDIR
75
110
  ENV['GPG_AGENT_INFO'] = nil
76
111
  end
77
112
 
113
+
78
114
  context 'when run from scratch' do
79
115
  before :all do
80
- FIRST_RUN_AGENT_INFO = described_class.new(TMP_DEV_DIR,OPTS).ensure_key
116
+ FIRST_RUN_AGENT_INFO = described_class.new(TMP_DEV_KEYDIR,OPTS).ensure_key
81
117
  end
118
+
82
119
  let(:agent_info){ FIRST_RUN_AGENT_INFO }
120
+
83
121
  it_behaves_like 'it just generated a local gpg signing key'
84
122
  it_behaves_like 'a valid gpg signing key environment'
85
123
  end
86
124
 
87
125
  context 'when run again' do
88
126
  before :all do
89
- SECOND_RUN_AGENT_INFO = described_class.new(TMP_DEV_DIR,OPTS).ensure_key
127
+ SECOND_RUN_AGENT_INFO = described_class.new(TMP_DEV_KEYDIR,OPTS).ensure_key
90
128
  end
129
+
91
130
  let(:agent_info){ SECOND_RUN_AGENT_INFO }
131
+ let(:original_key_id) { get_key_id(gpg_keydir, gpg_email_name) }
132
+
92
133
  it_behaves_like 'it encountered an unexpired local gpg signing key'
93
134
  it_behaves_like 'a valid gpg signing key environment'
94
135
  end
95
136
  end
137
+
138
+ context '#gpg_agent_info' do
139
+ before :all do
140
+ rm_rf TMP_DEV_KEYDIR
141
+ end
142
+
143
+ # other use cases already tested in ensure_key tests
144
+ it 'returns nil when no gpg agent env file exists' do
145
+ expect(described_class.new(gpg_keydir,opts).gpg_agent_info).to be_nil
146
+ end
147
+ end
148
+
149
+ context '#dev_key_days_left' do
150
+ before :all do
151
+ rm_rf TMP_DEV_KEYDIR
152
+ end
153
+
154
+ let(:gpg_cmd) { "gpg --with-colons --homedir=#{gpg_keydir} --list-keys '<#{gpg_email_name}>' 2>&1" }
155
+
156
+ it 'returns 0 when key is not found' do
157
+ expect(described_class.new(gpg_keydir,opts).dev_key_days_left).to eq 0
158
+ end
159
+
160
+ it 'returns 0 when key is expired' do
161
+ generator = described_class.new(gpg_keydir,opts)
162
+ output = <<~EOM
163
+ tru::1:1521838828:0:3:1:5
164
+ pub:e:4096:1:722B97A808E7DAEA:1521838554:1523048154::-:::sc::::::23::0:
165
+ fpr:::::::::5DD3E8D45C99780DCA7D0B83722B97A808E7DAEA:
166
+ uid:e::::1521838554::773C55CA511CCE31244D86D4AB70F6499024695F::SIMP Development (Development key 1521838554) <gatekeeper@simp.development.key>::::::::::0:
167
+ EOM
168
+ expect(generator).to receive(:`).with(gpg_cmd).and_return(output)
169
+
170
+ expect(generator.dev_key_days_left).to eq 0
171
+ end
172
+
173
+ it 'returns # days left when unexpired key is found with ISO 8601 date' do
174
+ generator = described_class.new(gpg_keydir,opts)
175
+
176
+ require 'date'
177
+ creation_date = DateTime.now - 5
178
+ expiration_date = creation_date + 14
179
+ creation_str = creation_date.iso8601.gsub(/:|-/,'')
180
+ expiration_str = expiration_date.iso8601.gsub(/:|-/,'')
181
+
182
+ output = <<~EOM
183
+ tru::1:1521838828:0:3:1:5
184
+ pub:u:4096:1:722B97A808E7DAEA:#{creation_str}:#{expiration_str}::-:::sc::::::23::0:
185
+ fpr:::::::::5DD3E8D45C99780DCA7D0B83722B97A808E7DAEA:
186
+ uid:e::::1521838554::773C55CA511CCE31244D86D4AB70F6499024695F::SIMP Development (Development key 1521838554) <gatekeeper@simp.development.key>::::::::::0:
187
+ EOM
188
+ expect(generator).to receive(:`).with(gpg_cmd).and_return(output)
189
+
190
+ expect(generator.dev_key_days_left).to eq 9
191
+ end
192
+ end
96
193
  end
@@ -21,7 +21,7 @@
21
21
 
22
22
  Start with a one- or two-sentence summary of what the module does and/or what
23
23
  problem it solves. This is your 30-second elevator pitch for your module.
24
- Consider including OS and Puppet version compatability, and any other
24
+ Consider including OS and Puppet version compatibility, and any other
25
25
  information users will need to quickly assess the module's viability within
26
26
  their environment.
27
27
 
@@ -33,7 +33,7 @@ management, etc.), this is the time to mention it.
33
33
  ### This is a SIMP module
34
34
 
35
35
  This module is a component of the [System Integrity Management
36
- Platform](https://github.com/NationalSecurityAgency/SIMP), a
36
+ Platform](https://simp-project.com), a
37
37
  compliance-management framework built on Puppet.
38
38
 
39
39
  If you find any issues, they may be submitted to our [bug
@@ -0,0 +1,98 @@
1
+ require 'simp/rpm_signer'
2
+ require 'spec_helper'
3
+ require 'fileutils'
4
+ require 'tmpdir'
5
+
6
+
7
+ describe Simp::RpmSigner do
8
+
9
+ before :all do
10
+ @tmp_dir = Dir.mktmpdir('spec_test__rpm_signer')
11
+ @gpg_keydir = File.join(@tmp_dir, 'dev')
12
+ end
13
+
14
+ after :all do
15
+ FileUtils.remove_entry_secure(@tmp_dir)
16
+ end
17
+
18
+ let(:verbose) { ENV['VERBOSE'].to_s =~ /^(yes|true)$/ }
19
+ let(:gpg_email_name) { 'gatekeeper@simp.development.key' }
20
+ let(:passphrase) { 'dev_passphrase' }
21
+ let(:key_id) { '722B97A808E7DAEA' }
22
+ let(:key_size) { 4096 }
23
+ let(:key_info) { {
24
+ :dir => @gpg_keydir,
25
+ :name => gpg_email_name,
26
+ :key_id => key_id,
27
+ :key_size => key_size,
28
+ :password => passphrase
29
+ } }
30
+
31
+ let(:gpg_cmd) { "gpg --with-colons --homedir=#{@gpg_keydir} --list-keys '<#{gpg_email_name}>' 2>&1" }
32
+ let(:key_list_output) { <<~EOM
33
+ tru::1:1521838828:0:3:1:5
34
+ pub:e:4096:1:722B97A808E7DAEA:1521838554:1523048154::-:::sc::::::23::0:
35
+ fpr:::::::::5DD3E8D45C99780DCA7D0B83722B97A808E7DAEA:
36
+ uid:e::::1521838554::773C55CA511CCE31244D86D4AB70F6499024695F::SIMP Development (Development key 1521838554) <gatekeeper@simp.development.key>::::::::::0:
37
+ EOM
38
+ }
39
+
40
+ # The bulk of load_key is tested in the acceptance test. These tests are
41
+ # a few edge cases.
42
+ context '.load_key' do
43
+ context 'key info missing from files' do
44
+ before :each do
45
+ allow(Simp::RpmSigner).to receive(:which).with('gpg').and_return('/usr/bin/gpg')
46
+ FileUtils.mkdir_p(@gpg_keydir)
47
+ end
48
+
49
+ after :each do
50
+ FileUtils.rm_rf(@gpg_keydir)
51
+ Simp::RpmSigner.clear_gpg_keys_cache
52
+ end
53
+
54
+ it 'should prompt user for key email and passphrase when not in files' do
55
+ expect($stdin).to receive(:gets).and_return(gpg_email_name, passphrase)
56
+ expect(Simp::RpmSigner).to receive(:`).with(gpg_cmd).and_return(key_list_output)
57
+
58
+ expect(Simp::RpmSigner.load_key(@gpg_keydir, verbose)).to eq (key_info)
59
+
60
+ # verifies returning info from the cache, otherwise user would be prompted again
61
+ # and expectation on $stdin would fail
62
+ expect(Simp::RpmSigner.load_key(@gpg_keydir, verbose)).to eq (key_info)
63
+ end
64
+
65
+ it "should read the passphrase from the 'password' file" do
66
+ File.open(File.join(@gpg_keydir, 'password'),'w') { |file| file.puts passphrase }
67
+ expect($stdin).to receive(:gets).and_return(gpg_email_name)
68
+ expect(Simp::RpmSigner).to receive(:`).with(gpg_cmd).and_return(key_list_output)
69
+
70
+ expect(Simp::RpmSigner.load_key(@gpg_keydir, verbose)).to eq (key_info)
71
+ end
72
+ end
73
+
74
+ context 'errors' do
75
+ it 'should fail when gpg does not exist' do
76
+ expect(Simp::RpmSigner).to receive(:which).with('gpg').and_return(nil)
77
+ expect { Simp::RpmSigner.load_key(@gpg_keydir, verbose) }.to raise_error(
78
+ /Cannot sign RPMs without 'gpg'/)
79
+ end
80
+
81
+ it 'should fail when keydir does not exist' do
82
+ expect(Simp::RpmSigner).to receive(:which).with('gpg').and_return('/usr/bin/gpg')
83
+ expect { Simp::RpmSigner.load_key(@gpg_keydir, verbose) }.to raise_error(
84
+ /Could not find GPG keydir/)
85
+ end
86
+
87
+ it 'should fail when key info cannot be retrieved via gpg' do
88
+ FileUtils.mkdir_p(@gpg_keydir)
89
+ expect(Simp::RpmSigner).to receive(:which).with('gpg').and_return('/usr/bin/gpg')
90
+ expect($stdin).to receive(:gets).and_return(gpg_email_name, passphrase)
91
+ expect(Simp::RpmSigner).to receive(:`).with(gpg_cmd).and_return('')
92
+
93
+ expect { Simp::RpmSigner.load_key(@gpg_keydir, verbose) }.to raise_error(
94
+ /Error getting GPG key ID or Key size metadata/)
95
+ end
96
+ end
97
+ end
98
+ end