simp-rake-helpers 5.6.1 → 5.6.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +1 -0
  3. data/CHANGELOG.md +4 -0
  4. data/Gemfile +1 -1
  5. data/lib/simp/local_gpg_signing_key.rb +273 -0
  6. data/lib/simp/rake/build/pkg.rb +47 -142
  7. data/lib/simp/rake/helpers/version.rb +1 -1
  8. data/spec/acceptance/50_local_gpg_signing_key_spec.rb +34 -0
  9. data/spec/acceptance/55_build_pkg_signing_spec.rb +140 -0
  10. data/spec/acceptance/files/build/pkg/gpg-keydir.expired.2018-04-06/RPM-GPG-KEY-SIMP-Dev +30 -0
  11. data/spec/acceptance/files/build/pkg/gpg-keydir.expired.2018-04-06/gengpgkey +17 -0
  12. data/spec/acceptance/files/build/pkg/gpg-keydir.expired.2018-04-06/pubring.gpg +0 -0
  13. data/spec/acceptance/files/build/pkg/gpg-keydir.expired.2018-04-06/random_seed +0 -0
  14. data/spec/acceptance/files/build/pkg/gpg-keydir.expired.2018-04-06/run_gpg_agent +3 -0
  15. data/spec/acceptance/files/build/pkg/gpg-keydir.expired.2018-04-06/secring.gpg +0 -0
  16. data/spec/acceptance/files/build/pkg/gpg-keydir.expired.2018-04-06/trustdb.gpg +0 -0
  17. data/spec/acceptance/files/build/project_skeleton/Puppetfile.tracking +1 -0
  18. data/spec/acceptance/files/build/project_skeleton/README.md +17 -0
  19. data/spec/acceptance/files/build/project_skeleton/Rakefile +8 -0
  20. data/spec/acceptance/files/build/project_skeleton/src/assets/simp/build/simp.spec +32 -0
  21. data/spec/acceptance/nodesets/default.yml +1 -0
  22. data/spec/acceptance/support/build_project_helpers.rb +72 -0
  23. data/spec/acceptance/support/build_user_helpers.rb +20 -0
  24. data/spec/acceptance/support/pkg_rpm_helpers.rb +3 -11
  25. data/spec/acceptance/support/simp_rake_helpers.rb +11 -0
  26. data/spec/lib/simp/local_gpg_signing_key_spec.rb.beaker-only +96 -0
  27. data/spec/spec_helper_acceptance.rb +1 -11
  28. metadata +24 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 6599aea873a06ae3cfaf152334a7effee7fed04f32fa5161b424475a2e350de8
4
- data.tar.gz: 7034e551215bf0636963264f2c483179368d3ca653498929b0e1b563253d6324
2
+ SHA1:
3
+ metadata.gz: 81eff52b592008f011ce1cbf7906a2de2b5a0b1a
4
+ data.tar.gz: 8b23f1eee1426b3966dcfdd5497c12842393f54c
5
5
  SHA512:
6
- metadata.gz: f336088887b860878ced18d3391cf7b682cf0cdf460827bfb3525330fc41437a76dae20ed73e1a89875b8a63cc354288746e96cffff83be400d015e898d0972b
7
- data.tar.gz: 709eb08291c9944c3d3929f872bff72dc36fff4603503945e0d33f2ba06ad4569e65ac933e4d7a1e4691a671372e660f84b26222f4ce049613b7c1ca561454a6
6
+ metadata.gz: b95308bf18a70abc0ed3e6c9c1141a2d93657ead6538b0d3672b23653ca1b80af049a9639d32022137d1a51ffa06f7de4e3c2ffe5e168a45442ebf7b5748ac4c
7
+ data.tar.gz: c9d08045244a15fdd38c5ee09d1600a0d17a3dea637273fba9b3a8dcf9a1e381cfc2165da69e45f635c16bcf016596664c1e2927cd094fc725d439e45bc27277
data/.travis.yml CHANGED
@@ -35,6 +35,7 @@ jobs:
35
35
 
36
36
  - stage: deploy
37
37
  rvm: 2.4.4
38
+ if: 'fork = false AND tag = true'
38
39
  script:
39
40
  - true
40
41
  before_deploy:
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ ### 5.6.2 / 2018-10-02
2
+ * Refactor 'dev' GPG signing key logic into `Simp::LocalGpgSigningKey`
3
+ * Add acceptance tests for GPG logic and `rake pkg:signrpms`
4
+
1
5
  ### 5.6.1 / 2018-10-01
2
6
  * Ensure that modules do not contain symlinks per the standard Puppet guidance.
3
7
  * Do not try to only use the system cache for yum operations since this
data/Gemfile CHANGED
@@ -2,7 +2,7 @@
2
2
  #
3
3
  # SIMP_GEM_SERVERS | a space/comma delimited list of rubygem servers
4
4
  # PUPPET_VERSION | specifies the version of the puppet gem to load
5
- puppetversion = ENV.key?('PUPPET_VERSION') ? "#{ENV['PUPPET_VERSION']}" : '~> 4'
5
+ puppetversion = ENV.key?('PUPPET_VERSION') ? "#{ENV['PUPPET_VERSION']}" : '~> 5'
6
6
  gem_sources = ENV.key?('SIMP_GEM_SERVERS') ? ENV['SIMP_GEM_SERVERS'].split(/[, ]+/) : ['https://rubygems.org']
7
7
 
8
8
  gem_sources.each { |gem_source| source gem_source }
@@ -0,0 +1,273 @@
1
+ require 'securerandom'
2
+ require 'rake'
3
+
4
+ module Simp
5
+ # Ensure that a valid GPG signing key exists in a local directory
6
+ #
7
+ # This is typically used to sign packages during development.
8
+ #
9
+ # * The signing key will be generated if it is missing or expired.
10
+ # * Generated keys are short-lived (default: 14 days).
11
+ # * The signing key and its related assets are completely isolated from
12
+ # the user's own GPG keys, keyrings, and agent.
13
+ # - All files are kept under a local directory tree.
14
+ # - New keys are generated using a temporary GPG agent with its own
15
+ # settings and socket.
16
+ #
17
+ # The local signing key's directory is structured like this:
18
+ #
19
+ # ```
20
+ # #{key_name}/ # key directory
21
+ # +-- RPM-GPG-KEY-SIMP-#{key_name} # key file
22
+ # +-- gengpgkey # --gen-key params file **
23
+ # +-- pubring.gpg
24
+ # +-- secring.gpg
25
+ # +-- trustring.gpg
26
+ # ```
27
+ #
28
+ # `**` = `SIMP::RPM.sign_keys` will use the values in the `gengpgkey` file
29
+ # for the GPG signing key's email and passphrase
30
+ #
31
+ # If a new key is required, a project-only `gpg-agent` daemon is momentarily
32
+ # created to generate it, and destroyed after this is done. The daemon does
33
+ # not interact with any other `gpg-agent` daemons on the system--it is
34
+ # launched on a random socket and keeps all its files under the
35
+ # #{key_name/} directory.
36
+ #
37
+ # When instantiated, the daemon writes an "env-file" to the #{key_name}
38
+ # directory. This file specifies the location of the daemon's socket and
39
+ # pid.
40
+ #
41
+ # A typical env-file looks like:
42
+ #
43
+ # ```sh
44
+ # GPG_AGENT_INFO=/tmp/gpg-4yhfOB/S.gpg-agent:15495:1
45
+ # ```
46
+ #
47
+ # A brand-new gpg-agent daemon will output similar information, with an
48
+ # additional export:
49
+ #
50
+ # ```sh
51
+ # GPG_AGENT_INFO=/tmp/gpg-4yhfOB/S.gpg-agent:15495:1; export GPG_AGENT_INFO;\n"
52
+ # ```
53
+ class LocalGpgSigningKey
54
+ include FileUtils
55
+
56
+ # `SIMP::RPM.sign_keys` will look for a 'gengpgkey' file to
57
+ # non-interactively sign packages.
58
+ #
59
+ # @see SIMP::RPM.sign_keys
60
+ GPG_GENKEY_PARAMS_FILENAME = 'gengpgkey'.freeze
61
+
62
+ # @param dir [String] path to gpg-agent / key directory
63
+ # @param opts [Hash] optional configurations
64
+ #
65
+ # @option opts [String] :label Defaults to the basename of `dir` (dev)
66
+ # @option opts [String] :email (gatekeeper@simp.development.key)
67
+ # @option opts [String] :file Default based on label (RPM-GPG-KEY-SIMP-Dev)
68
+ # @option opts [Boolean] :verbose (false)
69
+ #
70
+ def initialize(dir = 'dev', opts = {})
71
+ @dir = File.expand_path(dir)
72
+ @label = opts[:label] || File.basename(dir.downcase)
73
+ @key_email = opts[:email] || 'gatekeeper@simp.development.key'
74
+ @key_file = opts[:file] || "RPM-GPG-KEY-SIMP-#{@label.capitalize}"
75
+ @verbose = opts[:verbose] || false
76
+
77
+ @gpg_agent_env_file = 'gpg-agent-info.env'
78
+ @gpg_agent_script = 'run_gpg_agent'
79
+ end
80
+
81
+ # Returns a gpg-agent's env string, if it can be detected from the
82
+ # gpg-agent-info file
83
+ #
84
+ # @return [String] if the env string was detected
85
+ # @return [nil] if the env string was not detected
86
+ #
87
+ def gpg_agent_info
88
+ if File.exist?(@gpg_agent_env_file)
89
+ puts "Reading gpg_agent_info from `#{@gpg_agent_env_file}`..." if @verbose
90
+ info = parse_gpg_agent_info_env(File.read(@gpg_agent_env_file))
91
+ else
92
+ puts "Couldn't find a valid source to read gpg_agent_info..." if @verbose
93
+ info = nil
94
+ end
95
+ info
96
+ end
97
+
98
+ # Return the number of days left before the GPG signing key expires
99
+ def dev_key_days_left
100
+ ensure_gpg_directory
101
+ days_left = 0
102
+ current_key = %x(GPG_AGENT_INFO='' gpg --homedir=#{@dir} --list-keys #{@key_email} 2>/dev/null)
103
+ unless current_key.empty?
104
+ lasts_until = current_key.lines.first.strip.split("\s").last.delete(']')
105
+ days_left = (Date.parse(lasts_until) - Date.today).to_i
106
+ end
107
+ days_left
108
+ end
109
+
110
+ # Remove all files under the key directory
111
+ def clean_gpg_agent_directory
112
+ puts " Removing all files under '#{@dir}'" if @verbose
113
+ Dir.glob(File.join(@dir, '*')).each do |todel|
114
+ rm_rf(todel, :verbose => @verbose)
115
+ end
116
+ end
117
+
118
+ # Make sure the local key's directory exists and has correct permissions
119
+ def ensure_gpg_directory
120
+ mkdir_p(@dir, :verbose => @verbose)
121
+ chmod(0o700, @dir, :verbose => @verbose)
122
+ end
123
+
124
+ # Ensure that the gpg-agent is running with a dev key
125
+ def ensure_key
126
+ ensure_gpg_directory
127
+
128
+ if (days_left = dev_key_days_left) > 0
129
+ puts "GPG key (#{@key_email}) will expire in #{days_left} days."
130
+ return
131
+ end
132
+
133
+ Dir.chdir @dir do |_dir|
134
+ puts 'Creating a new dev GPG agent...'
135
+
136
+ clean_gpg_agent_directory
137
+ write_genkey_parameter_file
138
+ write_gpg_agent_startup_script
139
+
140
+ begin
141
+ # Start the GPG agent.
142
+ gpg_agent_output = %x(./#{@gpg_agent_script}).strip
143
+
144
+ # Provide a local socket (needed by the `gpg` command when
145
+ local_socket = File.join(Dir.pwd, 'S.gpg-agent')
146
+
147
+ # This condition was handled differently in previous logic.
148
+ #
149
+ # a.) As the surrounding logic works now, it will _always_ be a new
150
+ # agent by this point, because the directory is cleaned out
151
+ # b.) The agent's information will be read from the env-file it
152
+ # writes at startup
153
+ # c.) The old command `gpg-agent --homedir=#{Dir.pwd} /get serverpid`
154
+ # did not work on EL6 or EL7.
155
+ #
156
+ warn(empty_gpg_agent_message) if gpg_agent_output.empty?
157
+
158
+ agent_info = gpg_agent_info
159
+
160
+ # The socket is useful to get back info on the command line.
161
+ unless File.exist?(File.join(Dir.pwd, File.basename(agent_info[:socket])))
162
+ ln_s(agent_info[:socket], local_socket, :verbose => @verbose)
163
+ end
164
+ generate_key(agent_info[:info])
165
+ ensure
166
+ kill_agent(agent_info[:pid])
167
+ end
168
+ agent_info
169
+ end
170
+ end
171
+
172
+ # Provides an informative warning message to display in the unlikely event
173
+ # that a new `gpg-agent` daemon returns empty output when it is started.
174
+ #
175
+ # @return [String] Warning message
176
+ def empty_gpg_agent_message
177
+ <<-WARNING.gsub(/^\s{8}/,'')
178
+ WARNING: Tried to start an project-only gpg-agent daemon on a random socket by
179
+ running the script:
180
+
181
+ #{@gpg_agent_script}
182
+
183
+ However, the script returned no output, which usually means that a GPG
184
+ Agent was already running on that socket. This is extraordinarily
185
+ unlikely, and is not expected to happen.
186
+
187
+ If the '#{@label}' GPG signing key fails to generate after this
188
+ message appears, please report this issue to the SIMP project,
189
+ including the OS you were were running from and its versions of the
190
+ `gpg-agent` and `gpg`/`gpg2` commands.
191
+ WARNING
192
+ end
193
+
194
+ # Kills the GPG agent by pid, if it is running
195
+ #
196
+ # @param pid [String] The GPG Agent PID to kill
197
+ def kill_agent(pid)
198
+ rm('S.gpg-agent') if File.symlink?('S.gpg-agent')
199
+ if pid
200
+ Process.kill(0, pid)
201
+ Process.kill(15, pid)
202
+ end
203
+ rescue Errno::ESRCH
204
+ # Not Running, Nothing to do!
205
+ end
206
+
207
+ # Generate a RPM GPG signing key for local development
208
+ #
209
+ # @param gpg_agent_info_str [String] value to set the GPG_AGENT_INFO
210
+ # environment variable to use in order to use the correct `gpg-agent`.
211
+ def generate_key(gpg_agent_info_str)
212
+ puts "Generating new GPG key#{@verbose ? " under '#{@dir}'" : ''}..."
213
+ gpg_cmd = %(GPG_AGENT_INFO=#{gpg_agent_info_str} gpg --homedir="#{@dir}")
214
+ pipe = @verbose ? '| tee' : '>'
215
+ sh %(#{gpg_cmd} --batch --gen-key #{GPG_GENKEY_PARAMS_FILENAME})
216
+ sh %(#{gpg_cmd} --armor --export #{@key_email} #{pipe} "#{@key_file}")
217
+ end
218
+
219
+ # Return a data structure from a gpg-agent env-file formatted string.
220
+ #
221
+ # @param str [String] path to gpg-agent / key directory
222
+ def parse_gpg_agent_info_env(str)
223
+ info = %r{^(GPG_AGENT_INFO=)?(?<info>[^;]+)}.match(str)[:info]
224
+ matches = %r{^(?<socket>[^:]+):(?<pid>[^:]+)}.match(info)
225
+ { info: info.strip, socket: matches[:socket], pid: matches[:pid].to_i }
226
+ end
227
+
228
+ # Write the `gpg --genkey --batch` control parameter file
229
+ #
230
+ # @see "Unattended key generation" in /usr/share/doc/gnupg2-*/DETAILS for
231
+ # documentation on the command parameters format
232
+ def write_genkey_parameter_file
233
+ now = Time.now.to_i.to_s
234
+ expire_date = Date.today + 14
235
+ passphrase = SecureRandom.base64(500)
236
+ genkey_parameters = <<-GENKEY_PARAMETERS.gsub(%r{^ {8}}, '')
237
+ %echo Generating Development GPG Key
238
+ %echo
239
+ %echo This key will expire on #{expire_date}
240
+ %echo
241
+ Key-Type: RSA
242
+ Key-Length: 4096
243
+ Key-Usage: sign
244
+ Name-Real: SIMP Development
245
+ Name-Comment: Development key #{now}
246
+ Name-Email: #{@key_email}
247
+ Expire-Date: 2w
248
+ Passphrase: #{passphrase}
249
+ %pubring pubring.gpg
250
+ %secring secring.gpg
251
+ # The following creates the key, so we can print "Done!" afterwards
252
+ %commit
253
+ %echo New GPG Development Key Created
254
+ GENKEY_PARAMETERS
255
+ File.open(GPG_GENKEY_PARAMS_FILENAME, 'w') { |fh| fh.puts(genkey_parameters) }
256
+ end
257
+
258
+ # Write a local gpg-agent daemon script file
259
+ def write_gpg_agent_startup_script
260
+ gpg_agent_script = <<-AGENT_SCRIPT.gsub(%r{^ {20}}, '')
261
+ #!/bin/sh
262
+
263
+ gpg-agent --homedir=#{Dir.pwd} --daemon \
264
+ --no-use-standard-socket --sh --batch \
265
+ --write-env-file "#{@gpg_agent_env_file}" \
266
+ --pinentry-program /usr/bin/pinentry-curses < /dev/null &
267
+ AGENT_SCRIPT
268
+
269
+ File.open(@gpg_agent_script, 'w') { |fh| fh.puts(gpg_agent_script) }
270
+ chmod(0o755, @gpg_agent_script)
271
+ end
272
+ end
273
+ end
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/rake -T
2
2
 
3
3
  require 'simp/yum'
4
+ require 'simp/local_gpg_signing_key.rb'
4
5
  require 'simp/rake/pkg'
5
6
  require 'simp/rake/build/constants'
6
7
  require 'simp/rake/build/rpmdeps'
@@ -105,155 +106,63 @@ module Simp::Rake::Build
105
106
  end
106
107
  end
107
108
 
108
- =begin
109
109
  desc <<-EOM
110
- Prepare the GPG key space for a SIMP build.
110
+ Prepare a GPG signing key to sign build packages
111
+
112
+ * :key - the name of the directory under build/build_keys to
113
+ prepare (defaults to 'dev')
114
+
115
+ When :key is `dev`, a temporary signing key is created, if needed:
116
+
117
+ - A 14-day `dev` key will be created if none exists, including:
118
+ - The `<build_dir>/build_keys/dev/` dir
119
+ - gpgagent assets to create/update the key
120
+
121
+ When :key is *not* `dev`, the logic is much stricter:
111
122
 
112
- If passed anything but 'dev', will fail if the directory is not present in
113
- the 'build/build_keys' directory.
123
+ - You must already have create `<build_dir>/build_keys/<:key>/`
124
+ directoy, and placed a valid GPG signing key inside
125
+ - If the directory or key are missing, the task will fail.
114
126
 
115
127
  ENV vars:
116
128
  - Set `SIMP_PKG_verbose=yes` to report file operations as they happen.
117
129
  EOM
118
- =end
119
130
  task :key_prep,[:key] => [:prep] do |t,args|
120
- require 'securerandom'
121
- _verbose = ENV.fetch('SIMP_PKG_verbose','no') == 'yes'
122
-
123
131
  args.with_defaults(:key => 'dev')
132
+ key = args.key
133
+ build_keys_dir = File.join(@build_dir, 'build_keys')
134
+ key_dir = File.join(build_keys_dir,key)
135
+ dvd_dir = @dvd_src
124
136
 
125
- FileUtils.mkdir_p("#{@build_dir}/build_keys")
137
+ FileUtils.mkdir_p build_keys_dir
126
138
 
127
- Dir.chdir("#{@build_dir}/build_keys") do
128
- if (args.key != 'dev')
129
- fail("Could not find GPG keydir '#{args[:key]}' in '#{Dir.pwd}'") unless File.directory?(args[:key])
139
+ Dir.chdir(build_keys_dir) do
140
+ if key == 'dev'
141
+ Simp::LocalGpgSigningKey.new(key_dir,{verbose: @verbose}).ensure_key
130
142
  else
131
-
132
- mkdir('dev') unless File.directory?('dev')
133
- chmod(0700,'dev')
134
-
135
- Dir.chdir('dev') do
136
- dev_email = 'gatekeeper@simp.development.key'
137
- current_key = `gpg --homedir=#{Dir.pwd} --list-keys #{dev_email} 2>/dev/null`
138
- days_left = 0
139
- unless current_key.empty?
140
- lasts_until = current_key.lines.first.strip.split("\s").last.delete(']')
141
- days_left = (Date.parse(lasts_until) - DateTime.now).to_i
142
- end
143
-
144
- if days_left > 0
145
- puts "GPG key will expire in #{days_left} days."
146
- else
147
- puts "Generating new GPG key"
148
-
149
- Dir.glob('*').each do |todel|
150
- rm_rf(todel, :verbose => _verbose)
151
- end
152
-
153
- expire_date = (DateTime.now + 14)
154
- now = Time.now.to_i.to_s
155
- dev_email = 'gatekeeper@simp.development.key'
156
- passphrase = SecureRandom.base64(500)
157
-
158
- gpg_infile = <<-EOM
159
- %echo Generating Development GPG Key
160
- %echo
161
- %echo This key will expire on #{expire_date}
162
- %echo
163
- Key-Type: RSA
164
- Key-Length: 4096
165
- Key-Usage: sign
166
- Name-Real: SIMP Development
167
- Name-Comment: Development key #{now}
168
- Name-Email: #{dev_email}
169
- Expire-Date: 2w
170
- Passphrase: #{passphrase}
171
- %pubring pubring.gpg
172
- %secring secring.gpg
173
- # The following creates the key, so we can print "Done!" afterwards
174
- %commit
175
- %echo New GPG Development Key Created
176
- EOM
177
-
178
- gpg_agent_script = <<-EOM
179
- #!/bin/sh
180
-
181
- gpg-agent --homedir=#{Dir.pwd} --batch --daemon --pinentry-program /usr/bin/pinentry-curses < /dev/null &
182
- EOM
183
-
184
- File.open('gengpgkey','w'){ |fh| fh.puts(gpg_infile) }
185
- File.open('run_gpg_agent','w'){ |fh| fh.puts(gpg_agent_script) }
186
- chmod(0755,'run_gpg_agent')
187
-
188
- gpg_agent_pid = nil
189
- gpg_agent_socket = nil
190
-
191
- if File.exist?(%(#{ENV['HOME']}/.gnupg/S.gpg-agent))
192
- gpg_agent_socket = %(#{ENV['HOME']}/.gnupg/S.gpg-agent)
193
- gpg_agent_socket = %(#{ENV['HOME']}/.gnupg/S.gpg-agent)
194
- end
195
-
196
- begin
197
- unless gpg_agent_socket
198
- gpg_agent_output = %x(./run_gpg_agent).strip
199
-
200
- if gpg_agent_output.empty?
201
- # This is a working version of gpg-agent, that means we need to
202
- # connect to it to figure out what's going on
203
-
204
- gpg_agent_socket = %(#{Dir.pwd}/S.gpg-agent)
205
- gpg_agent_pid_info = %x(gpg-agent --homedir=#{Dir.pwd} /get serverpid).strip
206
- gpg_agent_pid_info =~ %r(\[(\d+)\])
207
- gpg_agent_pid = $1
208
- else
209
- # Are we running a broken version of the gpg-agent? If so, we'll
210
- # get back info on the command line.
211
-
212
- gpg_agent_info = gpg_agent_output.split(';').first.split('=').last.split(':')
213
- gpg_agent_socket = gpg_agent_info[0]
214
- gpg_agent_pid = gpg_agent_info[1].strip.to_i
215
-
216
- unless File.exist?(%(#{Dir.pwd}/#{File.basename(gpg_agent_socket)}))
217
- ln_s(gpg_agent_socket,%(#{Dir.pwd}/#{File.basename(gpg_agent_socket)}))
218
- end
219
- end
220
- end
221
-
222
- sh %{gpg --homedir=#{Dir.pwd} --batch --gen-key gengpgkey}
223
- %x{gpg --homedir=#{Dir.pwd} --armor --export #{dev_email} > RPM-GPG-KEY-SIMP-Dev}
224
- ensure
225
- begin
226
- rm('S.gpg-agent') if File.symlink?('S.gpg-agent')
227
-
228
- if gpg_agent_pid
229
- Process.kill(0,gpg_agent_pid)
230
- Process.kill(15,gpg_agent_pid)
231
- end
232
- rescue Errno::ESRCH
233
- # Not Running, Nothing to do!
234
- end
235
- end
236
- end
143
+ unless File.directory?(key_dir)
144
+ fail("Could not find GPG keydir '#{key_dir}' in '#{Dir.pwd}'")
237
145
  end
238
146
  end
239
147
 
240
- Dir.chdir(args[:key]) do
148
+ Dir.chdir(key_dir) do
241
149
  rpm_build_keys = Dir.glob('RPM-GPG-KEY-*')
150
+ if rpm_build_keys.empty?
151
+ fail("Could not find any RPM-GPG-KEY-* files in '#{key_dir}'")
152
+ end
242
153
 
243
- fail("Could not find any RPM-GPG-KEY files in '#{Dir.pwd}'") if rpm_build_keys.empty?
244
-
245
- # Drop the development key in the root of the ISO for convenience
246
- if args[:key] == 'dev'
247
- target_dir = @dvd_src
248
-
249
- fail("Could not find directory '#{target_dir}'") unless File.directory?(target_dir)
154
+ # Copy development keys into the root of the ISO for convenience
155
+ if key == 'dev'
156
+ unless File.directory?(dvd_dir)
157
+ fail("Could not find DVD ISO root directory '#{dvd_dir}'")
158
+ end
250
159
 
251
160
  rpm_build_keys.each do |gpgkey|
252
- cp(gpgkey,target_dir, :verbose => _verbose)
161
+ cp(gpgkey, dvd_dir, :verbose => @verbose)
253
162
  end
254
163
  # Otherwise, make sure it isn't present for the build
255
164
  else
256
- Dir.glob(File.join(@dvd_src,'RPM-GPG-KEY-SIMP*')).each do |to_del|
165
+ Dir[File.join(dvd_dir,'RPM-GPG-KEY-SIMP*')].each do |to_del|
257
166
  rm(to_del)
258
167
  end
259
168
  end
@@ -279,7 +188,6 @@ module Simp::Rake::Build
279
188
  fail("No RPMs found at #{rpm_dir}") if (rpms.nil? || rpms.empty?)
280
189
 
281
190
  have_signed_rpm = false
282
-
283
191
  Dir.chdir(rpm_dir) do
284
192
  rpms.each_key do |rpm|
285
193
  if @verbose
@@ -335,9 +243,6 @@ module Simp::Rake::Build
335
243
  EOM
336
244
  =end
337
245
  task :build,[:docs,:key] => [:prep,:key_prep] do |t,args|
338
-
339
- _verbose = ENV.fetch('SIMP_PKG_verbose','no') == 'yes'
340
-
341
246
  args.with_defaults(:key => 'dev')
342
247
  args.with_defaults(:docs => 'true')
343
248
 
@@ -603,7 +508,6 @@ module Simp::Rake::Build
603
508
  args[:aux_dir] = File.expand_path(args[:aux_dir])
604
509
  end
605
510
 
606
- _verbose = ENV.fetch('SIMP_PKG_verbose','no') == 'yes'
607
511
  _repoclose_pe = ENV.fetch('SIMP_PKG_repoclose_pe','no') == 'yes'
608
512
 
609
513
  yum_conf_template = <<-EOF
@@ -644,7 +548,7 @@ protect=1
644
548
  Find.find(base_dir) do |path|
645
549
  if (path =~ /.*\.rpm$/) and (path !~ /.*.src\.rpm$/)
646
550
  sym_path = "repos/base/#{File.basename(path)}"
647
- ln_s(path,sym_path, :verbose => _verbose) unless File.exists?(sym_path)
551
+ ln_s(path,sym_path, :verbose => @verbose) unless File.exists?(sym_path)
648
552
  end
649
553
  end
650
554
  end
@@ -654,7 +558,7 @@ protect=1
654
558
  Find.find(aux_dir) do |path|
655
559
  if (path =~ /.*\.rpm$/) and (path !~ /.*.src\.rpm$/)
656
560
  sym_path = "repos/lookaside/#{File.basename(path)}"
657
- ln_s(path,sym_path, :verbose => _verbose) unless File.exists?(sym_path)
561
+ ln_s(path,sym_path, :verbose => @verbose) unless File.exists?(sym_path)
658
562
  end
659
563
  end
660
564
  end
@@ -909,15 +813,15 @@ protect=1
909
813
  Dir.chdir(dir) do
910
814
  built_rpm = false
911
815
 
912
- if _verbose
816
+ if @verbose
913
817
  $stderr.puts("\nPackaging #{File.basename(dir)}")
914
818
  end
915
819
 
916
820
  # We're building a module, override anything down there
917
821
  if File.exist?('metadata.json')
918
822
  unique_namespace = generate_namespace
919
- if require_rebuild?(dir, yum_helper, { :unique_namespace => unique_namespace, :fetch => true, :verbose => _verbose, :prefix => dbg_prefix})
920
- $stderr.puts("#{dbg_prefix}Running 'rake pkg:rpm' on #{File.basename(dir)}") if _verbose
823
+ if require_rebuild?(dir, yum_helper, { :unique_namespace => unique_namespace, :fetch => true, :verbose => @verbose, :prefix => dbg_prefix})
824
+ $stderr.puts("#{dbg_prefix}Running 'rake pkg:rpm' on #{File.basename(dir)}") if @verbose
921
825
  Rake::Task["#{unique_namespace}:pkg:rpm"].invoke
922
826
  else
923
827
  # Record metadata for the downloaded RPM
@@ -929,8 +833,8 @@ protect=1
929
833
  # We're building one of the extra assets and should honor its Rakefile
930
834
  # and RPM spec file.
931
835
  elsif File.exist?('Rakefile')
932
- if require_rebuild?(dir, yum_helper, { :fetch => true, :verbose => _verbose, :prefix => dbg_prefix })
933
- $stderr.puts("#{dbg_prefix}Running 'rake pkg:rpm' in #{File.basename(dir)}") if _verbose
836
+ if require_rebuild?(dir, yum_helper, { :fetch => true, :verbose => @verbose, :prefix => dbg_prefix })
837
+ $stderr.puts("#{dbg_prefix}Running 'rake pkg:rpm' in #{File.basename(dir)}") if @verbose
934
838
  rake_flags = Rake.application.options.trace ? '--trace' : ''
935
839
  cmd = %{SIMP_BUILD_version=#{@simp_version} rake pkg:rpm #{rake_flags} 2>&1}
936
840
 
@@ -945,7 +849,7 @@ protect=1
945
849
  end
946
850
 
947
851
  unless build_success
948
- if _verbose
852
+ if @verbose
949
853
  $stderr.puts("First 'rake pkg:rpm' attempt for #{dir} failed, running bundle and trying again.")
950
854
  end
951
855
 
@@ -981,7 +885,7 @@ protect=1
981
885
  raise("No RPMs generated for #{dir}") if rpms.empty?
982
886
  end
983
887
 
984
- if _verbose
888
+ if @verbose
985
889
  rpms = Dir.glob('dist/*.rpm')
986
890
  # $stderr.puts("#{dbg_prefix}RPMS: #{rpms.join("\n#{dbg_prefix} ")}")
987
891
  $stderr.puts("Finished #{File.basename(dir)}")
@@ -1005,4 +909,5 @@ protect=1
1005
909
  end
1006
910
  end
1007
911
  end
912
+
1008
913
  end
@@ -2,5 +2,5 @@ module Simp; end
2
2
  module Simp::Rake; end
3
3
 
4
4
  class Simp::Rake::Helpers
5
- VERSION = '5.6.1'
5
+ VERSION = '5.6.2'
6
6
  end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper_acceptance'
2
+ require_relative 'support/build_user_helpers'
3
+
4
+ RSpec.configure do |c|
5
+ c.include Simp::BeakerHelpers::SimpRakeHelpers::BuildUserHelpers
6
+ c.extend Simp::BeakerHelpers::SimpRakeHelpers::BuildUserHelpers
7
+ end
8
+
9
+ # These spec tests are run from inside beaker nodesets because the logic
10
+ # Simp::LocalGpgSigningKey relies heavily on the behavior of the local OS's
11
+ # `gpg` and `gpg-agent` commands. Historically, these have caused us some
12
+ # grief due to minor inconsistencies between versions of gpg/gpg2/gpg-agent.
13
+ #
14
+ # It should be possible manage GPG keys using this logic from many OSes,
15
+ # but it's silly to try to mock them all directly in RSpec.
16
+ describe 'rake pkg:rpm with customized content' do
17
+
18
+ def hf_cmd( hosts, cmd, env_str=nil, opts={})
19
+ if ENV['PUPPET_VERSION']
20
+ env_str ||= %(export PUPPET_VERSION='#{ENV['PUPPET_VERSION']}';)
21
+ end
22
+ on hosts, %(#{run_cmd} "cd /home/build_user/host_files; #{env_str} #{cmd}"), opts
23
+ end
24
+
25
+ before :all do
26
+ copy_host_files_into_build_user_homedir(hosts)
27
+ hf_cmd(hosts, "bundle --local || bundle", nil, {run_in_parallel: true})
28
+ end
29
+
30
+ it 'can run the os-dependent Simp::LocalGpgSigningKey spec tests' do
31
+ hf_cmd( hosts, "bundle exec rspec spec/lib/simp/local_gpg_signing_key_spec.rb.beaker-only" );
32
+ end
33
+ end
34
+
@@ -0,0 +1,140 @@
1
+ require 'spec_helper_acceptance'
2
+ require_relative 'support/build_user_helpers'
3
+ require_relative 'support/build_project_helpers'
4
+
5
+ RSpec.configure do |c|
6
+ c.include Simp::BeakerHelpers::SimpRakeHelpers::BuildUserHelpers
7
+ c.extend Simp::BeakerHelpers::SimpRakeHelpers::BuildUserHelpers
8
+ c.include Simp::BeakerHelpers::SimpRakeHelpers::BuildProjectHelpers
9
+ c.extend Simp::BeakerHelpers::SimpRakeHelpers::BuildProjectHelpers
10
+ end
11
+
12
+ describe 'rake pkg:signrpms' do
13
+ def opts
14
+ { run_in_parallel: true, environment: { 'SIMP_PKG_verbose' => 'yes' } }
15
+ end
16
+
17
+ # Clean out RPMs dir and copy in a fresh dummy RPM
18
+ def prep_rpms_dir(rpms_dir, src_rpms, opts = {})
19
+ copy_cmds = src_rpms.map { |_rpm| "cp -a '#{_rpm}' '#{rpms_dir}'" }.join('; ')
20
+ on(hosts, %(#{run_cmd} "rm -f '#{rpms_dir}/*'; #{copy_cmds} "), opts)
21
+ end
22
+
23
+ # Provides a scaffolded test project and `let` variables
24
+ shared_context 'a freshly-scaffolded test project' do |dir|
25
+ opts = {}
26
+ test__dir = "#{build_user_homedir}/test--#{dir}"
27
+ rpms__dir = "#{test__dir}/test.rpms"
28
+ src__rpm = "#{build_user_host_files}/spec/lib/simp/files/testpackage-1-0.noarch.rpm"
29
+ host__dirs = {}
30
+
31
+ hosts.each do |host|
32
+ dist_dir = distribution_dir(host, test__dir, opts)
33
+ host__dirs[host] = {
34
+ test_dir: test__dir,
35
+ dev_keydir: "#{dist_dir}/build_keys/dev",
36
+ dvd_dir: "#{dist_dir}/DVD",
37
+ }
38
+ host__dirs[host.name] = host__dirs[host]
39
+ end
40
+
41
+ before(:all) do
42
+ # Scaffold a project skeleton
43
+ scaffold_build_project(hosts, test__dir, opts)
44
+
45
+ # Provide an RPM directory to process and a dummy RPM to sign
46
+ on(hosts, %(#{run_cmd} "mkdir '#{rpms__dir}'"))
47
+
48
+ # Ensure a DVD directory exists that is appropriate to each SUT
49
+ hosts.each do |host|
50
+ on(host, %(#{run_cmd} "mkdir -p '#{host__dirs[host][:dvd_dir]}'"), opts)
51
+ end
52
+ end
53
+
54
+ let(:test_dir) { test__dir }
55
+ let(:rpms_dir) { rpms__dir }
56
+ let(:src_rpm) { src__rpm }
57
+ let(:test_rpm) { "#{rpms__dir}/#{File.basename(src__rpm)}" }
58
+ let(:dirs) { host__dirs }
59
+ end
60
+
61
+ let(:rpm_unsigned_regex) do
62
+ %r{^Signature\s+:\s+\(none\)$}
63
+ end
64
+
65
+ let(:rpm_signed_regex) do
66
+ %r{^Signature\s+:\s+.*,\s*Key ID (?<key_id>[0-9a-f]+)$}
67
+ end
68
+
69
+ let(:expired_keydir) do
70
+ "#{build_user_host_files}/spec/acceptance/files/build/pkg/gpg-keydir.expired.2018-04-06"
71
+ end
72
+
73
+ shared_examples 'it creates a new GPG dev signing key' do
74
+ it 'creates a new GPG dev signing key' do
75
+ on(hosts, %(#{run_cmd} "cd '#{test_dir}'; bundle exec rake pkg:signrpms[dev,'#{rpms_dir}']"), opts)
76
+ hosts.each do |host|
77
+ expect { dev_signing_key_id(host, test_dir, opts) }.not_to(raise_error)
78
+ end
79
+ end
80
+ end
81
+
82
+ shared_examples 'it begins with unsigned RPMs' do
83
+ it 'begins with unsigned RPMs' do
84
+ prep_rpms_dir(rpms_dir, [src_rpm], opts)
85
+ rpms_before_signing = on(hosts, %(#{run_cmd} "rpm -qip '#{test_rpm}' | grep ^Signature"), opts)
86
+ rpms_before_signing.each do |result|
87
+ expect(result.stdout).to match rpm_unsigned_regex
88
+ end
89
+ end
90
+ end
91
+
92
+ shared_examples 'it signs RPM packages in the directory using the GPG dev signing key' do
93
+ it 'signs RPM packages in the directory using the GPG dev signing key' do
94
+ on(hosts, %(#{run_cmd} "cd '#{test_dir}'; bundle exec rake pkg:signrpms[dev,'#{rpms_dir}']"), opts)
95
+ rpms_after_signing = on(hosts, %(#{run_cmd} "rpm -qip '#{test_rpm}' | grep ^Signature"), opts)
96
+ rpms_after_signing.each do |result|
97
+ host = hosts_with_name(hosts, result.host).first
98
+ on(host, "gpg --list-keys --homedir='#{dirs[host][:dev_keydir]}'", opts)
99
+
100
+ expect(result.stdout).to match rpm_signed_regex
101
+ signed_rpm_data = rpm_signed_regex.match(result.stdout)
102
+ expect(signed_rpm_data[:key_id]).to eql dev_signing_key_id(host, test_dir, opts)
103
+ end
104
+ end
105
+ end
106
+
107
+ describe 'when starting without a dev key' do
108
+ include_context('a freshly-scaffolded test project', 'pkg-signrpms')
109
+ include_examples('it creates a new GPG dev signing key')
110
+ include_examples('it begins with unsigned RPMs')
111
+ include_examples('it signs RPM packages in the directory using the GPG dev signing key')
112
+
113
+ context 'when there is an unexpired GPG dev signing key' do
114
+ include_examples('it begins with unsigned RPMs')
115
+ include_examples('it signs RPM packages in the directory using the GPG dev signing key')
116
+ end
117
+ end
118
+
119
+ describe 'when starting with an expired dev key' do
120
+ include_context('a freshly-scaffolded test project', 'pkg-signrpms-expired_dev_key')
121
+
122
+ it 'begins with an expired GPG signing key' do
123
+ prep_rpms_dir(rpms_dir, [src_rpm], opts)
124
+ hosts.each do |host|
125
+ copy_expired_keydir_to_dev_cmds = [
126
+ "mkdir -p '$(dirname '#{dirs[host][:dev_keydir]}')'",
127
+ "cp -aT '#{expired_keydir}' '#{dirs[host][:dev_keydir]}'",
128
+ "ls -lart '#{expired_keydir}'"
129
+ ].join(' && ')
130
+ on(host, %(#{run_cmd} "#{copy_expired_keydir_to_dev_cmds}"), opts)
131
+ result = on(host, %(#{run_cmd} "gpg --list-keys --homedir='#{dirs[host][:dev_keydir]}'"), opts)
132
+ expect(result.stdout).to match(/expired: 2018-04-06/)
133
+ end
134
+ end
135
+
136
+ include_examples('it creates a new GPG dev signing key')
137
+ include_examples('it begins with unsigned RPMs')
138
+ include_examples('it signs RPM packages in the directory using the GPG dev signing key')
139
+ end
140
+ end
@@ -0,0 +1,30 @@
1
+ -----BEGIN PGP PUBLIC KEY BLOCK-----
2
+ Version: GnuPG v2.0.22 (GNU/Linux)
3
+
4
+ mQINBFq1adoBEACrnso3sC9+10Z+v0m1KU1EeFFTBZve5OO9vxGDFa0GSn9aLAm7
5
+ UQcaVxEnXeB83fKS6AndXD0tR9/ut64WYGUCIVusW7iYhUL26w5qHYfK3M8PTa/A
6
+ mNTeV5327NmkJ8Ky5Djvx4nR43e2vhtzHK+WjfFdaFLpHqvATnQFohl/VtT8DGHg
7
+ zB7jHnif4rWx36wS2ftJCYFAtvrTqGT1ZQ+FNT64Y5NG8U8X1DRRgOiuY7z/fXqD
8
+ 9akOglP9hhmaWBBKHySjO/7JC6SOdiNDDGD/Ay4IpYeBb1RP1WheKvrP6VNVLp3N
9
+ wNrmZouZvh/itxrmEaeOrGkLjlpSa5BTZz+Cyrig+fR4DjeSwHrQRFsVHpzKwt01
10
+ tBssfpvC5x23MFyEnsqaCR/XlpjE/PFG5NeNR+hwNolhGr30vbrht6iaGfAjbh8G
11
+ V5jmYHFIdFT+Q0V3zwviCznZPSEHcjay769wp39wa0rgqG9pIX/zYTdetolI6+Mn
12
+ 3cskueoiVfSTL3iDA6rObFdg2c72JGdQpZRxr5oC5pD1ecdGULOCv47ppTQW+r8O
13
+ cnCNotXPw/2GNoofPGP6wKx7wimUIBATn2gAGLRtXip1MyzmzCY6Hz9an+aiPlJ+
14
+ Fo1fnJGxiiLbBwS/gPCdhrDPHFbcHjROA0i1HTnYwqvSqfdJFvXuk9oZMQARAQAB
15
+ tE9TSU1QIERldmVsb3BtZW50IChEZXZlbG9wbWVudCBrZXkgMTUyMTgzODU1NCkg
16
+ PGdhdGVrZWVwZXJAc2ltcC5kZXZlbG9wbWVudC5rZXk+iQI+BBMBAgApBQJatWna
17
+ AhsDBQkAEnUABwsJCAcDAgEGFQgCCQoLBBYCAwECHgECF4AACgkQciuXqAjn2uqG
18
+ Ow/45WoHH4k06jT98uM0qTzwCMUeuNSlCLcGUw+MmcAqC00lApEzRSmTWXFJDr+E
19
+ DMHCNTl5gK+vVXkhY/VGS+xBTrjO7Zc/jtCHIYRu92hRc18WSkfdzmP1rEnhmrrT
20
+ sCjdbBfV5vccSG2QCsqrf8boZ25FDMUQy2yW7CYiP3jMIaWZGcN5YXmVotq4e9g7
21
+ /9UIvoSk6ra45VXSBcfqUKDHvCn44PV7Qq3V9Z1TLRVxUIHVIujmVabUey5cSK9X
22
+ frzg9C0q5C0ksOLeC4RhUsS/FFxPPOaZ2u/LCUCad60Pwmdfxdx8QqPHKfhW52V7
23
+ tAtfW2LwWTu0tJ5nmUPSup12Jm36JUxZRK1bxQMgt90jL0LcY7L5VlXtaHO4sWhV
24
+ B1rUDRyhYmLceex585IdjyUTczEwOB7FuYdF8sR0Y/5a2gZKsrDk1A5Aq2QSi7pJ
25
+ ISFEnTfO6KRBpa4Oqo3DB5ABKqnL4aoROiqNaGp+6/Wgg7seErK6ZBDhTHqK+muF
26
+ eBVlmei0iZa5H3BwFEtWNRjeiNaWbWqVROTchezBlu1IjDnordBHC3T7r1Wal+Mg
27
+ boATaK9hyQfo2Gnab8IgsF+mwWYpU8lN3H/u4rEVoLr43YWDGVqaD8gcQFK7qzRq
28
+ jwfirprHBAW567vUqgloljq9w9xsAJl4PijX6mQcIy31RQ==
29
+ =bq4o
30
+ -----END PGP PUBLIC KEY BLOCK-----
@@ -0,0 +1,17 @@
1
+ %echo Generating Development GPG Key
2
+ %echo
3
+ %echo This key will expire on 2018-04-06T20:55:54+00:00
4
+ %echo
5
+ Key-Type: RSA
6
+ Key-Length: 4096
7
+ Key-Usage: sign
8
+ Name-Real: SIMP Development
9
+ Name-Comment: Development key 1521838554
10
+ Name-Email: gatekeeper@simp.development.key
11
+ Expire-Date: 2w
12
+ Passphrase: rcGDDzNywQNTuRmAN145EQJBEwCtHMTNmzYtMdYin9H+VrAIwn4Facv5e6l2mvu8IkyRXL38GpJjopCN3L9Hj6Jk22xkUvOPP+sabE8zzMdJpmsO0eOoxkUM7JEj4uF2CgCC5FFnWOD2zodpBBC3EJQbfdeCrjQlNYcMrbHCz+VODDhq954ZXhM94DmE3MXKqV5FyhGCy4r3IV3nfquQsZts9hbqcJquJ7vrX3ES0LYv1h6tz9Wcm5cRXSUo8eYPY3kSeQulseeyLR1sQgaQmAqRVBWSMD2hBkV8EBHfwRnyTPgHkL990oP5t7ER08fGBTnHcqPKr23Jij9BTSDWMKkwGagLbg+kfPoLRfW7R/791Xr3tN/kb02vainGjiRHgt/VlAQluzZZ60XFnDwBk8AoOopDXTX5lUrlVUsaBOi5KtEVEHLZdVtBqANQxtlpZtUWsnvjpoBrmu85kqbXX9YEoRitraS/Y4bf5ybOkMjixjthk5vGaHFZnYwON4gEbhN1fhxN4ElPyqahLQuBRmy4cF+8YJGlsOjnaVRzgm0XFu3O1INIwC7ZejXdkKumqajSRfmPCVy8NpEAJrb5h6Z9al/3Bu2mjAPU9MfDWYgSsqvS1V40nRI6Af1uLnCupWkyrcnLnBaV7VeDf8pasI0NQ1U=
13
+ %pubring pubring.gpg
14
+ %secring secring.gpg
15
+ # The following creates the key, so we can print "Done!" afterwards
16
+ %commit
17
+ %echo New GPG Development Key Created
@@ -0,0 +1,3 @@
1
+ #!/bin/sh
2
+
3
+ gpg-agent --homedir=/src/build/distributions/CentOS/7/x86_64/build_keys/dev --batch --daemon --pinentry-program /usr/bin/pinentry-curses < /dev/null &
@@ -0,0 +1,17 @@
1
+ # Dummy super-release (`simp-core`) project
2
+
3
+ The contents of this directory tree provide _just enough _directories and dummy
4
+ files for a `rake -T` to avoid failing during ` Simp::Rake::Build::Helpers.new`
5
+
6
+ ## What this provides
7
+
8
+ * A (paper-thin) dummy for a super-release project like [`simp-core`][simp-core])
9
+ * A means to acceptance-test `simp/rake/build/helpers`
10
+
11
+ ## How to use this project in your acceptance tests
12
+
13
+ To use this project in your acceptance tests:
14
+
15
+ * `rsync` this directory tree into a test-specific directory root
16
+ * copy in any specific assets you need for your tests
17
+ * run `bundle exec rake <task>` to test the scenario you have modeled.
@@ -0,0 +1,8 @@
1
+ begin
2
+ require 'simp/rake/build/helpers'
3
+ BASEDIR = File.dirname(__FILE__)
4
+ Simp::Rake::Build::Helpers.new( BASEDIR )
5
+ rescue LoadError => e
6
+ warn "WARNING: #{e.message}"
7
+ end
8
+
@@ -0,0 +1,32 @@
1
+ Name: testpackage
2
+ Version: 1
3
+ Release: 0
4
+ Summary: dummy test package
5
+ BuildArch: noarch
6
+
7
+ License: Apache-2.0
8
+ URL: http://foo.bar
9
+
10
+ %description
11
+ A dummy package used to test Simp::RPM methods
12
+
13
+ %prep
14
+ exit 0
15
+
16
+ %build
17
+ exit 0
18
+
19
+
20
+ %install
21
+ exit 0
22
+
23
+ %clean
24
+ exit 0
25
+
26
+ %files
27
+ %doc
28
+
29
+
30
+ %changelog
31
+ * Wed Jun 10 2015 nobody
32
+ - some comment
@@ -53,6 +53,7 @@ HOSTS:
53
53
  - 'runuser build_user -l -c "rvm install 2.1"'
54
54
  - 'runuser build_user -l -c "rvm use --default 2.1"'
55
55
  - 'runuser build_user -l -c "rvm all do gem install bundler"'
56
+ - 'yum install -y rpm-sign'
56
57
  mount_folders:
57
58
  folder1:
58
59
  host_path: ./
@@ -0,0 +1,72 @@
1
+ module Simp::BeakerHelpers::SimpRakeHelpers::BuildProjectHelpers
2
+ # Scaffolds _just_ enough of a super-release project to run `bundle exec rake
3
+ # -T` using this repository's source code as the simp-rake-helper source
4
+ #
5
+ # @param [Host, Array<Host>, String, Symbol] hosts Beaker host/hosts/role
6
+ # @param [Hash{Symbol=>String}] opts Beaker options Hash for `#on` ({})
7
+ #
8
+ def scaffold_build_project(hosts, test_dir, opts = {})
9
+ copy_host_files_into_build_user_homedir(hosts, opts)
10
+ skeleton_dir = "#{build_user_host_files}/spec/acceptance/files/build/project_skeleton/"
11
+
12
+ on(hosts, %(mkdir "#{test_dir}"; chown build_user:build_user "#{test_dir}"), opts)
13
+ on(hosts, %(#{run_cmd} "cp -aT '#{skeleton_dir}' '#{test_dir}'"), opts)
14
+ gemfile = <<-GEMFILE.gsub(%r{^ {6}}, '')
15
+ gem_sources = ENV.fetch('GEM_SERVERS','https://rubygems.org').split(/[, ]+/)
16
+ gem_sources.each { |gem_source| source gem_source }
17
+ gem 'simp-rake-helpers', :path => '#{build_user_host_files}'
18
+ gem 'simp-build-helpers', ENV.fetch('SIMP_BUILD_HELPERS_VERSION', '>= 0.1.0')
19
+ GEMFILE
20
+ create_remote_file(hosts, "#{test_dir}/Gemfile", gemfile, opts)
21
+ on(hosts, "chown build_user:build_user #{test_dir}/Gemfile", opts)
22
+ on(hosts, %(#{run_cmd} "cd '#{test_dir}'; rvm use default; bundle --local || bundle"), opts)
23
+ end
24
+
25
+ # Returns the distribution directory path appropriate for a given SUT
26
+ #
27
+ # @example The distribution directory format looks like:
28
+ #
29
+ # `build/distributions/CentOS/6/x86_64
30
+ #
31
+ # @param [Host, String, Symbol] host Beaker host
32
+ # @param [String] proj_dir Absolute path to the parent project directory
33
+ # If this is set, the returned path will be absolute as well.
34
+ # @param [Hash{Symbol=>String}] opts Beaker options Hash for `#on` ({})
35
+ # @return [String] distribution directory matching the SUT's properties
36
+ #
37
+ def distribution_dir(host, proj_dir, opts = {})
38
+ opts ||= {}
39
+ @distribution_dirs ||= {}
40
+ return @distribution_dirs[host.to_s] if @distribution_dirs.key?(host.to_s)
41
+
42
+ result = on(host, %(#{run_cmd} 'facter --yaml'), opts.merge(silent: true))
43
+ facts_string = result.stdout.lines[1..-1].join
44
+ facts = YAML.load(facts_string)
45
+
46
+ # This logic should work regardless of the version of facter
47
+ name = facts['operatingsystem'] || facts['os']['name']
48
+ maj_rel = facts['operatingsystemmajrelease'] ||
49
+ facts.fetch('os', {}).fetch('release', {})['major'] ||
50
+ facts['operatingsystemrelease'].split('.').first
51
+ architecture = facts['architecture']
52
+
53
+ dir = "#{proj_dir}/build/distributions/#{name}/#{maj_rel}/#{architecture}"
54
+ @distribution_dirs[host.to_s] = dir
55
+ end
56
+
57
+ # Scans a host path for the 'SIMP Development' GPG key and returns its Key ID
58
+ #
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
62
+ # @param [Hash{Symbol=>String}] opts Beaker options Hash for `#on` ({})
63
+ # @return [String] GPG dev signing Key ID
64
+ #
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
71
+ end
72
+ end
@@ -0,0 +1,20 @@
1
+ module Simp::BeakerHelpers::SimpRakeHelpers::BuildUserHelpers
2
+ def build_user_homedir
3
+ '/home/build_user'
4
+ end
5
+
6
+ def build_user_host_files
7
+ "#{build_user_homedir}/host_files"
8
+ end
9
+
10
+ def copy_host_files_into_build_user_homedir(hosts, opts = {})
11
+ commands = <<-COMMANDS.gsub(/^ {6}/,'')
12
+ cp -aT /host_files #{build_user_host_files} ;
13
+ find #{build_user_host_files} \\
14
+ -type d -a \\( -name dist -o -name junit -o -name log \\) \\
15
+ -exec chmod -R go=u-w {} \\; ;
16
+ chown -R build_user:build_user #{build_user_host_files}
17
+ COMMANDS
18
+ on(hosts,commands,opts)
19
+ end
20
+ end
@@ -1,5 +1,8 @@
1
1
  module Simp::BeakerHelpers::SimpRakeHelpers::PkgRpmHelpers
2
2
 
3
+ require_relative 'build_user_helpers'
4
+ include Simp::BeakerHelpers::SimpRakeHelpers::BuildUserHelpers
5
+
3
6
  # rake command string to run on hosts
4
7
  # passes on useful troubleshooting env vars
5
8
  def rake_cmd
@@ -17,17 +20,6 @@ module Simp::BeakerHelpers::SimpRakeHelpers::PkgRpmHelpers
17
20
  end
18
21
 
19
22
 
20
- def copy_host_files_into_build_user_homedir(
21
- hosts,
22
- root_dir=File.expand_path('../../../',__FILE__)
23
- )
24
- # I've added the `ch* -R` on the SUT-side, which seems to work on a fresh checkout
25
- on hosts, 'cp -a /host_files /home/build_user/; ' +
26
- 'chmod -R go=u-w /home/build_user/host_files/{dist,**/dist,junit,log}; ' +
27
- 'chown -R build_user:build_user /home/build_user/host_files; '
28
- end
29
-
30
-
31
23
  # key = what `rpm -q --scripts` calls each scriptlet
32
24
  # value = the label passed to `simp_rpm_helper`
33
25
  def scriptlet_label_map
@@ -0,0 +1,11 @@
1
+ module Simp::BeakerHelpers::SimpRakeHelpers
2
+ # Add RSpec log comments within examples ("it blocks")
3
+ def comment(msg, indent = 10)
4
+ logger.optionally_color(Beaker::Logger::MAGENTA, ' ' * indent + msg)
5
+ end
6
+
7
+ # basic command + arguments for executing `runuser` within an SUT
8
+ def run_cmd
9
+ @run_cmd ||= 'runuser build_user -l -c '
10
+ end
11
+ end
@@ -0,0 +1,96 @@
1
+ require 'simp/local_gpg_signing_key'
2
+ require 'spec_helper'
3
+ require 'fileutils'
4
+ require 'tmpdir'
5
+
6
+ describe Simp::LocalGpgSigningKey do
7
+ include FileUtils
8
+
9
+ before :all do
10
+ TMP_DIR = Dir.mktmpdir('spec_test__simp_local_gpg_signing_key')
11
+ TMP_DEV_DIR = File.join(TMP_DIR, 'dev')
12
+ OPTS = {verbose: ENV['VERBOSE'].to_s =~ /^(yes|true)$/ }
13
+
14
+ mkdir_p TMP_DIR
15
+
16
+ # Be a good citizen and preserve pre-existing agent variables
17
+ ORIGINAL_GPG_AGENT_INFO = ENV['GPG_AGENT_INFO']
18
+ end
19
+
20
+ after :all do
21
+ rm_rf TMP_DIR
22
+
23
+ # Be a good citizen and preserve pre-existing agent variables
24
+ ENV['GPG_AGENT_INFO'] = ORIGINAL_GPG_AGENT_INFO
25
+ end
26
+
27
+ 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)
30
+ end
31
+
32
+ it 'had a gpg-agent socket' do
33
+ socket = agent_info[:socket]
34
+ expect(File.absolute_path(socket.to_s)).to eq socket.to_s
35
+ end
36
+
37
+ it 'has killed the local gpg-agent' do
38
+ expect(File.exist?(agent_info[:socket])).to be false
39
+ end
40
+ end
41
+
42
+
43
+ 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') }
46
+ end
47
+
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
55
+ end
56
+ end
57
+
58
+ shared_examples_for 'it encountered an unexpired local gpg signing key' do
59
+ it 'reuses an unexpired local gpg signing key' do
60
+ expect{described_class.new(TMP_DEV_DIR,OPTS).ensure_key}.to output(
61
+ /^GPG key \(gatekeeper@simp\.development\.key\) will expire in 14 days\./
62
+ ).to_stdout
63
+ end
64
+
65
+ it 'reuses an unexpired local gpg signing key' do
66
+ expect{described_class.new(TMP_DEV_DIR,OPTS).ensure_key}.to output(
67
+ /^GPG key \(gatekeeper@simp\.development\.key\) will expire in 14 days\./
68
+ ).to_stdout
69
+ end
70
+ end
71
+
72
+ context '#ensure_key' do
73
+ before :all do
74
+ rm_rf TMP_DEV_DIR
75
+ ENV['GPG_AGENT_INFO'] = nil
76
+ end
77
+
78
+ context 'when run from scratch' do
79
+ before :all do
80
+ FIRST_RUN_AGENT_INFO = described_class.new(TMP_DEV_DIR,OPTS).ensure_key
81
+ end
82
+ let(:agent_info){ FIRST_RUN_AGENT_INFO }
83
+ it_behaves_like 'it just generated a local gpg signing key'
84
+ it_behaves_like 'a valid gpg signing key environment'
85
+ end
86
+
87
+ context 'when run again' do
88
+ before :all do
89
+ SECOND_RUN_AGENT_INFO = described_class.new(TMP_DEV_DIR,OPTS).ensure_key
90
+ end
91
+ let(:agent_info){ SECOND_RUN_AGENT_INFO }
92
+ it_behaves_like 'it encountered an unexpired local gpg signing key'
93
+ it_behaves_like 'a valid gpg signing key environment'
94
+ end
95
+ end
96
+ end
@@ -4,19 +4,9 @@ include Simp::BeakerHelpers
4
4
  require 'tmpdir'
5
5
  require 'pry' if ENV['PRY'] == 'yes'
6
6
 
7
+ require 'acceptance/support/simp_rake_helpers'
7
8
  $LOAD_PATH.unshift(File.expand_path('../acceptance/support',__FILE__))
8
9
 
9
- module Simp::BeakerHelpers::SimpRakeHelpers
10
- # Add RSpec log comments within examples ("it blocks")
11
- def comment(msg, indent=10)
12
- logger.optionally_color(Beaker::Logger::MAGENTA, " "*indent + msg)
13
- end
14
-
15
- # basic command + arguments for executing `runuser` within an SUT
16
- def run_cmd
17
- @run_cmd ||= 'runuser build_user -l -c '
18
- end
19
- end
20
10
 
21
11
  RSpec.configure do |c|
22
12
  # provide helper methods to individual examples AND example groups
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simp-rake-helpers
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.6.1
4
+ version: 5.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Tessmer
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2018-10-02 00:00:00.000000000 Z
12
+ date: 2018-11-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: simp-beaker-helpers
@@ -225,8 +225,9 @@ dependencies:
225
225
  - - "~>"
226
226
  - !ruby/object:Gem::Version
227
227
  version: '0.0'
228
- description: |2
229
- "simp-rake-helpers provides common methods for SIMP Rake Tasks"
228
+ description: ' "simp-rake-helpers provides common methods for SIMP Rake Tasks"
229
+
230
+ '
230
231
  email: simp@simp-project.org
231
232
  executables: []
232
233
  extensions: []
@@ -243,6 +244,7 @@ files:
243
244
  - Rakefile
244
245
  - bin/simp_rake_helpers
245
246
  - lib/simp/componentinfo.rb
247
+ - lib/simp/local_gpg_signing_key.rb
246
248
  - lib/simp/rake.rb
247
249
  - lib/simp/rake/build/auto.rb
248
250
  - lib/simp/rake/build/build.rb
@@ -278,6 +280,8 @@ files:
278
280
  - spec/acceptance/10_pkg_rpm_spec.rb
279
281
  - spec/acceptance/20_pkg_rpm_safely_upgrading_obsolete_modules_spec.rb
280
282
  - spec/acceptance/30_pkg_misc_spec.rb
283
+ - spec/acceptance/50_local_gpg_signing_key_spec.rb
284
+ - spec/acceptance/55_build_pkg_signing_spec.rb
281
285
  - spec/acceptance/development/docker_env.sh
282
286
  - spec/acceptance/development/rerun_acceptance_tests.sh
283
287
  - spec/acceptance/development/vagrant_rsync.sh
@@ -285,6 +289,17 @@ files:
285
289
  - spec/acceptance/files/asset/build/asset.spec
286
290
  - spec/acceptance/files/asset_with_misordered_entries/Rakefile
287
291
  - spec/acceptance/files/asset_with_misordered_entries/build/asset_with_misordered_entries.spec
292
+ - spec/acceptance/files/build/pkg/gpg-keydir.expired.2018-04-06/RPM-GPG-KEY-SIMP-Dev
293
+ - spec/acceptance/files/build/pkg/gpg-keydir.expired.2018-04-06/gengpgkey
294
+ - spec/acceptance/files/build/pkg/gpg-keydir.expired.2018-04-06/pubring.gpg
295
+ - spec/acceptance/files/build/pkg/gpg-keydir.expired.2018-04-06/random_seed
296
+ - spec/acceptance/files/build/pkg/gpg-keydir.expired.2018-04-06/run_gpg_agent
297
+ - spec/acceptance/files/build/pkg/gpg-keydir.expired.2018-04-06/secring.gpg
298
+ - spec/acceptance/files/build/pkg/gpg-keydir.expired.2018-04-06/trustdb.gpg
299
+ - spec/acceptance/files/build/project_skeleton/Puppetfile.tracking
300
+ - spec/acceptance/files/build/project_skeleton/README.md
301
+ - spec/acceptance/files/build/project_skeleton/Rakefile
302
+ - spec/acceptance/files/build/project_skeleton/src/assets/simp/build/simp.spec
288
303
  - spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-2.1/CHANGELOG
289
304
  - spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-2.1/Rakefile
290
305
  - spec/acceptance/files/custom_scriptlet_triggers/pupmod-new-package-2.1/build/rpm_metadata/custom/overrides
@@ -370,7 +385,10 @@ files:
370
385
  - spec/acceptance/files/testpackage_without_changelog/build/rpm_metadata/requires
371
386
  - spec/acceptance/files/testpackage_without_changelog/metadata.json
372
387
  - spec/acceptance/nodesets/default.yml
388
+ - spec/acceptance/support/build_project_helpers.rb
389
+ - spec/acceptance/support/build_user_helpers.rb
373
390
  - spec/acceptance/support/pkg_rpm_helpers.rb
391
+ - spec/acceptance/support/simp_rake_helpers.rb
374
392
  - spec/lib/simp/componentinfo_changelog_regex_spec.rb
375
393
  - spec/lib/simp/componentinfo_spec.rb
376
394
  - spec/lib/simp/files/build/testpackage.spec
@@ -429,6 +447,7 @@ files:
429
447
  - spec/lib/simp/files/testpackage-dist.spec
430
448
  - spec/lib/simp/files/testpackage-multi.spec
431
449
  - spec/lib/simp/files/testpackage.spec
450
+ - spec/lib/simp/local_gpg_signing_key_spec.rb.beaker-only
432
451
  - spec/lib/simp/rake/build/files/changed_name_mod/metadata.json
433
452
  - spec/lib/simp/rake/build/files/dependencies.yaml
434
453
  - spec/lib/simp/rake/build/files/malformed_dep_meta_mod/metadata.json
@@ -506,7 +525,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
506
525
  version: '0'
507
526
  requirements: []
508
527
  rubyforge_project:
509
- rubygems_version: 2.7.7
528
+ rubygems_version: 2.6.14.1
510
529
  signing_key:
511
530
  specification_version: 4
512
531
  summary: SIMP rake helpers