Skip to content

Commit

Permalink
Initialize project
Browse files Browse the repository at this point in the history
  • Loading branch information
elct9620 committed May 6, 2017
0 parents commit f36fbf0
Show file tree
Hide file tree
Showing 26 changed files with 608 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
.bundle/
log/*.log
pkg/
test/dummy/db/*.sqlite3
test/dummy/db/*.sqlite3-journal
test/dummy/log/*.log
test/dummy/tmp/
14 changes: 14 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
source 'https://rubygems.org'

# Declare your gem's dependencies in lets_encrypt.gemspec.
# Bundler will treat runtime dependencies like base dependencies, and
# development dependencies will be added by default to the :development group.
gemspec

# Declare any dependencies that are still in development here instead of in
# your gemspec. These might include edge Rails or gems from your path or
# Git. Remember to move these dependencies to your gemspec before releasing
# your gem to rubygems.org.

# To use a debugger
# gem 'byebug', group: [:development, :test]
143 changes: 143 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
PATH
remote: .
specs:
rails-letsencrypt (0.1.0)
acme-client
rails (~> 5.1.0)

GEM
remote: https://rubygems.org/
specs:
acme-client (0.5.5)
faraday (~> 0.9, >= 0.9.1)
actioncable (5.1.0)
actionpack (= 5.1.0)
nio4r (~> 2.0)
websocket-driver (~> 0.6.1)
actionmailer (5.1.0)
actionpack (= 5.1.0)
actionview (= 5.1.0)
activejob (= 5.1.0)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (5.1.0)
actionview (= 5.1.0)
activesupport (= 5.1.0)
rack (~> 2.0)
rack-test (~> 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.2)
actionview (5.1.0)
activesupport (= 5.1.0)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.0.3)
activejob (5.1.0)
activesupport (= 5.1.0)
globalid (>= 0.3.6)
activemodel (5.1.0)
activesupport (= 5.1.0)
activerecord (5.1.0)
activemodel (= 5.1.0)
activesupport (= 5.1.0)
arel (~> 8.0)
activesupport (5.1.0)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (~> 0.7)
minitest (~> 5.1)
tzinfo (~> 1.1)
arel (8.0.0)
builder (3.2.3)
concurrent-ruby (1.0.5)
diff-lcs (1.3)
erubi (1.6.0)
faraday (0.12.1)
multipart-post (>= 1.2, < 3)
globalid (0.4.0)
activesupport (>= 4.2.0)
i18n (0.8.1)
loofah (2.0.3)
nokogiri (>= 1.5.9)
mail (2.6.5)
mime-types (>= 1.16, < 4)
method_source (0.8.2)
mime-types (3.1)
mime-types-data (~> 3.2015)
mime-types-data (3.2016.0521)
mini_portile2 (2.1.0)
minitest (5.10.1)
multipart-post (2.0.0)
nio4r (2.0.0)
nokogiri (1.7.1)
mini_portile2 (~> 2.1.0)
rack (2.0.1)
rack-test (0.6.3)
rack (>= 1.0)
rails (5.1.0)
actioncable (= 5.1.0)
actionmailer (= 5.1.0)
actionpack (= 5.1.0)
actionview (= 5.1.0)
activejob (= 5.1.0)
activemodel (= 5.1.0)
activerecord (= 5.1.0)
activesupport (= 5.1.0)
bundler (>= 1.3.0, < 2.0)
railties (= 5.1.0)
sprockets-rails (>= 2.0.0)
rails-dom-testing (2.0.2)
activesupport (>= 4.2.0, < 6.0)
nokogiri (~> 1.6)
rails-html-sanitizer (1.0.3)
loofah (~> 2.0)
railties (5.1.0)
actionpack (= 5.1.0)
activesupport (= 5.1.0)
method_source
rake (>= 0.8.7)
thor (>= 0.18.1, < 2.0)
rake (12.0.0)
rspec-core (3.5.4)
rspec-support (~> 3.5.0)
rspec-expectations (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.5.0)
rspec-mocks (3.5.0)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.5.0)
rspec-rails (3.5.2)
actionpack (>= 3.0)
activesupport (>= 3.0)
railties (>= 3.0)
rspec-core (~> 3.5.0)
rspec-expectations (~> 3.5.0)
rspec-mocks (~> 3.5.0)
rspec-support (~> 3.5.0)
rspec-support (3.5.0)
sprockets (3.7.1)
concurrent-ruby (~> 1.0)
rack (> 1, < 3)
sprockets-rails (3.2.0)
actionpack (>= 4.0)
activesupport (>= 4.0)
sprockets (>= 3.0.0)
sqlite3 (1.3.13)
thor (0.19.4)
thread_safe (0.3.6)
tzinfo (1.2.3)
thread_safe (~> 0.1)
websocket-driver (0.6.5)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.2)

PLATFORMS
ruby

DEPENDENCIES
rails-letsencrypt!
rspec-rails
sqlite3

BUNDLED WITH
1.14.6
20 changes: 20 additions & 0 deletions MIT-LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
Copyright 2017 蒼時弦也

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 changes: 28 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# LetsEncrypt
Short description and motivation.

## Usage
How to use my plugin.

## Installation
Add this line to your application's Gemfile:

```ruby
gem 'lets_encrypt'
```

And then execute:
```bash
$ bundle
```

Or install it yourself as:
```bash
$ gem install lets_encrypt
```

## Contributing
Contribution directions go here.

## License
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
36 changes: 36 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
begin
require 'bundler/setup'
rescue LoadError
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
end

require 'rdoc/task'

RDoc::Task.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = 'LetsEncrypt'
rdoc.options << '--line-numbers'
rdoc.rdoc_files.include('README.md')
rdoc.rdoc_files.include('lib/**/*.rb')
end

APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
load 'rails/tasks/engine.rake'


load 'rails/tasks/statistics.rake'



require 'bundler/gem_tasks'

require 'rake/testtask'

Rake::TestTask.new(:test) do |t|
t.libs << 'test'
t.pattern = 'test/**/*_test.rb'
t.verbose = false
end


task default: :test
5 changes: 5 additions & 0 deletions app/controllers/lets_encrypt/application_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module LetsEncrypt
class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
end
end
25 changes: 25 additions & 0 deletions app/controllers/lets_encrypt/verifications_controller.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
require_dependency 'lets_encrypt/application_controller'

module LetsEncrypt
# :nodoc:
class VerificationsController < ApplicationController
def show
return render_verification_string if certificate.present?
render plain: 'Verification not found', status: 404
end

protected

def render_verification_string
render plain: certificate.verification_string
end

def certificate
LetsEncrypt::Certificate.find_by(verification_path: filename)
end

def filename
".well-known/acme-challenge/#{params[:verification_path]}"
end
end
end
4 changes: 4 additions & 0 deletions app/jobs/lets_encrypt/application_job.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module LetsEncrypt
class ApplicationJob < ActiveJob::Base
end
end
37 changes: 37 additions & 0 deletions app/models/concerns/lets_encrypt/certificate_issuable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
module LetsEncrypt
# :nodoc:
module CertificateIssuable
extend ActiveSupport::Concern

def issue
logger.info "Getting certificate for #{domain}"
create_certificate
# rubocop:disable Metrics/LineLength
logger.info "Certificate issued (expires on #{expires_at}, will renew after #{renew_after})"
# rubocop:enable Metrics/LineLength
true
end

private

def csr
csr = OpenSSL::X509::Request.new
csr.subject = OpenSSL::X509::Name.new(
[['CN', domain, OpenSSL::ASN1::UTF8STRING]]
)
private_key = OpenSSL::PKey::RSA.new(key)
csr.public_key = private_key.public_key
csr.sign(private_key, OpenSSL::Digest::SHA256.new)
csr
end

def create_certificate
https_cert = LetsEncrypt.client.new_certificate(csr)
self.certificate = https_cert.to_pem
self.intermediaries = https_cert.chain_to_pem
self.expires_at = https_cert.x509.not_after
self.renew_after = (expires_at - 1.month) + rand(10).days
save!
end
end
end
66 changes: 66 additions & 0 deletions app/models/concerns/lets_encrypt/certificate_verifiable.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
module LetsEncrypt
# :nodoc:
module CertificateVerifiable
extend ActiveSupport::Concern

def verify
start_authorize
start_challenge
wait_verify_status
check_verify_status
rescue Acme::Client::Error => e
retry_on_verify_error(e)
end

private

def start_authorize
authorization = LetsEncrypt.client.authorize(domain: domain)
@challenge = authorization.http01
self.verification_path = @challenge.filename
self.verification_string = @challenge.file_content
save!
end

def start_challenge
logger.info "Attempting verification of #{domain}"
@challenge.request_verification
end

def wait_verify_status
checks = 0
until @challenge.verify_status != 'pending'
checks += 1
if checks > 30
logger.info 'Status remained at pending for 30 checks'
return false
end
sleep 1
end
end

def check_verify_status
unless @challenge.verify_status == 'valid'
logger.info "Status was not valid (was: #{@challenge.verify_status})"
return false
end

true
end

def retry_on_verify_error
@retries = 0
if e.is_a?(Acme::Client::Error::BadNonce) && @retries < 5
@retries += 1
# rubocop:disable Metrics/LineLength
logger.info "Bad nounce encountered. Retrying (#{@retries} of 5 attempts)"
# rubocop:enable Metrics/LineLength
sleep 1
verify
else
logger.info "Error: #{e.class} (#{e.message})"
return false
end
end
end
end
Loading

0 comments on commit f36fbf0

Please sign in to comment.