pupistry 1.0.0 → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +13 -1
- data/{bin → exe}/pupistry +45 -76
- data/lib/pupistry.rb +1 -1
- data/lib/pupistry/agent.rb +40 -60
- data/lib/pupistry/artifact.rb +136 -172
- data/lib/pupistry/bootstrap.rb +30 -35
- data/lib/pupistry/config.rb +59 -31
- data/lib/pupistry/gpg.rb +71 -102
- data/lib/pupistry/storage_aws.rb +56 -61
- data/lib/pupistry/version.rb +3 -0
- data/resources/aws/cfn_pupistry_bucket_and_iam.template +11 -1
- data/resources/packer/amazon_linux.json +17 -0
- data/resources/packer/test_user_data.txt +33 -0
- metadata +92 -5
data/lib/pupistry/bootstrap.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
+
# rubocop:disable Style/Documentation, Style/GlobalVars
|
1
2
|
require 'rubygems'
|
2
|
-
require
|
3
|
+
require 'base64'
|
3
4
|
require 'erubis'
|
4
5
|
|
5
6
|
module Pupistry
|
@@ -10,98 +11,92 @@ module Pupistry
|
|
10
11
|
attr_accessor :contents
|
11
12
|
|
12
13
|
def initialize
|
13
|
-
|
14
14
|
# We need to find where the templates are located - either it should be
|
15
15
|
# in the current working directory, or if we are an installed gem, we
|
16
16
|
# can try the gem's installed path.
|
17
17
|
|
18
|
-
if Dir.
|
18
|
+
if Dir.exist?('resources/bootstrap/')
|
19
19
|
# Use local PWD version first if possible
|
20
20
|
@template_dir = Dir.pwd
|
21
21
|
else
|
22
22
|
# Check for GEM installed location
|
23
23
|
begin
|
24
|
-
@template_dir = Gem::Specification.find_by_name(
|
24
|
+
@template_dir = Gem::Specification.find_by_name('pupistry').gem_dir
|
25
25
|
rescue Gem::LoadError
|
26
26
|
$logger.error "Unable to find templates/ directory, doesn't appear we are running from project dir nor as a Gem"
|
27
27
|
return false
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
@template_dir = @template_dir.chomp(
|
31
|
+
@template_dir = @template_dir.chomp('/') + '/resources/bootstrap/'
|
32
32
|
|
33
|
-
|
33
|
+
if Dir.exist?(@template_dir)
|
34
|
+
$logger.debug "Using directory #{@template_dir} for bootstrap templates"
|
35
|
+
else
|
34
36
|
$logger.error "Unable to find templates dir at #{@template_dir}, unable to proceed."
|
35
37
|
return false
|
36
|
-
else
|
37
|
-
$logger.debug "Using directory #{@template_dir} for bootstrap templates"
|
38
38
|
end
|
39
|
-
|
40
39
|
end
|
41
|
-
|
42
40
|
|
43
41
|
def list
|
44
42
|
# Simply glob the templates directory and list their names.
|
45
|
-
$logger.debug
|
43
|
+
$logger.debug 'Finding all available templates'
|
46
44
|
|
47
45
|
Dir.glob("#{@template_dir}/*.erb").each do |file|
|
48
|
-
puts "- #{File.basename(file,
|
46
|
+
puts "- #{File.basename(file, '.erb')}"
|
49
47
|
end
|
50
48
|
end
|
51
49
|
|
52
|
-
|
53
|
-
def build template
|
50
|
+
def build(template)
|
54
51
|
# Build a template with the configured parameters already to go and save
|
55
52
|
# into the object, so it can be outputted in the desired format.
|
56
53
|
|
57
54
|
$logger.debug "Generating a bootstrap script for #{template}"
|
58
55
|
|
59
|
-
unless File.
|
60
|
-
$logger.error
|
56
|
+
unless File.exist?("#{@template_dir}/#{template}.erb")
|
57
|
+
$logger.error 'The requested template does not exist, unable to build'
|
61
58
|
return 0
|
62
59
|
end
|
63
60
|
|
64
61
|
# Assume values we care about
|
65
62
|
template_values = {
|
66
|
-
s3_bucket: $config[
|
67
|
-
s3_prefix: $config[
|
68
|
-
gpg_disable: $config[
|
69
|
-
gpg_signing_key: $config[
|
70
|
-
puppetcode: $config[
|
71
|
-
access_key_id: $config[
|
72
|
-
secret_access_key: $config[
|
73
|
-
region: $config[
|
74
|
-
proxy_uri: $config[
|
75
|
-
daemon_frequency: $config[
|
76
|
-
daemon_minimal: $config[
|
63
|
+
s3_bucket: $config['general']['s3_bucket'],
|
64
|
+
s3_prefix: $config['general']['s3_prefix'],
|
65
|
+
gpg_disable: $config['general']['gpg_disable'],
|
66
|
+
gpg_signing_key: $config['general']['gpg_signing_key'],
|
67
|
+
puppetcode: $config['agent']['puppetcode'],
|
68
|
+
access_key_id: $config['agent']['access_key_id'],
|
69
|
+
secret_access_key: $config['agent']['secret_access_key'],
|
70
|
+
region: $config['agent']['region'],
|
71
|
+
proxy_uri: $config['agent']['proxy_uri'],
|
72
|
+
daemon_frequency: $config['agent']['daemon_frequency'],
|
73
|
+
daemon_minimal: $config['agent']['daemon_minimal']
|
77
74
|
}
|
78
75
|
|
79
76
|
# Generate template using ERB
|
80
77
|
begin
|
81
78
|
@contents = Erubis::Eruby.new(File.read("#{@template_dir}/#{template}.erb")).result(template_values)
|
82
|
-
rescue
|
83
|
-
$logger.error
|
79
|
+
rescue StandardError => e
|
80
|
+
$logger.error 'An unexpected error occured when trying to generate the bootstrap template'
|
84
81
|
raise e
|
85
82
|
end
|
86
|
-
|
87
83
|
end
|
88
84
|
|
89
85
|
def output_plain
|
90
86
|
# Do nothing clever, just output the template data.
|
91
|
-
puts
|
87
|
+
puts '-- Bootstrap Start --'
|
92
88
|
puts @contents
|
93
|
-
puts
|
89
|
+
puts '-- Bootstrap End --'
|
94
90
|
end
|
95
91
|
|
96
92
|
def output_base64
|
97
93
|
# Some providers like AWS can accept the data in Base64 version which is
|
98
94
|
# smaller and less likely to get messed up by copy and paste or weird
|
99
95
|
# formatting issues.
|
100
|
-
puts
|
96
|
+
puts '-- Bootstrap Start --'
|
101
97
|
puts Base64.encode64(@contents)
|
102
|
-
puts
|
98
|
+
puts '-- Bootstrap End --'
|
103
99
|
end
|
104
|
-
|
105
100
|
end
|
106
101
|
end
|
107
102
|
|
data/lib/pupistry/config.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
# rubocop:disable Style/Documentation, Style/GlobalVars
|
1
2
|
require 'rubygems'
|
2
3
|
require 'fileutils'
|
3
4
|
require 'tempfile'
|
4
5
|
require 'yaml'
|
6
|
+
require 'safe_yaml'
|
5
7
|
|
6
8
|
module Pupistry
|
7
9
|
# Pupistry::Config
|
@@ -10,50 +12,79 @@ module Pupistry
|
|
10
12
|
#
|
11
13
|
|
12
14
|
class Config
|
13
|
-
|
14
|
-
def self.load file
|
15
|
+
def self.load(file)
|
15
16
|
$logger.debug "Loading configuration file #{file}"
|
17
|
+
|
18
|
+
# Load YAML file with minimum safety/basic checks
|
19
|
+
unless File.exist?(file)
|
20
|
+
$logger.fatal 'The configuration file provided does not exist, or cannot be accessed'
|
21
|
+
exit 0
|
22
|
+
end
|
23
|
+
|
24
|
+
begin
|
25
|
+
$config = YAML.load(File.open(file), safe: true, raise_on_unknown_tag: true)
|
26
|
+
rescue => ex
|
27
|
+
$logger.fatal 'The supplied file is not a valid YAML configuration file'
|
28
|
+
$logger.debug ex.message
|
29
|
+
exit 0
|
30
|
+
end
|
31
|
+
|
16
32
|
|
17
|
-
|
18
|
-
|
33
|
+
# Run checks for minimum configuration parameters
|
34
|
+
# TODO: Is there a smarter way of doing this? Maybe a better config parser?
|
35
|
+
begin
|
36
|
+
fail 'Missing general:app_cache' unless defined? $config['general']['app_cache']
|
37
|
+
fail 'Missing general:s3_bucket' unless defined? $config['general']['s3_bucket']
|
38
|
+
fail 'Missing general:gpg_disable' unless defined? $config['general']['gpg_disable']
|
39
|
+
fail 'Missing agent:puppetcode' unless defined? $config['agent']['puppetcode']
|
40
|
+
rescue => ex
|
41
|
+
$logger.fatal 'The supplied configuration files doesn\'t include the minimum expect configuration parameters'
|
42
|
+
$logger.debug ex.message
|
19
43
|
exit 0
|
20
44
|
end
|
21
45
|
|
22
|
-
|
46
|
+
|
23
47
|
|
24
48
|
# Make sure cache directory exists, create it otherwise
|
25
|
-
$config[
|
49
|
+
$config['general']['app_cache'] = File.expand_path($config['general']['app_cache']).chomp('/')
|
26
50
|
|
27
|
-
unless Dir.
|
51
|
+
unless Dir.exist?($config['general']['app_cache'])
|
28
52
|
begin
|
29
|
-
FileUtils.mkdir_p($config[
|
30
|
-
FileUtils.chmod(0700, $config[
|
31
|
-
rescue
|
32
|
-
$logger.fatal "Unable to create cache directory at \"#{$config[
|
53
|
+
FileUtils.mkdir_p($config['general']['app_cache'])
|
54
|
+
FileUtils.chmod(0700, $config['general']['app_cache']) # Generally only the user running Pupistry should have access
|
55
|
+
rescue StandardError => e
|
56
|
+
$logger.fatal "Unable to create cache directory at \"#{$config['general']['app_cache']}\"."
|
33
57
|
raise e
|
34
58
|
end
|
35
59
|
end
|
36
60
|
|
37
61
|
# Write test file to confirm writability
|
38
62
|
begin
|
39
|
-
FileUtils.touch($config[
|
40
|
-
FileUtils.rm($config[
|
41
|
-
rescue
|
42
|
-
$logger.fatal "Unexpected exception when creating testfile in cache directory at \"#{$config[
|
63
|
+
FileUtils.touch($config['general']['app_cache'] + '/testfile')
|
64
|
+
FileUtils.rm($config['general']['app_cache'] + '/testfile')
|
65
|
+
rescue StandardError => e
|
66
|
+
$logger.fatal "Unexpected exception when creating testfile in cache directory at \"#{$config['general']['app_cache']}\", is the directory writable?"
|
43
67
|
raise e
|
44
68
|
end
|
45
69
|
|
70
|
+
|
71
|
+
# Check if Puppet is available
|
72
|
+
unless system('puppet --version 2>&1 > /dev/null')
|
73
|
+
$logger.fatal "Unable to find an installation of Puppet - please make sure Puppet is installed from either OS package or Gem"
|
74
|
+
exit 0
|
75
|
+
end
|
76
|
+
|
46
77
|
end
|
47
78
|
|
48
79
|
def self.find_and_load
|
49
|
-
$logger.debug
|
80
|
+
$logger.debug 'Looking for configuration file in common locations'
|
50
81
|
|
51
82
|
# If the HOME environmental hasn't been set (which can happen when
|
52
83
|
# running via some cloud user-data/init systems) the app will die
|
53
84
|
# horribly, we should set a HOME path default.
|
54
85
|
unless ENV['HOME']
|
55
|
-
$logger.warn
|
56
|
-
ENV['HOME'] =
|
86
|
+
$logger.warn 'No HOME environmental set, defaulting to /tmp'
|
87
|
+
ENV['HOME'] = '/tmp'
|
57
88
|
end
|
58
89
|
|
59
90
|
# Locations in order of preference:
|
@@ -64,29 +95,26 @@ module Pupistry
|
|
64
95
|
config = ''
|
65
96
|
local_dir = Dir.pwd
|
66
97
|
|
67
|
-
if File.
|
98
|
+
if File.exist?("#{local_dir}/settings.yaml")
|
68
99
|
config = "#{local_dir}/settings.yaml"
|
69
100
|
|
70
|
-
elsif File.
|
71
|
-
config = File.expand_path
|
101
|
+
elsif File.exist?(File.expand_path '~/.pupistry/settings.yaml')
|
102
|
+
config = File.expand_path '~/.pupistry/settings.yaml'
|
72
103
|
|
73
|
-
elsif File.
|
74
|
-
config =
|
104
|
+
elsif File.exist?('/usr/local/etc/pupistry/settings.yaml')
|
105
|
+
config = '/usr/local/etc/pupistry/settings.yaml'
|
75
106
|
|
76
|
-
elsif File.
|
77
|
-
config =
|
107
|
+
elsif File.exist?('/etc/pupistry/settings.yaml')
|
108
|
+
config = '/etc/pupistry/settings.yaml'
|
78
109
|
|
79
110
|
else
|
80
|
-
$logger.error
|
81
|
-
$logger.error
|
111
|
+
$logger.error 'No configuration file provided.'
|
112
|
+
$logger.error 'See pupistry help for information on configuration'
|
82
113
|
exit 0
|
83
114
|
end
|
84
115
|
|
85
|
-
|
86
|
-
|
116
|
+
load(config)
|
87
117
|
end
|
88
|
-
|
89
|
-
|
90
118
|
end
|
91
119
|
end
|
92
120
|
# vim:shiftwidth=2:tabstop=2:softtabstop=2:expandtab:smartindent
|
data/lib/pupistry/gpg.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
+
# rubocop:disable Style/Documentation, Style/GlobalVars
|
1
2
|
require 'rubygems'
|
2
3
|
require 'yaml'
|
4
|
+
require 'safe_yaml'
|
3
5
|
require 'fileutils'
|
4
6
|
require 'base64'
|
5
7
|
|
@@ -11,25 +13,22 @@ module Pupistry
|
|
11
13
|
attr_accessor :checksum
|
12
14
|
attr_accessor :signature
|
13
15
|
|
14
|
-
def initialize
|
15
|
-
|
16
|
+
def initialize(checksum)
|
16
17
|
# Need a checksum to do signing for
|
17
18
|
if checksum
|
18
19
|
@checksum = checksum
|
19
20
|
else
|
20
|
-
$logger.fatal
|
21
|
+
$logger.fatal 'Probable bug, need a checksum provided with GPG validation'
|
21
22
|
exit 0
|
22
23
|
end
|
23
24
|
|
24
25
|
# Make sure that we have GPG available
|
25
|
-
unless system(
|
26
|
+
unless system('gpg --version >> /dev/null 2>&1') # rubocop:disable Style/GuardClause
|
26
27
|
$logger.fatal "'gpg' command is not available, unable to do any signature creation or verification."
|
27
28
|
exit 0
|
28
29
|
end
|
29
|
-
|
30
30
|
end
|
31
31
|
|
32
|
-
|
33
32
|
# Sign the artifact and return the signature. Does not validation of the signature.
|
34
33
|
#
|
35
34
|
# false Failure
|
@@ -41,19 +40,17 @@ module Pupistry
|
|
41
40
|
# Clean up the existing signature file
|
42
41
|
signature_cleanup
|
43
42
|
|
44
|
-
|
45
|
-
Dir.chdir("#{$config["general"]["app_cache"]}/artifacts/") do
|
46
|
-
|
43
|
+
Dir.chdir("#{$config['general']['app_cache']}/artifacts/") do
|
47
44
|
# Generate the signature file and pick up the signature data
|
48
45
|
unless system "gpg --use-agent --detach-sign artifact.#{@checksum}.tar.gz"
|
49
|
-
$logger.error
|
46
|
+
$logger.error 'Unable to sign the artifact, an unexpected failure occured. No file uploaded.'
|
50
47
|
return false
|
51
48
|
end
|
52
49
|
|
53
|
-
if File.
|
54
|
-
$logger.info
|
50
|
+
if File.exist?("artifact.#{@checksum}.tar.gz.sig")
|
51
|
+
$logger.info 'A signature file was successfully generated.'
|
55
52
|
else
|
56
|
-
$logger.error
|
53
|
+
$logger.error 'A signature file was NOT generated.'
|
57
54
|
return false
|
58
55
|
end
|
59
56
|
|
@@ -61,43 +58,37 @@ module Pupistry
|
|
61
58
|
# metadata into a single file and extracting it out when needed, than
|
62
59
|
# having to keep track of yet-another-file. Because we encode into
|
63
60
|
# ASCII here, no need to call GPG with --armor either.
|
64
|
-
|
61
|
+
|
65
62
|
@signature = Base64.encode64(File.read("artifact.#{@checksum}.tar.gz.sig"))
|
66
63
|
|
67
64
|
unless @signature
|
68
|
-
$logger.error
|
65
|
+
$logger.error 'An unexpected issue occured and no signature was generated'
|
69
66
|
return false
|
70
67
|
end
|
71
68
|
end
|
72
69
|
|
73
|
-
|
74
70
|
# Make sure the public key has been uploaded if it hasn't already
|
75
71
|
pubkey_upload
|
76
72
|
|
77
|
-
|
73
|
+
@signature
|
78
74
|
end
|
79
75
|
|
80
|
-
|
81
76
|
# Verify the signature for a particular artifact.
|
82
77
|
#
|
83
78
|
# true Signature is legit
|
84
79
|
# false Signature is invalid (security issue!)
|
85
80
|
#
|
86
81
|
def artifact_verify
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
if File.exists?("artifact.#{@checksum}.tar.gz.sig")
|
91
|
-
$logger.debug "Signature already extracted on disk, running verify...."
|
82
|
+
Dir.chdir("#{$config['general']['app_cache']}/artifacts/") do
|
83
|
+
if File.exist?("artifact.#{@checksum}.tar.gz.sig")
|
84
|
+
$logger.debug 'Signature already extracted on disk, running verify....'
|
92
85
|
else
|
93
|
-
$logger.debug
|
86
|
+
$logger.debug 'Extracting signature from manifest data...'
|
94
87
|
signature_extract
|
95
88
|
end
|
96
89
|
|
97
90
|
# Verify the signature
|
98
|
-
unless
|
99
|
-
pubkey_install
|
100
|
-
end
|
91
|
+
pubkey_install unless pubkey_exist?
|
101
92
|
|
102
93
|
output_verify = `gpg --quiet --status-fd 1 --verify artifact.#{@checksum}.tar.gz.sig 2>&1`
|
103
94
|
|
@@ -106,9 +97,8 @@ module Pupistry
|
|
106
97
|
|
107
98
|
# Was it valid?
|
108
99
|
output_verify.each_line do |line|
|
109
|
-
|
110
100
|
if /\[GNUPG:\]\sGOODSIG\s[A-Z0-9]*#{$config["general"]["gpg_signing_key"]}\s/.match(line)
|
111
|
-
$logger.info "Artifact #{@checksum} has a valid signature belonging to #{$config[
|
101
|
+
$logger.info "Artifact #{@checksum} has a valid signature belonging to #{$config['general']['gpg_signing_key']}"
|
112
102
|
return true
|
113
103
|
end
|
114
104
|
|
@@ -116,32 +106,27 @@ module Pupistry
|
|
116
106
|
$logger.fatal "Artifact #{@checksum} has AN INVALID GPG SECURITY SIGNATURE and could be CORRUPT or TAMPERED with."
|
117
107
|
exit 0
|
118
108
|
end
|
119
|
-
|
120
109
|
end
|
121
110
|
|
122
111
|
# Unexpected error
|
123
|
-
$logger.error
|
112
|
+
$logger.error 'An unexpected validation issue occured, see below debug information:'
|
124
113
|
|
125
114
|
output_verify.each_line do |line|
|
126
115
|
$logger.error "GPG: #{line}"
|
127
116
|
end
|
128
|
-
|
129
117
|
end
|
130
118
|
|
131
119
|
# Something went wrong
|
132
120
|
$logger.fatal "Artifact #{@checksum} COULD NOT BE GPG VALIDATED and could be CORRUPT or TAMPERED with."
|
133
121
|
exit 0
|
134
|
-
|
135
122
|
end
|
136
123
|
|
137
|
-
|
138
124
|
# Generally we should clean up old signature files before and after using them
|
139
125
|
#
|
140
126
|
def signature_cleanup
|
141
|
-
FileUtils.rm("#{$config[
|
127
|
+
FileUtils.rm("#{$config['general']['app_cache']}/artifacts/artifact.#{@checksum}.tar.gz.sig", force: true)
|
142
128
|
end
|
143
129
|
|
144
|
-
|
145
130
|
# Extract the signature from the manifest file and write it to file in native binary format.
|
146
131
|
#
|
147
132
|
# false Unable to extract
|
@@ -149,103 +134,90 @@ module Pupistry
|
|
149
134
|
# base64 Encoded signature
|
150
135
|
#
|
151
136
|
def signature_extract
|
152
|
-
|
153
|
-
manifest = YAML::load(File.open($config["general"]["app_cache"] + "/artifacts/manifest.#{@checksum}.yaml"))
|
154
|
-
|
155
|
-
if manifest['gpgsig']
|
156
|
-
# We have the base64 version
|
157
|
-
@signature = manifest['gpgsig']
|
137
|
+
manifest = YAML.load(File.open($config['general']['app_cache'] + "/artifacts/manifest.#{@checksum}.yaml"), safe: true, raise_on_unknown_tag: true)
|
158
138
|
|
159
|
-
|
160
|
-
|
139
|
+
if manifest['gpgsig']
|
140
|
+
# We have the base64 version
|
141
|
+
@signature = manifest['gpgsig']
|
161
142
|
|
162
|
-
|
163
|
-
|
164
|
-
return false
|
165
|
-
end
|
143
|
+
# Decode the base64 and write the signature file
|
144
|
+
File.write("#{$config['general']['app_cache']}/artifacts/artifact.#{@checksum}.tar.gz.sig", Base64.decode64(@signature))
|
166
145
|
|
167
|
-
|
168
|
-
|
169
|
-
|
146
|
+
return @signature
|
147
|
+
else
|
148
|
+
return false
|
170
149
|
end
|
171
150
|
|
151
|
+
rescue StandardError => e
|
152
|
+
$logger.error 'Something unexpected occured when reading the manifest file'
|
153
|
+
raise e
|
172
154
|
end
|
173
155
|
|
174
|
-
|
175
156
|
# Save the signature into the manifest file
|
176
157
|
#
|
177
158
|
def signature_save
|
178
|
-
|
179
|
-
|
180
|
-
manifest['gpgsig'] = @signature
|
181
|
-
|
182
|
-
File.open("#{$config["general"]["app_cache"]}/artifacts/manifest.#{@checksum}.yaml",'w') do |fh|
|
183
|
-
fh.write YAML::dump(manifest)
|
184
|
-
end
|
159
|
+
manifest = YAML.load(File.open($config['general']['app_cache'] + "/artifacts/manifest.#{@checksum}.yaml"), safe: true, raise_on_unknown_tag: true)
|
160
|
+
manifest['gpgsig'] = @signature
|
185
161
|
|
186
|
-
|
187
|
-
|
188
|
-
rescue Exception => e
|
189
|
-
$logger.error "Something unexpected occured when updating the manifest file with GPG signature"
|
190
|
-
return false
|
162
|
+
File.open("#{$config['general']['app_cache']}/artifacts/manifest.#{@checksum}.yaml", 'w') do |fh|
|
163
|
+
fh.write YAML.dump(manifest)
|
191
164
|
end
|
192
165
|
|
193
|
-
|
166
|
+
return true
|
194
167
|
|
168
|
+
rescue StandardError
|
169
|
+
$logger.error 'Something unexpected occured when updating the manifest file with GPG signature'
|
170
|
+
return false
|
171
|
+
end
|
195
172
|
|
196
173
|
# Check if the public key is installed on this machine?
|
197
174
|
#
|
198
|
-
def
|
199
|
-
|
175
|
+
def pubkey_exist?
|
200
176
|
# We prefix with 0x to avoid matching on strings in key names
|
201
|
-
if system "gpg --status-fd a --list-keys 0x#{$config[
|
202
|
-
$logger.debug
|
177
|
+
if system "gpg --status-fd a --list-keys 0x#{$config['general']['gpg_signing_key']} 2>&1 >> /dev/null"
|
178
|
+
$logger.debug 'Public key exists on this system'
|
203
179
|
return true
|
204
180
|
else
|
205
|
-
$logger.debug
|
181
|
+
$logger.debug 'Public key does not exist on this system'
|
206
182
|
return false
|
207
183
|
end
|
208
184
|
end
|
209
|
-
|
210
185
|
|
211
186
|
# Extract & upload the public key to the s3 bucket for other users
|
212
187
|
#
|
213
188
|
def pubkey_upload
|
214
|
-
unless File.
|
189
|
+
unless File.exist?("#{$config['general']['app_cache']}/artifacts/#{$config['general']['gpg_signing_key']}.publickey")
|
215
190
|
|
216
191
|
# GPG key does not exist locally, we therefore assume it's not in the S3
|
217
192
|
# bucket either, so we should export out and upload. Technically this may
|
218
193
|
# result in a few extra uploads (once for any new machine using Pupistry)
|
219
194
|
# but it doesn't cause any issue and saves me writing more code ;-)
|
220
|
-
|
221
|
-
$logger.info "Exporting GPG key #{$config[
|
195
|
+
|
196
|
+
$logger.info "Exporting GPG key #{$config['general']['gpg_signing_key']} and uploading to S3 bucket..."
|
222
197
|
|
223
198
|
# If it doesn't exist on this machine, then we're a bit stuck!
|
224
|
-
unless
|
225
|
-
$logger.error "The public key #{$config[
|
199
|
+
unless pubkey_exist?
|
200
|
+
$logger.error "The public key #{$config['general']['gpg_signing_key']} does not exist on this system, so unable to export it out"
|
226
201
|
return false
|
227
202
|
end
|
228
203
|
|
229
204
|
# Export out key
|
230
|
-
unless system "gpg --export --armour 0x#{$config[
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
205
|
+
unless system "gpg --export --armour 0x#{$config['general']['gpg_signing_key']} > #{$config['general']['app_cache']}/artifacts/#{$config['general']['gpg_signing_key']}.publickey"
|
206
|
+
$logger.error 'A fault occured when trying to export the GPG key'
|
207
|
+
return false
|
208
|
+
end
|
235
209
|
|
236
210
|
# Upload
|
237
|
-
s3 = Pupistry::
|
211
|
+
s3 = Pupistry::StorageAWS.new 'build'
|
238
212
|
|
239
|
-
unless s3.upload "#{$config[
|
240
|
-
$logger.error
|
213
|
+
unless s3.upload "#{$config['general']['app_cache']}/artifacts/#{$config['general']['gpg_signing_key']}.publickey", "#{$config['general']['gpg_signing_key']}.publickey"
|
214
|
+
$logger.error 'Unable to upload GPG key to S3 bucket'
|
241
215
|
return false
|
242
216
|
end
|
243
217
|
|
244
218
|
end
|
245
|
-
|
246
219
|
end
|
247
220
|
|
248
|
-
|
249
221
|
# Install the public key. This is a potential avenue for exploit, if a
|
250
222
|
# machine is being built for the first time, it has no existing trust of
|
251
223
|
# the GPG key, other than transit encryption to the S3 bucket. To protect
|
@@ -256,28 +228,25 @@ module Pupistry
|
|
256
228
|
# the GPG public key for them direct from the S3 repo.
|
257
229
|
#
|
258
230
|
def pubkey_install
|
259
|
-
|
260
|
-
$logger.warn "Installing GPG key #{$config["general"]["gpg_signing_key"]}..."
|
231
|
+
$logger.warn "Installing GPG key #{$config['general']['gpg_signing_key']}..."
|
261
232
|
|
262
|
-
|
233
|
+
s3 = Pupistry::StorageAWS.new 'agent'
|
263
234
|
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
unless system "gpg --import < #{$config["general"]["app_cache"]}/artifacts/#{$config["general"]["gpg_signing_key"]}.publickey > /dev/null 2>&1"
|
270
|
-
$logger.error "A fault occured when trying to import the GPG key"
|
271
|
-
return false
|
272
|
-
end
|
235
|
+
unless s3.download "#{$config['general']['gpg_signing_key']}.publickey", "#{$config['general']['app_cache']}/artifacts/#{$config['general']['gpg_signing_key']}.publickey"
|
236
|
+
$logger.error 'Unable to download GPG key from S3 bucket, this will prevent validation of signature'
|
237
|
+
return false
|
238
|
+
end
|
273
239
|
|
274
|
-
|
275
|
-
$logger.error
|
240
|
+
unless system "gpg --import < #{$config['general']['app_cache']}/artifacts/#{$config['general']['gpg_signing_key']}.publickey > /dev/null 2>&1"
|
241
|
+
$logger.error 'A fault occured when trying to import the GPG key'
|
276
242
|
return false
|
277
243
|
end
|
278
|
-
end
|
279
244
|
|
280
|
-
|
245
|
+
rescue StandardError
|
246
|
+
$logger.error 'Something unexpected occured when installing the GPG public key'
|
247
|
+
return false
|
248
|
+
end
|
249
|
+
end
|
281
250
|
end
|
282
251
|
|
283
252
|
# vim:shiftwidth=2:tabstop=2:softtabstop=2:expandtab:smartindent
|