1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
|
##
# Signing plugin for hoe.
#
# === Tasks Provided:
#
# generate_key:: Generate a key for signing your gems.
#
# === Extra Configuration Options:
#
# signing_key_file:: Signs your gems with this private key.
# signing_cert_file:: Signs your gem with this certificate.
#
# === Usage:
#
# Run the 'generate_key' task. This will:
#
# 1. Configure your ~/.hoerc.
# 2. Generate a signing key and certificate.
# 3. Install the private key and public certificate files into ~/.gem.
#
# Hoe will now generate signed gems when the package task is run. If you have
# multiple machines you build gems on, be sure to install your key and
# certificate on each machine.
#
# Keep your private key secret! Keep your private key safe!
#
# To make sure your gems are signed run:
#
# rake package; tar tf pkg/yourproject-1.2.3.gem
#
# If your gem is signed you will see:
#
# data.tar.gz
# data.tar.gz.sig
# metadata.gz
# metadata.gz.sig
module Hoe::Signing
Hoe::DEFAULT_CONFIG["signing_key_file"] = "~/.gem/gem-private_key.pem"
Hoe::DEFAULT_CONFIG["signing_cert_file"] = "~/.gem/gem-public_cert.pem"
##
# Define tasks for plugin.
def define_signing_tasks
set_up_signing
desc "Generate a key for signing your gems."
task :generate_key do
generate_key_task
end
desc "Check pubilc key for signing your gems."
task :check_key do
check_key_task
end
rescue NameError
warn "Couldn't set up signing (openssl error?). Skipping."
end
def set_up_signing # :nodoc:
signing_key = nil
cert_chain = []
with_config do |config, _path|
break unless config["signing_key_file"] and config["signing_cert_file"]
key_file = File.expand_path config["signing_key_file"].to_s
signing_key = key_file if File.exist? key_file
cert_file = File.expand_path config["signing_cert_file"].to_s
cert_chain << cert_file if File.exist? cert_file
end
if signing_key and cert_chain then
passphrase = ENV['GEM_PRIVATE_KEY_PASSPHRASE']
spec.signing_key = OpenSSL::PKey::RSA.new(File.read(signing_key), passphrase)
spec.cert_chain = cert_chain
end
end
def check_key_task # :nodoc:
with_config do |config, _path|
break unless config["signing_cert_file"]
pub_key = File.expand_path config["signing_cert_file"].to_s
c = OpenSSL::X509::Certificate.new File.read pub_key
t = c.not_after
if t < Time.now then
warn "Gem signing certificate has expired"
else
warn "Gem signing certificate has NOT expired. Carry on."
end
end
end
def generate_key_task # :nodoc:
email = Array(spec.email)
abort "No email in your gemspec" if email.nil? or email.empty?
key_file = with_config { |config, _| config["signing_key_file"] }
cert_file = with_config { |config, _| config["signing_cert_file"] }
if key_file.nil? or cert_file.nil? then
ENV["SHOW_EDITOR"] ||= "no"
Rake::Task["config_hoe"].invoke
key_file = with_config { |config, _| config["signing_key_file"] }
cert_file = with_config { |config, _| config["signing_cert_file"] }
end
key_file = File.expand_path key_file
cert_file = File.expand_path cert_file
unless File.exist? key_file then
puts "Generating certificate"
if File.exist? key_file then
abort "Have #{key_file} but no #{cert_file}, aborting as a precaution"
end
warn "NOTICE: using #{email.first} for certificate" if email.size > 1
sh "gem cert --build #{email.first}"
mv "gem-private_key.pem", key_file, :verbose => true
mv "gem-public_cert.pem", cert_file, :verbose => true
puts "Installed key and certificate."
end
puts "Key file = #{key_file}"
puts "Cert file = #{cert_file}"
puts
puts "Until rubygems.org has a better strategy for signing, that's"
puts "the best we can do at this point."
end
end
|