simp-rake-helpers 5.6.1 → 5.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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