lecli 0.2.2 → 0.2.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4808b041d83a611a2a5b133ab485d3e59aabfaaf
4
- data.tar.gz: b5781570c2e72e9bf34f4649e32ac77a0d206256
3
+ metadata.gz: da9e05e9c2100f24c17b18b0102812c9a1ef4de5
4
+ data.tar.gz: 0ded86f70fab0543811022364e58f83b30114df7
5
5
  SHA512:
6
- metadata.gz: cba07c13f72fd47dcde7b9dd3a73300ea37cda6ba249ee4fc87b73a1cdc2e3f3bfc8669d6812d63835b06d384f4f7ca213d0119afb3d451120b1703f29554d20
7
- data.tar.gz: 06a9eea65ae077421593d8414208b4c68a2bd0c1be656ad15c430cbfa782349692ef23493cc9074bfb2f6c0c6a287dc56ff967c7fa2e3a589ef579e2800b1861
6
+ metadata.gz: 94b3f4c61d97431798588137ff64b0a48fba6f906e07396e1908428af9e46f0c883f950d759de42f451b8f51c19eb21100e3d02a8a2698b5ed32fcc8505734af
7
+ data.tar.gz: 2b9669dded2a38d7bfceb0b6b5f9bffcf806908ed7b4d303815f2d4407734c203a9234a8a7d2f7c0678acefe87492a16beec8445d9499e27dfd418a5c582c6f6
data/.gitignore CHANGED
@@ -9,3 +9,5 @@
9
9
 
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
+
13
+ .lecli.yml
@@ -0,0 +1,13 @@
1
+ Metrics/MethodLength:
2
+ Max: 20
3
+ Metrics/ClassLength:
4
+ Max: 150
5
+ Metrics/BlockLength:
6
+ Exclude:
7
+ - 'Rakefile'
8
+ - '**/*.rake'
9
+ - 'spec/**/*.rb'
10
+ Style/ExpandPathArguments:
11
+ Enabled: false
12
+ Style/WordArray:
13
+ Enabled: false
@@ -1,5 +1,10 @@
1
+ dist: trusty
1
2
  sudo: false
2
3
  language: ruby
3
4
  rvm:
5
+ - 2.3.1
4
6
  - 2.4.2
7
+ - 2.5.1
5
8
  before_install: gem install bundler -v 1.16.0
9
+ script:
10
+ - bundle exec rake spec
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
- source "https://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
- git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
3
+ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in lecli.gemspec
6
6
  gemspec
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- lecli (0.2.2)
4
+ lecli (0.2.4)
5
5
  acme-client (~> 2.0.0)
6
6
  thor (~> 0.20.0)
7
7
 
@@ -11,8 +11,10 @@ GEM
11
11
  acme-client (2.0.0)
12
12
  faraday (~> 0.9, >= 0.9.1)
13
13
  diff-lcs (1.3)
14
+ docile (1.3.1)
14
15
  faraday (0.15.2)
15
16
  multipart-post (>= 1.2, < 3)
17
+ json (2.1.0)
16
18
  multipart-post (2.0.0)
17
19
  rake (10.5.0)
18
20
  rspec (3.7.0)
@@ -28,6 +30,11 @@ GEM
28
30
  diff-lcs (>= 1.2.0, < 2.0)
29
31
  rspec-support (~> 3.7.0)
30
32
  rspec-support (3.7.1)
33
+ simplecov (0.16.1)
34
+ docile (~> 1.1)
35
+ json (>= 1.8, < 3)
36
+ simplecov-html (~> 0.10.0)
37
+ simplecov-html (0.10.2)
31
38
  thor (0.20.0)
32
39
 
33
40
  PLATFORMS
@@ -38,6 +45,7 @@ DEPENDENCIES
38
45
  lecli!
39
46
  rake (~> 10.0)
40
47
  rspec (~> 3.0)
48
+ simplecov (~> 0.16.1)
41
49
 
42
50
  BUNDLED WITH
43
51
  1.16.0
data/README.md CHANGED
@@ -1,38 +1,92 @@
1
- # Lecli
1
+ # lecli
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/lecli`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ lecli is a gem that provides a CLI to generate Let's Encrypt certificates. It wraps around the [ACME protocol Client gem](https://github.com/unixcharles/acme-client). It pairs well with cron jobs and the [whenever gem](https://github.com/javan/whenever) for a tighter grip on automation/scripting customization.
6
4
 
7
5
  ## Installation
8
6
 
9
- Add this line to your application's Gemfile:
7
+ $ gem install lecli
8
+
9
+ ## Getting started
10
+
11
+ The CLI will use the Let's Encrypt staging endpoint unless explicitly passed with the `--production` flag. All other configuration data is managed by a config file - `.lecli.yml`. To help understand the available options you can run the following in your terminal and a sample YAML file will be generated for you
10
12
 
11
- ```ruby
12
- gem 'lecli'
13
+ ```
14
+ $ lecli yaml
13
15
  ```
14
16
 
15
- And then execute:
17
+ Now let's see what's inside
16
18
 
17
- $ bundle
19
+ ### `lecli.yml`
18
20
 
19
- Or install it yourself as:
21
+ ```
22
+ ---
23
+ domains:
24
+ - example.com
25
+ common_name: Let's Encrypt
26
+ account_email: test@account.com
27
+ request_key: request.pem
28
+ certificate_key: certificate.pem
29
+ challenges_relative_path: challenges
30
+ success_callback_script: deploy.sh
31
+ ```
20
32
 
21
- $ gem install lecli
33
+ Most entries are optional, except those that specify the domains you are requesting and "identity fields". Meaning that at least **domains** (list of entries), **common_name** and **account_email** should always appear in order to perform a valid request.
22
34
 
23
- ## Usage
35
+ ### The flow
24
36
 
25
- TODO: Write usage instructions here
37
+ From the two available types of validation requests only HTTP (and not DNS) is supported [yet](#contributing). This means you'll need to serve a token (lecli will create them) behind each domain in the **list of domain addresses** requested, on a certain **port**.
26
38
 
27
- ## Development
39
+ The tokens are written to a single **challenges_relative_path** and need to be served behind each domain you are requesting, i.e. `example.com/.well-known/acme-challenge/#{token_filename}`. If requesting multiple domains at once you will need additional setup to route from each domain requested to where the tokens are persisted. When working with a single domain, for example, you can just make this relative path write the tokens on `/usr/share/nginx/html/.well-known/acme-challenge/` if working with an nginx server.
40
+
41
+ ![alt text](https://github.com/fdoxyz/lecli/blob/master/lecli_diagram.png)
42
+
43
+ After Let's Encrypt is able to access both tokens on the list of domain addresses requested the certificates can be issued. The resulting certificate will be identified by the **email** and under the **common_name** provided. The name of the `.pem` files can be customized with **request_key** and **certificate_key**.
44
+
45
+ Optionally you can specify a script filename with **success_callback_script**. This script will function as a "callback hook" and it will be run after successfully exporting the domains' certificate.
46
+
47
+ In this section you've read about all `lecli.yml` options available (keywords in **bold**). Now, if you've made sure you: (1) Customized the options in this file to create the desired certificate, and (2) made sure the **success_callback_script** path is available for a public internet. You are now ready to kick off the validation process by executing the following on your terminal
48
+
49
+ ```
50
+ lecli generate
51
+ ```
28
52
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
53
+ ### Making use of the result Certificates
30
54
 
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
55
+ A simple example `nginx.conf` excerpt to make use of the result certificates could be the following
56
+
57
+ ```
58
+ server {
59
+ listen 443 ssl;
60
+ server_name example.com;
61
+
62
+ ssl_certificate /etc/nginx/ssl/request.pem;
63
+ ssl_certificate_key /etc/nginx/ssl/certificate.pem;
64
+
65
+ ...
66
+ }
67
+ ```
68
+
69
+ You can script a server restart if needed, or any other setup that you require to make use of the newly created certificates. Just make sure to point the **success_callback_script** path in your config file so the CLI can automatically execute it if the request result was success.
70
+
71
+ If you pair the CLI with a cron-job (specially using the [whenever](https://github.com/javan/whenever) gem) you've essentially put together a Let's Encrypt bot and can now leverage scripting for complex deployments. Your certificates will be renewed periodically. When using **whenever** you'll have lecli CLI in your crontab as easy as:
72
+
73
+ ```
74
+ every :month, at: '4am' do
75
+ command "lecli --production -f /path/to/config/file.yml"
76
+ end
77
+ ```
78
+
79
+ Be sure to run `lecli help` for more details.
80
+
81
+ ## Development
82
+
83
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `bundle exec rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. To install this gem onto your local machine, run `bundle exec rake install`.
32
84
 
33
85
  ## Contributing
34
86
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/lecli.
87
+ Bug reports and pull requests are welcome on GitHub at https://github.com/fdoxyz/lecli.
88
+
89
+ Please include tests if new features are added and make sure rubocop styling guide is met.
36
90
 
37
91
  ## License
38
92
 
data/Rakefile CHANGED
@@ -1,6 +1,6 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
3
 
4
4
  RSpec::Core::RakeTask.new(:spec)
5
5
 
6
- task :default => :spec
6
+ task default: :spec
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "bundler/setup"
4
- require "lecli"
3
+ require 'bundler/setup'
4
+ require 'lecli'
5
5
 
6
6
  # You can add fixtures and/or initialization code here to make experimenting
7
7
  # with your gem easier. You can also use a different console, if you like.
8
8
 
9
9
  # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
10
+ # require 'pry'
11
11
  # Pry.start
12
12
 
13
- require "irb"
13
+ require 'irb'
14
14
  IRB.start(__FILE__)
data/exe/lecli CHANGED
@@ -1,60 +1,55 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- require "thor"
4
- require "yaml"
5
- require "lecli"
3
+ require 'thor'
4
+ require 'yaml'
5
+ require 'lecli'
6
6
 
7
+ # Class in charge of the CLI functionallity powered by Thor
7
8
  class LECLIRunner < Thor
8
-
9
- YAML_FILENAME = ".lecli.yml"
10
-
11
- desc "version", "Prints out the gem version"
9
+ desc 'version', 'Prints out the gem version'
12
10
  def version
13
- puts "v#{LECLI::VERSION}"
11
+ puts LECLI::VERSION
14
12
  end
15
13
 
16
- desc "yaml", "Generates the #{YAML_FILENAME} file with all default options"
14
+ desc 'yaml', 'Generates the options file with defaults to customize'
17
15
  option :override,
18
- type: :boolean,
19
- aliases: [:o],
20
- desc: "Overrides the existing #{YAML_FILENAME} if any exist."
16
+ type: :boolean,
17
+ aliases: [:o],
18
+ desc: 'Overrides the existing options file the defaults.'
21
19
  def yaml
22
- if !File.file?(YAML_FILENAME) || options[:override]
23
- hash = LECLI::CertificateBuilder.default_options_yaml
24
- File.write(YAML_FILENAME, hash.to_yaml)
25
- puts YAML_FILENAME
26
- else
27
- puts "ERROR: #{YAML_FILENAME} file already exists. Try `lecli help yaml`"
28
- end
20
+ LECLI::CertificateBuilder.persist_defaults_file(
21
+ override: options[:override]
22
+ )
29
23
  end
30
24
 
31
- desc "generate", "Requests and outputs Let's Encrypt SSL Certificates"
25
+ desc 'generate', 'Requests and outputs Let\'s Encrypt SSL Certificates'
32
26
  option :production,
33
- type: :boolean,
34
- aliases: [:p],
35
- desc: "Use Let's Encrypt production API endpoint."
27
+ type: :boolean,
28
+ aliases: [:p],
29
+ desc: 'Use Let\'s Encrypt production API endpoint.'
30
+ option :config_file,
31
+ default: '.lecli.yml',
32
+ aliases: [:f],
33
+ desc: 'Specify the path of the configuration file.'
36
34
  def generate
37
- begin
38
- # Load defaults and merge with the config file data
39
- hash = LECLI::CertificateBuilder.default_options_yaml
40
- if File.file?(YAML_FILENAME)
41
- hash = hash.merge(YAML.load_file(YAML_FILENAME))
42
- end
43
- rescue
44
- puts "ERROR: Invalid format for file #{YAML_FILENAME}"
45
- return 1
35
+ puts "LOL: #{options[:config_file]}"
36
+ return
37
+ opts = LECLI::CertificateBuilder.load_options(config_file: config_file)
38
+ if opts.nil? # Bail if options can't be loaded properly
39
+ puts 'Unable to locate .lecli.yml file. Try `lecli help generate`'
40
+ return
46
41
  end
47
42
 
48
- hash["production"] = options[:production]
49
- LECLI::CertificateBuilder.generate_certs(hash)
50
-
51
- puts "Certificates generated successfully!"
52
-
53
- script_path = hash["success_callback_script"]
54
- if File.file?(script_path)
55
- puts "Execution attempt of success callback script `#{script_path}`"
56
- `./#{script_path}`
43
+ builder = LECLI::CertificateBuilder.new do |b|
44
+ b.production = options[:production]
57
45
  end
46
+ builder.generate_certs(opts)
47
+ puts 'Certificates generated successfully!'
48
+
49
+ script_path = File.expand_path(opts['success_callback_script'])
50
+ return if File.file?(script_path)
51
+ puts "Executing now success callback script `#{script_path}`..."
52
+ `./#{script_path}`
58
53
  end
59
54
  end
60
55
 
@@ -1,31 +1,30 @@
1
-
2
- lib = File.expand_path("../lib", __FILE__)
1
+ lib = File.expand_path('../lib', __FILE__)
3
2
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require "lecli/version"
3
+ require 'lecli/version'
5
4
 
6
5
  Gem::Specification.new do |spec|
7
- spec.name = "lecli"
6
+ spec.name = 'lecli'
8
7
  spec.version = LECLI::VERSION
9
- spec.authors = ["Fernando Valverde Arredondo"]
10
- spec.email = ["fdov88@gmail.com"]
8
+ spec.authors = ['Fernando Valverde Arredondo']
9
+ spec.email = ['fdov88@gmail.com']
11
10
 
12
- spec.summary = "Let's Encrypt CLI to generate certificates"
13
- spec.description = "Let's Encrypt CLI to generate certificates"
14
- spec.homepage = "https://github.com/fdoxyz/lecli"
15
- spec.license = "MIT"
11
+ spec.summary = 'CLI to generate Let\'s Encrypt certificates'
12
+ spec.description = 'CLI to generate Let\'s Encrypt certificates'
13
+ spec.homepage = 'https://github.com/fdoxyz/lecli'
14
+ spec.license = 'MIT'
16
15
 
17
16
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
17
  f.match(%r{^(test|spec|features)/})
19
18
  end
20
- spec.bindir = "exe"
19
+ spec.bindir = 'exe'
21
20
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
- spec.require_paths = ["lib"]
23
-
24
- spec.add_dependency "thor", "~> 0.20.0"
25
- spec.add_dependency "acme-client", "~> 2.0.0"
21
+ spec.require_paths = ['lib']
26
22
 
27
- spec.add_development_dependency "bundler", "~> 1.16"
28
- spec.add_development_dependency "rake", "~> 10.0"
29
- spec.add_development_dependency "rspec", "~> 3.0"
23
+ spec.add_dependency 'acme-client', '~> 2.0.0'
24
+ spec.add_dependency 'thor', '~> 0.20.0'
30
25
 
26
+ spec.add_development_dependency 'bundler', '~> 1.16'
27
+ spec.add_development_dependency 'rake', '~> 10.0'
28
+ spec.add_development_dependency 'rspec', '~> 3.0'
29
+ spec.add_development_dependency 'simplecov', '~> 0.16.1'
31
30
  end
Binary file
@@ -1,5 +1,6 @@
1
- require "lecli/version"
2
- require "lecli/certificate_builder"
1
+ require 'lecli/version'
2
+ require 'lecli/certificate_builder'
3
3
 
4
+ # Gem module where all the logic is implemented
4
5
  module LECLI
5
6
  end
@@ -1,92 +1,143 @@
1
- require "thor"
2
- require "acme-client"
3
- require "uri"
4
- require "fileutils"
1
+ require 'thor'
2
+ require 'acme-client'
3
+ require 'uri'
4
+ require 'fileutils'
5
5
 
6
6
  module LECLI
7
+ # Helper class to generate certs and access the default options
7
8
  class CertificateBuilder
9
+ attr_accessor :production
8
10
 
9
- def self.default_options_yaml
11
+ YAML_FILENAME = '.lecli.yml'.freeze
12
+
13
+ def initialize
14
+ @challenges = []
15
+ @production = false
16
+
17
+ # Pass a block to edit the new object for prod/staging or other options
18
+ yield self if block_given?
19
+
20
+ prod_url = 'https://acme-v02.api.letsencrypt.org/directory'
21
+ staging_url = 'https://acme-staging-v02.api.letsencrypt.org/directory'
22
+ @endpoint = @production ? prod_url : staging_url
23
+ end
24
+
25
+ def self.default_options
10
26
  {
11
- "port" => 3333,
12
- "domains" => [ "example.com" ],
13
- "common_name" => "Let's Encrypt",
14
- "account_email" => "test@account.com",
15
- "request_key" => "request.pem",
16
- "certificate_key" => "certificate.pem",
17
- "challenges_relative_path" => "challenges",
18
- "success_callback_script" => "deploy.sh"
27
+ 'domains' => ['example.com'],
28
+ 'common_name' => 'Let\'s Encrypt',
29
+ 'account_email' => 'test@account.com',
30
+ 'request_key' => 'request.pem',
31
+ 'certificate_key' => 'certificate.pem',
32
+ 'challenges_relative_path' => 'challenges',
33
+ 'success_callback_script' => 'deploy.sh'
19
34
  }
20
35
  end
21
36
 
22
- def self.generate_certs(options)
23
- if options["production"]
24
- endpoint = "https://acme-v02.api.letsencrypt.org/directory"
37
+ def self.load_options(config_file:)
38
+ opts = LECLI::CertificateBuilder.default_options
39
+ opts.merge(YAML.load_file(config_file)) if File.file?(config_file)
40
+ end
41
+
42
+ def self.persist_defaults_file(override:)
43
+ opts = LECLI::CertificateBuilder.default_options
44
+ if !File.file?(YAML_FILENAME) || override
45
+ File.write(YAML_FILENAME, opts.to_yaml)
46
+ puts YAML_FILENAME
25
47
  else
26
- endpoint = "https://acme-staging-v02.api.letsencrypt.org/directory"
48
+ puts "#{YAML_FILENAME} already exists. Try `lecli help yaml`"
27
49
  end
50
+ end
51
+
52
+ def generate_certs(options)
53
+ request_challenges(options: options)
54
+ sleep(3) # We are unaware of challenge hosting, better give them some time
28
55
 
29
- account_pkey = OpenSSL::PKey::RSA.new(4096)
30
- client = Acme::Client.new(private_key: account_pkey, directory: endpoint)
56
+ request_challenge_validation
57
+ request_key = finalize_order(
58
+ domains: options['domains'],
59
+ title: options['common_name']
60
+ )
61
+
62
+ write_certificate(
63
+ cert: @order.certificate, relative_path: options['certificate_key']
64
+ )
65
+ write_certificate(
66
+ cert: request_key, relative_path: options['request_key']
67
+ )
68
+ end
69
+
70
+ private
71
+
72
+ def request_challenges(options:)
73
+ create_order(email: options['account_email'], domains: options['domains'])
74
+ setup_challenges_dir(relative_path: options['challenges_relative_path'])
75
+ persist_challenge_tokens
76
+ end
77
+
78
+ def write_certificate(cert:, relative_path:)
79
+ full_path = File.expand_path(relative_path)
80
+ File.write(full_path, cert)
81
+ end
82
+
83
+ def finalize_order(domains:, title:)
84
+ request_key = OpenSSL::PKey::RSA.new(4096)
85
+ csr = Acme::Client::CertificateRequest.new(
86
+ private_key: request_key,
87
+ names: domains.values,
88
+ subject: { common_name: title }
89
+ )
90
+ @order.finalize(csr: csr)
91
+ sleep(1) while @order.status == 'processing'
92
+ request_key
93
+ end
94
+
95
+ def create_order(email:, domains:)
96
+ pkey = OpenSSL::PKey::RSA.new(4096)
97
+ client = Acme::Client.new(private_key: pkey, directory: @endpoint)
31
98
  client.new_account(
32
- contact: "mailto:#{options["account_email"]}",
33
- terms_of_service_agreed: true
34
- )
35
- order = client.new_order(identifiers: options["domains"])
36
-
37
- # Setup if necessary & clear challenges directory
38
- challenges_dir = File.expand_path(options["challenges_relative_path"])
39
- FileUtils.mkdir_p(challenges_dir)
40
- FileUtils.rm(Dir[File.join(challenges_dir, "*")])
41
-
42
- challenges = []
43
- order.authorizations.each do |authorization|
44
- challenge = authorization.http
45
- token_path = File.join(challenges_dir, challenge.token)
46
- File.write(token_path, challenge.file_content)
47
- challenges << challenge
48
- end
99
+ contact: "mailto:#{email}",
100
+ terms_of_service_agreed: true
101
+ )
102
+ @order = client.new_order(identifiers: domains)
103
+ end
49
104
 
50
- sleep(1)
105
+ def setup_challenges_dir(relative_path:)
106
+ @challenges_dir = File.expand_path(relative_path)
107
+ FileUtils.mkdir_p(@challenges_dir)
108
+ FileUtils.rm(Dir[File.join(@challenges_dir, '*')])
109
+ end
51
110
 
111
+ def request_challenge_validation
52
112
  wait_time = 5
53
113
  pending = true
54
114
  while pending
55
- challenges.each do |challenge|
115
+ @challenges.each do |challenge|
56
116
  begin
57
117
  challenge.request_validation
58
118
  rescue Acme::Client::Error::Malformed
59
- print "."
119
+ print '.'
60
120
  end
61
121
  end
62
122
 
63
- status = challenges.map(&:status)
64
- pending = status.include?("pending")
65
-
66
- if pending
67
- puts "At least one challenge still pending, waiting #{wait_time}s ..."
68
- sleep(wait_time)
123
+ status = @challenges.map(&:status)
124
+ pending = status.include?('pending')
69
125
 
70
- # Gradually increment wait times before retrying (max ~10min)
71
- wait_time *= 2 if wait_time < 640
72
- end
126
+ next unless pending
127
+ puts "At least one challenge still pending, waiting #{wait_time}s ..."
128
+ sleep(wait_time)
129
+ wait_time *= 2 if wait_time < 640 # Gradually increment retry max ~10min
73
130
  end
74
- puts "Challenges are all valid now!"
75
-
76
- request_key = OpenSSL::PKey::RSA.new(4096)
77
- csr = Acme::Client::CertificateRequest.new(
78
- private_key: request_key,
79
- names: domains.values,
80
- subject: { common_name: options["common_name"] }
81
- )
82
- order.finalize(csr: csr)
83
- sleep(1) while order.status == "processing"
84
-
85
- certificate_path = File.expand_path(options["certificate_key"])
86
- File.write(certificate_path, order.certificate)
87
- request_path = File.expand_path(options["request_key"])
88
- File.write(request_path, request_key)
131
+ puts 'Challenges are all valid now!'
89
132
  end
90
133
 
134
+ def persist_challenge_tokens
135
+ @order.authorizations.each do |authorization|
136
+ challenge = authorization.http
137
+ token_path = File.join(@challenges_dir, challenge.token)
138
+ File.write(token_path, challenge.file_content)
139
+ @challenges << challenge
140
+ end
141
+ end
91
142
  end
92
143
  end
@@ -1,3 +1,3 @@
1
1
  module LECLI
2
- VERSION = "0.2.2"
2
+ VERSION = '0.2.4'.freeze
3
3
  end
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lecli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.2.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fernando Valverde Arredondo
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-07-13 00:00:00.000000000 Z
11
+ date: 2018-07-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: thor
14
+ name: acme-client
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 0.20.0
19
+ version: 2.0.0
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 0.20.0
26
+ version: 2.0.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: acme-client
28
+ name: thor
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 2.0.0
33
+ version: 0.20.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 2.0.0
40
+ version: 0.20.0
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: bundler
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -80,7 +80,21 @@ dependencies:
80
80
  - - "~>"
81
81
  - !ruby/object:Gem::Version
82
82
  version: '3.0'
83
- description: Let's Encrypt CLI to generate certificates
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.16.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.16.1
97
+ description: CLI to generate Let's Encrypt certificates
84
98
  email:
85
99
  - fdov88@gmail.com
86
100
  executables:
@@ -90,6 +104,7 @@ extra_rdoc_files: []
90
104
  files:
91
105
  - ".gitignore"
92
106
  - ".rspec"
107
+ - ".rubocop.yml"
93
108
  - ".travis.yml"
94
109
  - Gemfile
95
110
  - Gemfile.lock
@@ -100,6 +115,7 @@ files:
100
115
  - bin/setup
101
116
  - exe/lecli
102
117
  - lecli.gemspec
118
+ - lecli_diagram.png
103
119
  - lib/lecli.rb
104
120
  - lib/lecli/certificate_builder.rb
105
121
  - lib/lecli/version.rb
@@ -126,5 +142,5 @@ rubyforge_project:
126
142
  rubygems_version: 2.6.14
127
143
  signing_key:
128
144
  specification_version: 4
129
- summary: Let's Encrypt CLI to generate certificates
145
+ summary: CLI to generate Let's Encrypt certificates
130
146
  test_files: []