letsencrypt_heroku 0.1.0

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fd350843a8264fbb86c567c3da1050d577ad6bff
4
+ data.tar.gz: 4a09bf20e63e78b20718ca4647441ce9a1df8d77
5
+ SHA512:
6
+ metadata.gz: b8ab3351b3b0055270feb47c668c0622211b42ad0f68af19463a90c7993b67f72c6b6adf8220cc0b02b94083fd2218ee110b2eaad13d83ae13129ad2705084db
7
+ data.tar.gz: 77a13396a80b2a4a78e3477effa4f99b5197ddebb4f04b65bd2ad2c277e8773b73845f575378e38c56c37d1f223725ba2ded003c4d09e812c9190e669da59629
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.3.1
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.3.1
5
+ before_install: gem install bundler -v 1.12.5
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in letsencrypt_heroku.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # LetsencryptHeroku
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/letsencrypt_heroku`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ ## Installation
6
+
7
+ Add these lines to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'letsencrypt_rack'
11
+ gem 'letsencrypt_heroku', require: false
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ You'll need a `config/letsencrypt_heroku.yml`
19
+
20
+ - contact: contact@foobar.dev
21
+ domains: foobar.dev www.foobar.dev
22
+ herokuapp: foobar
23
+
24
+ And finally execute
25
+
26
+ $ letsencrypt_heroku
27
+
28
+ ## Contributing
29
+
30
+ Bug reports and pull requests are welcome on GitHub at https://github.com/xijo/letsencrypt_heroku.
31
+
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ require 'bundler/gem_tasks'
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new(:spec)
5
+ task :default => :spec
6
+
7
+ desc 'Open an irb session preloaded with this library'
8
+ task :console do
9
+ sh 'irb -rubygems -I lib -r letsencrypt_heroku.rb'
10
+ end
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "letsencrypt_heroku"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'letsencrypt_heroku'
5
+
6
+ LetsencryptHeroku::CLI.run
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'letsencrypt_heroku/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'letsencrypt_heroku'
8
+ spec.version = LetsencryptHeroku::VERSION
9
+ spec.authors = ['Johannes Opper']
10
+ spec.email = ['johannes.opper@gmail.com']
11
+
12
+ spec.summary = %q{Setup SSL for heroku with letsencrypt}
13
+ spec.description = %q{Setup SSL for heroku with letsencrypt}
14
+ spec.homepage = 'https://github.com/xijo/letsencrypt_heroku'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
17
+ spec.bindir = "exe"
18
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "rainbow"
22
+ spec.add_dependency "acme-client"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.12"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec", "~> 3.0"
27
+ end
@@ -0,0 +1,21 @@
1
+ require 'rainbow'
2
+ require 'yaml'
3
+ require 'acme-client'
4
+ require 'openssl'
5
+ require 'letsencrypt_heroku/version'
6
+ require 'letsencrypt_heroku/setup'
7
+
8
+ module LetsencryptHeroku
9
+ class CLI
10
+ CONFIG_FILE = 'config/letsencrypt_heroku.yml'
11
+
12
+ def self.run
13
+ if File.exist?(CONFIG_FILE)
14
+ configs = Array(YAML.load(File.read(CONFIG_FILE))).map { |c| OpenStruct.new(c) }
15
+ configs.each { |config| Setup.new(config).perform }
16
+ else
17
+ puts Rainbow("Missing config: #{CONFIG_FILE}").red
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,92 @@
1
+ module LetsencryptHeroku
2
+ class Setup
3
+ class SetupError < StandardError ; end
4
+
5
+ PRODUCTION = 'https://acme-v01.api.letsencrypt.org/'
6
+ STAGING = 'https://acme-staging.api.letsencrypt.org/'
7
+
8
+ attr_accessor :config
9
+
10
+ def initialize(config)
11
+ @config = config
12
+ @config.endpoint ||= PRODUCTION
13
+ @config.domains = config.domains.split
14
+ end
15
+
16
+ def perform
17
+ run_task "preflight" do
18
+ # heroku labs:enable http-sni
19
+ # heroku plugins:install heroku-certs
20
+
21
+ # check that ssl endpoint is on
22
+ # check heroku is there
23
+ # check that certs are there
24
+ end
25
+
26
+ run_task 'register with letsencrypt server' do
27
+ @private_key = OpenSSL::PKey::RSA.new(4096)
28
+ @client = Acme::Client.new(private_key: @private_key, endpoint: config.endpoint)
29
+ @client.register(contact: "mailto:#{config.contact}").agree_terms or fail_task
30
+ end
31
+
32
+ config.domains.each do |domain|
33
+ run_task "authorize #{domain}" do
34
+ @challenge = @client.authorize(domain: domain).http01
35
+
36
+ command = "heroku config:set LETSENCRYPT_RESPONSE=#{@challenge.file_content} &> /dev/null"
37
+ `#{command}`
38
+ $?.success? or fail_task
39
+
40
+ test_response(domain: domain, challenge: @challenge)
41
+
42
+ @challenge.request_verification
43
+ sleep(1) while 'pending' == @challenge.verify_status
44
+ @challenge.verify_status == 'valid' or fail_task
45
+ end
46
+ end
47
+
48
+ # if has cert: update cert, else add cert
49
+
50
+ run_task "update certificates" do
51
+ csr = Acme::Client::CertificateRequest.new(names: config.domains)
52
+ certificate = @client.new_certificate(csr)
53
+ File.write('privkey.pem', certificate.request.private_key.to_pem)
54
+ File.write('fullchain.pem', certificate.fullchain_to_pem)
55
+
56
+ command = "heroku _certs:update fullchain.pem privkey.pem --confirm #{config.herokuapp}"
57
+ `#{command}`
58
+ $?.success? or fail_task
59
+
60
+ FileUtils.rm %w(privkey.pem fullchain.pem)
61
+ end
62
+ rescue SetupError
63
+ end
64
+
65
+ def test_response(domain:, challenge:)
66
+ url = "http://#{domain}/#{challenge.filename}"
67
+ fail_count = 0
68
+ while fail_count < 30
69
+ answer = `curl -sL #{url}`
70
+ if answer != challenge.file_content
71
+ fail_count += 1
72
+ sleep(1)
73
+ else
74
+ return
75
+ end
76
+ end
77
+ fail_task
78
+ end
79
+
80
+ def run_task(name)
81
+ @_current_task = name
82
+ print Rainbow(" #{@_current_task}").yellow
83
+ yield
84
+ puts Rainbow("\r ✔ #{@_current_task}").green
85
+ end
86
+
87
+ def fail_task(reason = nil)
88
+ puts Rainbow("\r ✘ #{@_current_task}").red
89
+ raise SetupError, reason
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,3 @@
1
+ module LetsencryptHeroku
2
+ VERSION = "0.1.0"
3
+ end
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: letsencrypt_heroku
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Johannes Opper
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-06-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rainbow
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: acme-client
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.12'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.12'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ description: Setup SSL for heroku with letsencrypt
84
+ email:
85
+ - johannes.opper@gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - ".ruby-version"
93
+ - ".travis.yml"
94
+ - Gemfile
95
+ - README.md
96
+ - Rakefile
97
+ - bin/console
98
+ - bin/letsencrypt_heroku
99
+ - bin/setup
100
+ - letsencrypt_heroku.gemspec
101
+ - lib/letsencrypt_heroku.rb
102
+ - lib/letsencrypt_heroku/setup.rb
103
+ - lib/letsencrypt_heroku/version.rb
104
+ homepage: https://github.com/xijo/letsencrypt_heroku
105
+ licenses: []
106
+ metadata: {}
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.6.4
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: Setup SSL for heroku with letsencrypt
127
+ test_files: []
128
+ has_rdoc: