Class: Gem::Commands::CertCommand
- Inherits:
-
Gem::Command
- Object
- Gem::Command
- Gem::Commands::CertCommand
- Defined in:
- lib/rubygems/commands/cert_command.rb
Instance Attribute Summary
Attributes inherited from Gem::Command
#command, #defaults, #options, #program_name, #summary
Instance Method Summary collapse
-
#add_certificate(certificate) ⇒ Object
:nodoc:.
- #build(email) ⇒ Object
-
#build_cert(email, key) ⇒ Object
:nodoc:.
-
#build_key ⇒ Object
:nodoc:.
- #certificates_matching(filter) ⇒ Object
- #check_openssl ⇒ Object
-
#description ⇒ Object
:nodoc:.
- #execute ⇒ Object
-
#initialize ⇒ CertCommand
constructor
A new instance of CertCommand.
-
#list_certificates_matching(filter) ⇒ Object
:nodoc:.
- #load_default_cert ⇒ Object
- #load_default_key ⇒ Object
-
#load_defaults ⇒ Object
:nodoc:.
- #open_cert(certificate_file) ⇒ Object
- #open_private_key(key_file) ⇒ Object
- #re_sign_cert(cert, cert_path, private_key) ⇒ Object
-
#remove_certificates_matching(filter) ⇒ Object
:nodoc:.
- #sign(cert_file) ⇒ Object
-
#sign_certificates ⇒ Object
:nodoc:.
Methods inherited from Gem::Command
add_common_option, #add_extra_args, #add_option, add_specific_extra_args, #arguments, #begins?, build_args, build_args=, #check_deprecated_options, common_options, #defaults_str, #deprecate_option, #deprecated?, extra_args, extra_args=, #extract_gem_name_and_version, #get_all_gem_names, #get_all_gem_names_and_versions, #get_one_gem_name, #get_one_optional_argument, #handle_options, #handles?, #invoke, #invoke_with_build_args, #merge_options, #remove_option, #show_help, #show_lookup_failure, specific_extra_args, specific_extra_args_hash, #usage, #when_invoked
Methods included from UserInteraction
#alert, #alert_error, #alert_warning, #ask, #ask_for_password, #ask_yes_no, #choose_from_list, #say, #terminate_interaction, #verbose
Methods included from DefaultUserInteraction
ui, #ui, ui=, #ui=, use_ui, #use_ui
Methods included from Text
#clean_text, #format_text, #levenshtein_distance, #min3, #truncate_text
Constructor Details
#initialize ⇒ CertCommand
Returns a new instance of CertCommand.
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 |
# File 'lib/rubygems/commands/cert_command.rb', line 7 def initialize super "cert", "Manage RubyGems certificates and signing settings", add: [], remove: [], list: [], build: [], sign: [] add_option("-a", "--add CERT", "Add a trusted certificate.") do |cert_file, | [:add] << open_cert(cert_file) end add_option("-l", "--list [FILTER]", "List trusted certificates where the", "subject contains FILTER") do |filter, | filter ||= "" [:list] << filter end add_option("-r", "--remove FILTER", "Remove trusted certificates where the", "subject contains FILTER") do |filter, | [:remove] << filter end add_option("-b", "--build EMAIL_ADDR", "Build private key and self-signed", "certificate for EMAIL_ADDR") do |email_address, | [:build] << email_address end add_option("-C", "--certificate CERT", "Signing certificate for --sign") do |cert_file, | [:issuer_cert] = open_cert(cert_file) [:issuer_cert_file] = cert_file end add_option("-K", "--private-key KEY", "Key for --sign or --build") do |key_file, | [:key] = open_private_key(key_file) end add_option("-A", "--key-algorithm ALGORITHM", "Select which key algorithm to use for --build") do |algorithm, | [:key_algorithm] = algorithm end add_option("-s", "--sign CERT", "Signs CERT with the key from -K", "and the certificate from -C") do |cert_file, | raise Gem::OptionParser::InvalidArgument, "#{cert_file}: does not exist" unless File.file? cert_file [:sign] << cert_file end add_option("-d", "--days NUMBER_OF_DAYS", "Days before the certificate expires") do |days, | [:expiration_length_days] = days.to_i end add_option("-R", "--re-sign", "Re-signs the certificate from -C with the key from -K") do |resign, | [:resign] = resign end end |
Instance Method Details
#add_certificate(certificate) ⇒ Object
:nodoc:
72 73 74 75 76 |
# File 'lib/rubygems/commands/cert_command.rb', line 72 def add_certificate(certificate) # :nodoc: Gem::Security.trust_dir.trust_cert certificate say "Added '#{certificate.subject}'" end |
#build(email) ⇒ Object
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/rubygems/commands/cert_command.rb', line 138 def build(email) unless valid_email?(email) raise Gem::CommandLineError, "Invalid email address #{email}" end key, key_path = build_key cert_path = build_cert email, key say "Certificate: #{cert_path}" if key_path say "Private Key: #{key_path}" say "Don't forget to move the key file to somewhere private!" end end |
#build_cert(email, key) ⇒ Object
:nodoc:
154 155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/rubygems/commands/cert_command.rb', line 154 def build_cert(email, key) # :nodoc: expiration_length_days = [:expiration_length_days] || Gem.configuration.cert_expiration_length_days cert = Gem::Security.create_cert_email( email, key, (Gem::Security::ONE_DAY * expiration_length_days) ) Gem::Security.write cert, "gem-public_cert.pem" end |
#build_key ⇒ Object
:nodoc:
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/rubygems/commands/cert_command.rb', line 167 def build_key # :nodoc: return [:key] if [:key] passphrase = ask_for_password "Passphrase for your Private Key:" say "\n" passphrase_confirmation = ask_for_password "Please repeat the passphrase for your Private Key:" say "\n" raise Gem::CommandLineError, "Passphrase and passphrase confirmation don't match" unless passphrase == passphrase_confirmation algorithm = [:key_algorithm] || Gem::Security::DEFAULT_KEY_ALGORITHM key = Gem::Security.create_key(algorithm) key_path = Gem::Security.write key, "gem-private_key.pem", 0o600, passphrase [key, key_path] end |
#certificates_matching(filter) ⇒ Object
186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/rubygems/commands/cert_command.rb', line 186 def certificates_matching(filter) return enum_for __method__, filter unless block_given? Gem::Security.trusted_certificates.select do |certificate, _| subject = certificate.subject.to_s subject.downcase.index filter end.sort_by do |certificate, _| certificate.subject.to_a.map {|name, data,| [name, data] } end.each do |certificate, path| yield certificate, path end end |
#check_openssl ⇒ Object
78 79 80 81 82 83 |
# File 'lib/rubygems/commands/cert_command.rb', line 78 def check_openssl return if Gem::HAVE_OPENSSL alert_error "OpenSSL library is required for the cert command" terminate_interaction 1 end |
#description ⇒ Object
:nodoc:
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/rubygems/commands/cert_command.rb', line 199 def description # :nodoc: <<-EOF The cert command manages signing keys and certificates for creating signed gems. Your signing certificate and private key are typically stored in ~/.gem/gem-public_cert.pem and ~/.gem/gem-private_key.pem respectively. To build a certificate for signing gems: gem cert --build you@example If you already have an RSA key, or are creating a new certificate for an existing key: gem cert --build you@example --private-key /path/to/key.pem If you wish to trust a certificate you can add it to the trust list with: gem cert --add /path/to/cert.pem You can list trusted certificates with: gem cert --list or: gem cert --list cert_subject_substring If you wish to remove a previously trusted certificate: gem cert --remove cert_subject_substring To sign another gem author's certificate: gem cert --sign /path/to/other_cert.pem For further reading on signing gems see `ri Gem::Security`. EOF end |
#execute ⇒ Object
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 |
# File 'lib/rubygems/commands/cert_command.rb', line 108 def execute check_openssl [:add].each do |certificate| add_certificate certificate end [:remove].each do |filter| remove_certificates_matching filter end [:list].each do |filter| list_certificates_matching filter end [:build].each do |email| build email end if [:resign] re_sign_cert( [:issuer_cert], [:issuer_cert_file], [:key] ) end sign_certificates unless [:sign].empty? end |
#list_certificates_matching(filter) ⇒ Object
:nodoc:
238 239 240 241 242 243 |
# File 'lib/rubygems/commands/cert_command.rb', line 238 def list_certificates_matching(filter) # :nodoc: certificates_matching filter do |certificate, _| # this could probably be formatted more gracefully say certificate.subject.to_s end end |
#load_default_cert ⇒ Object
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/rubygems/commands/cert_command.rb', line 245 def load_default_cert cert_file = File.join Gem.default_cert_path cert = File.read cert_file [:issuer_cert] = OpenSSL::X509::Certificate.new cert rescue Errno::ENOENT alert_error \ "--certificate not specified and ~/.gem/gem-public_cert.pem does not exist" terminate_interaction 1 rescue OpenSSL::X509::CertificateError alert_error \ "--certificate not specified and ~/.gem/gem-public_cert.pem is not valid" terminate_interaction 1 end |
#load_default_key ⇒ Object
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 |
# File 'lib/rubygems/commands/cert_command.rb', line 261 def load_default_key key_file = File.join Gem.default_key_path key = File.read key_file passphrase = ENV["GEM_PRIVATE_KEY_PASSPHRASE"] [:key] = OpenSSL::PKey.read key, passphrase rescue Errno::ENOENT alert_error \ "--private-key not specified and ~/.gem/gem-private_key.pem does not exist" terminate_interaction 1 rescue OpenSSL::PKey::PKeyError alert_error \ "--private-key not specified and ~/.gem/gem-private_key.pem is not valid" terminate_interaction 1 end |
#load_defaults ⇒ Object
:nodoc:
278 279 280 281 |
# File 'lib/rubygems/commands/cert_command.rb', line 278 def load_defaults # :nodoc: load_default_cert unless [:issuer_cert] load_default_key unless [:key] end |
#open_cert(certificate_file) ⇒ Object
85 86 87 88 89 90 91 92 93 |
# File 'lib/rubygems/commands/cert_command.rb', line 85 def open_cert(certificate_file) check_openssl OpenSSL::X509::Certificate.new File.read certificate_file rescue Errno::ENOENT raise Gem::OptionParser::InvalidArgument, "#{certificate_file}: does not exist" rescue OpenSSL::X509::CertificateError raise Gem::OptionParser::InvalidArgument, "#{certificate_file}: invalid X509 certificate" end |
#open_private_key(key_file) ⇒ Object
95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/rubygems/commands/cert_command.rb', line 95 def open_private_key(key_file) check_openssl passphrase = ENV["GEM_PRIVATE_KEY_PASSPHRASE"] key = OpenSSL::PKey.read File.read(key_file), passphrase raise Gem::OptionParser::InvalidArgument, "#{key_file}: private key not found" unless key.private? key rescue Errno::ENOENT raise Gem::OptionParser::InvalidArgument, "#{key_file}: does not exist" rescue OpenSSL::PKey::PKeyError, ArgumentError raise Gem::OptionParser::InvalidArgument, "#{key_file}: invalid RSA, DSA, or EC key" end |
#re_sign_cert(cert, cert_path, private_key) ⇒ Object
312 313 314 315 316 317 |
# File 'lib/rubygems/commands/cert_command.rb', line 312 def re_sign_cert(cert, cert_path, private_key) Gem::Security::Signer.re_sign_cert(cert, cert_path, private_key) do |expired_cert_path, new_expired_cert_path| alert("Your certificate #{expired_cert_path} has been re-signed") alert("Your expired certificate will be located at: #{new_expired_cert_path}") end end |
#remove_certificates_matching(filter) ⇒ Object
:nodoc:
283 284 285 286 287 288 |
# File 'lib/rubygems/commands/cert_command.rb', line 283 def remove_certificates_matching(filter) # :nodoc: certificates_matching filter do |certificate, path| FileUtils.rm path say "Removed '#{certificate.subject}'" end end |
#sign(cert_file) ⇒ Object
290 291 292 293 294 295 296 297 298 299 300 301 302 |
# File 'lib/rubygems/commands/cert_command.rb', line 290 def sign(cert_file) cert = File.read cert_file cert = OpenSSL::X509::Certificate.new cert = File.stat(cert_file).mode & 0o777 issuer_cert = [:issuer_cert] issuer_key = [:key] cert = Gem::Security.sign cert, issuer_key, issuer_cert Gem::Security.write cert, cert_file, end |
#sign_certificates ⇒ Object
:nodoc:
304 305 306 307 308 309 310 |
# File 'lib/rubygems/commands/cert_command.rb', line 304 def sign_certificates # :nodoc: load_defaults unless [:sign].empty? [:sign].each do |cert_file| sign cert_file end end |