summaryrefslogtreecommitdiff
path: root/vendor
diff options
context:
space:
mode:
authorelijah <elijah@riseup.net>2016-10-05 14:35:56 -0700
committerelijah <elijah@riseup.net>2016-10-05 14:35:56 -0700
commit7abfbd6abae14fa6a72350f7b75268ff561354ee (patch)
treeaf5c969c905a8d2a95f2b2aa7c4dd6f4b8763126 /vendor
parentcc57bc6c0ff99d88f3bfeff1b04297e9b91e6988 (diff)
parentf95e08ef7d8defbde4a19e138b1ac4ebc9677669 (diff)
Merge branch 'develop'
# Conflicts: # lib/leap_cli/version.rb
Diffstat (limited to 'vendor')
-rw-r--r--vendor/acme-client/Gemfile12
-rw-r--r--vendor/acme-client/LICENSE.txt21
-rw-r--r--vendor/acme-client/README.md168
-rw-r--r--vendor/acme-client/acme-client.gemspec27
-rw-r--r--vendor/acme-client/lib/acme-client.rb1
-rw-r--r--vendor/acme-client/lib/acme/client.rb122
-rw-r--r--vendor/acme-client/lib/acme/client/certificate.rb30
-rw-r--r--vendor/acme-client/lib/acme/client/certificate_request.rb111
-rw-r--r--vendor/acme-client/lib/acme/client/crypto.rb98
-rw-r--r--vendor/acme-client/lib/acme/client/error.rb16
-rw-r--r--vendor/acme-client/lib/acme/client/faraday_middleware.rb123
-rw-r--r--vendor/acme-client/lib/acme/client/resources.rb5
-rw-r--r--vendor/acme-client/lib/acme/client/resources/authorization.rb44
-rw-r--r--vendor/acme-client/lib/acme/client/resources/challenges.rb6
-rw-r--r--vendor/acme-client/lib/acme/client/resources/challenges/base.rb43
-rw-r--r--vendor/acme-client/lib/acme/client/resources/challenges/dns01.rb19
-rw-r--r--vendor/acme-client/lib/acme/client/resources/challenges/http01.rb18
-rw-r--r--vendor/acme-client/lib/acme/client/resources/challenges/tls_sni01.rb24
-rw-r--r--vendor/acme-client/lib/acme/client/resources/registration.rb37
-rw-r--r--vendor/acme-client/lib/acme/client/self_sign_certificate.rb60
-rw-r--r--vendor/acme-client/lib/acme/client/version.rb7
-rw-r--r--vendor/base32/LICENSE19
-rw-r--r--vendor/base32/base32.gemspec10
-rw-r--r--vendor/base32/lib/base32.rb67
-rw-r--r--vendor/certificate_authority/certificate_authority.gemspec19
-rw-r--r--vendor/certificate_authority/lib/certificate_authority.rb3
-rw-r--r--vendor/certificate_authority/lib/certificate_authority/certificate.rb8
-rw-r--r--vendor/certificate_authority/lib/certificate_authority/certificate_revocation_list.rb12
-rw-r--r--vendor/certificate_authority/lib/certificate_authority/core_extensions.rb46
-rw-r--r--vendor/certificate_authority/lib/certificate_authority/distinguished_name.rb8
-rw-r--r--vendor/certificate_authority/lib/certificate_authority/extensions.rb13
-rw-r--r--vendor/certificate_authority/lib/certificate_authority/key_material.rb20
-rw-r--r--vendor/certificate_authority/lib/certificate_authority/ocsp_handler.rb6
-rw-r--r--vendor/certificate_authority/lib/certificate_authority/pkcs11_key_material.rb2
-rw-r--r--vendor/certificate_authority/lib/certificate_authority/serial_number.rb10
-rw-r--r--vendor/certificate_authority/lib/certificate_authority/validations.rb31
-rw-r--r--vendor/rsync_command/README.md12
-rw-r--r--vendor/rsync_command/lib/rsync_command.rb61
38 files changed, 1280 insertions, 59 deletions
diff --git a/vendor/acme-client/Gemfile b/vendor/acme-client/Gemfile
new file mode 100644
index 0000000..e0b10df
--- /dev/null
+++ b/vendor/acme-client/Gemfile
@@ -0,0 +1,12 @@
+source 'https://rubygems.org'
+gemspec
+
+group :development, :test do
+ gem 'pry'
+ gem 'rubocop', '0.36.0'
+ gem 'ruby-prof', require: false
+
+ if Gem::Version.new(RUBY_VERSION) <= Gem::Version.new('2.2.2')
+ gem 'activesupport', '~> 4.2.6'
+ end
+end
diff --git a/vendor/acme-client/LICENSE.txt b/vendor/acme-client/LICENSE.txt
new file mode 100644
index 0000000..73b96b4
--- /dev/null
+++ b/vendor/acme-client/LICENSE.txt
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Charles Barbier
+
+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.
diff --git a/vendor/acme-client/README.md b/vendor/acme-client/README.md
new file mode 100644
index 0000000..2047885
--- /dev/null
+++ b/vendor/acme-client/README.md
@@ -0,0 +1,168 @@
+# Acme::Client
+[![Build Status](https://travis-ci.org/unixcharles/acme-client.svg?branch=master)](https://travis-ci.org/unixcharles/acme-client)
+
+`acme-client` is a client implementation of the [ACME](https://letsencrypt.github.io/acme-spec) protocol in Ruby.
+
+You can find the ACME reference implementations of the [server](https://github.com/letsencrypt/boulder) in Go and the [client](https://github.com/letsencrypt/letsencrypt) in Python.
+
+ACME is part of the [Letsencrypt](https://letsencrypt.org/) project, which goal is to provide free SSL/TLS certificates with automation of the acquiring and renewal process.
+
+## Installation
+
+Via Rubygems:
+
+ $ gem install acme-client
+
+Or add it to a Gemfile:
+
+```ruby
+gem 'acme-client'
+```
+
+## Usage
+
+### Register client
+
+In order to authenticate our client, we have to create an account for it.
+
+```ruby
+# We're going to need a private key.
+require 'openssl'
+private_key = OpenSSL::PKey::RSA.new(4096)
+
+# We need an ACME server to talk to, see github.com/letsencrypt/boulder
+# WARNING: This endpoint is the production endpoint, which is rate limited and will produce valid certificates.
+# You should probably use the staging endpoint for all your experimentation:
+# endpoint = 'https://acme-staging.api.letsencrypt.org/'
+endpoint = 'https://acme-v01.api.letsencrypt.org/'
+
+# Initialize the client
+require 'acme-client'
+client = Acme::Client.new(private_key: private_key, endpoint: endpoint, connection_options: { request: { open_timeout: 5, timeout: 5 } })
+
+# If the private key is not known to the server, we need to register it for the first time.
+registration = client.register(contact: 'mailto:contact@example.com')
+
+# You may need to agree to the terms of service (that's up the to the server to require it or not but boulder does by default)
+registration.agree_terms
+```
+
+### Authorize for domain
+
+Before you are able to obtain certificates for your domain, you have to prove that you are in control of it.
+
+```ruby
+authorization = client.authorize(domain: 'example.org')
+
+# If authorization.status returns 'valid' here you can already get a certificate
+# and _must not_ try to solve another challenge.
+authorization.status # => 'pending'
+
+# You can can store the authorization's URI to fully recover it and
+# any associated challenges via Acme::Client#fetch_authorization.
+authorization.uri # => '...'
+
+# This example is using the http-01 challenge type. Other challenges are dns-01 or tls-sni-01.
+challenge = authorization.http01
+
+# The http-01 method will require you to respond to a HTTP request.
+
+# You can retrieve the challenge token
+challenge.token # => "some_token"
+
+# You can retrieve the expected path for the file.
+challenge.filename # => ".well-known/acme-challenge/:some_token"
+
+# You can generate the body of the expected response.
+challenge.file_content # => 'string token and JWK thumbprint'
+
+# You are not required to send a Content-Type. This method will return the right Content-Type should you decide to include one.
+challenge.content_type
+
+# Save the file. We'll create a public directory to serve it from, and inside it we'll create the challenge file.
+FileUtils.mkdir_p( File.join( 'public', File.dirname( challenge.filename ) ) )
+
+# We'll write the content of the file
+File.write( File.join( 'public', challenge.filename), challenge.file_content )
+
+# Optionally save the challenge for use at another time (eg: by a background job processor)
+File.write('challenge', challenge.to_h.to_json)
+
+# The challenge file can be served with a Ruby webserver.
+# You can run a webserver in another console for that purpose. You may need to forward ports on your router.
+#
+# $ ruby -run -e httpd public -p 8080 --bind-address 0.0.0.0
+
+# Load a saved challenge. This is only required if you need to reuse a saved challenge as outlined above.
+challenge = client.challenge_from_hash(JSON.parse(File.read('challenge')))
+
+# Once you are ready to serve the confirmation request you can proceed.
+challenge.request_verification # => true
+challenge.authorization.verify_status # => 'pending'
+
+# Wait a bit for the server to make the request, or just blink. It should be fast.
+sleep(1)
+
+# Rely on authorization.verify_status more than on challenge.verify_status,
+# if the former is 'valid' you can already issue a certificate and the status of
+# the challenge is not relevant and in fact may never change from pending.
+challenge.authorization.verify_status # => 'valid'
+challenge.error # => nil
+
+# If authorization.verify_status is 'invalid', you can get at the error
+# message only through the failed challenge.
+authorization.verify_status # => 'invalid'
+authorization.http01.error # => {"type" => "...", "detail" => "..."}
+```
+
+### Obtain a certificate
+
+Now that your account is authorized for the domain, you should be able to obtain a certificate for it.
+
+```ruby
+# We're going to need a certificate signing request. If not explicitly
+# specified, the first name listed becomes the common name.
+csr = Acme::Client::CertificateRequest.new(names: %w[example.org www.example.org])
+
+# We can now request a certificate. You can pass anything that returns
+# a valid DER encoded CSR when calling to_der on it. For example an
+# OpenSSL::X509::Request should work too.
+certificate = client.new_certificate(csr) # => #<Acme::Client::Certificate ....>
+
+# Save the certificate and the private key to files
+File.write("privkey.pem", certificate.request.private_key.to_pem)
+File.write("cert.pem", certificate.to_pem)
+File.write("chain.pem", certificate.chain_to_pem)
+File.write("fullchain.pem", certificate.fullchain_to_pem)
+
+# Start a webserver, using your shiny new certificate
+# ruby -r openssl -r webrick -r 'webrick/https' -e "s = WEBrick::HTTPServer.new(
+# :Port => 8443,
+# :DocumentRoot => Dir.pwd,
+# :SSLEnable => true,
+# :SSLPrivateKey => OpenSSL::PKey::RSA.new( File.read('privkey.pem') ),
+# :SSLCertificate => OpenSSL::X509::Certificate.new( File.read('cert.pem') )); trap('INT') { s.shutdown }; s.start"
+```
+
+# Not implemented
+
+- Recovery methods are not implemented.
+
+# Requirements
+
+Ruby >= 2.1
+
+## Development
+
+All the tests use VCR to mock the interaction with the server but if you
+need to record new interation against the server simply clone boulder and
+run it normally with `./start.py`.
+
+## Pull request?
+
+Yes.
+
+## License
+
+[MIT License](http://opensource.org/licenses/MIT)
+
diff --git a/vendor/acme-client/acme-client.gemspec b/vendor/acme-client/acme-client.gemspec
new file mode 100644
index 0000000..b62d60c
--- /dev/null
+++ b/vendor/acme-client/acme-client.gemspec
@@ -0,0 +1,27 @@
+# coding: utf-8
+lib = File.expand_path('../lib', __FILE__)
+$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
+require 'acme/client/version'
+
+Gem::Specification.new do |spec|
+ spec.name = 'acme-client'
+ spec.version = Acme::Client::VERSION
+ spec.authors = ['Charles Barbier']
+ spec.email = ['unixcharles@gmail.com']
+ spec.summary = 'Client for the ACME protocol.'
+ spec.homepage = 'http://github.com/unixcharles/acme-client'
+ spec.license = 'MIT'
+
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
+ spec.require_paths = ['lib']
+
+ spec.required_ruby_version = '>= 2.1.0'
+
+ spec.add_development_dependency 'bundler', '~> 1.6', '>= 1.6.9'
+ spec.add_development_dependency 'rake', '~> 10.0'
+ spec.add_development_dependency 'rspec', '~> 3.3', '>= 3.3.0'
+ spec.add_development_dependency 'vcr', '~> 2.9', '>= 2.9.3'
+ spec.add_development_dependency 'webmock', '~> 1.21', '>= 1.21.0'
+
+ spec.add_runtime_dependency 'faraday', '~> 0.9', '>= 0.9.1'
+end
diff --git a/vendor/acme-client/lib/acme-client.rb b/vendor/acme-client/lib/acme-client.rb
new file mode 100644
index 0000000..7cc7a0a
--- /dev/null
+++ b/vendor/acme-client/lib/acme-client.rb
@@ -0,0 +1 @@
+require 'acme/client'
diff --git a/vendor/acme-client/lib/acme/client.rb b/vendor/acme-client/lib/acme/client.rb
new file mode 100644
index 0000000..801479e
--- /dev/null
+++ b/vendor/acme-client/lib/acme/client.rb
@@ -0,0 +1,122 @@
+# frozen_string_literal: true
+
+require 'faraday'
+require 'json'
+require 'openssl'
+require 'digest'
+require 'forwardable'
+require 'base64'
+require 'time'
+
+module Acme; end
+class Acme::Client; end
+
+require 'acme/client/version'
+require 'acme/client/certificate'
+require 'acme/client/certificate_request'
+require 'acme/client/self_sign_certificate'
+require 'acme/client/crypto'
+require 'acme/client/resources'
+require 'acme/client/faraday_middleware'
+require 'acme/client/error'
+
+class Acme::Client
+ DEFAULT_ENDPOINT = 'http://127.0.0.1:4000'.freeze
+ DIRECTORY_DEFAULT = {
+ 'new-authz' => '/acme/new-authz',
+ 'new-cert' => '/acme/new-cert',
+ 'new-reg' => '/acme/new-reg',
+ 'revoke-cert' => '/acme/revoke-cert'
+ }.freeze
+
+ def initialize(private_key:, endpoint: DEFAULT_ENDPOINT, directory_uri: nil, connection_options: {})
+ @endpoint, @private_key, @directory_uri, @connection_options = endpoint, private_key, directory_uri, connection_options
+ @nonces ||= []
+ load_directory!
+ end
+
+ attr_reader :private_key, :nonces, :operation_endpoints
+
+ def register(contact:)
+ payload = {
+ resource: 'new-reg', contact: Array(contact)
+ }
+
+ response = connection.post(@operation_endpoints.fetch('new-reg'), payload)
+ ::Acme::Client::Resources::Registration.new(self, response)
+ end
+
+ def authorize(domain:)
+ payload = {
+ resource: 'new-authz',
+ identifier: {
+ type: 'dns',
+ value: domain
+ }
+ }
+
+ response = connection.post(@operation_endpoints.fetch('new-authz'), payload)
+ ::Acme::Client::Resources::Authorization.new(self, response.headers['Location'], response)
+ end
+
+ def fetch_authorization(uri)
+ response = connection.get(uri)
+ ::Acme::Client::Resources::Authorization.new(self, uri, response)
+ end
+
+ def new_certificate(csr)
+ payload = {
+ resource: 'new-cert',
+ csr: Base64.urlsafe_encode64(csr.to_der)
+ }
+
+ response = connection.post(@operation_endpoints.fetch('new-cert'), payload)
+ ::Acme::Client::Certificate.new(OpenSSL::X509::Certificate.new(response.body), response.headers['location'], fetch_chain(response), csr)
+ end
+
+ def revoke_certificate(certificate)
+ payload = { resource: 'revoke-cert', certificate: Base64.urlsafe_encode64(certificate.to_der) }
+ endpoint = @operation_endpoints.fetch('revoke-cert')
+ response = connection.post(endpoint, payload)
+ response.success?
+ end
+
+ def self.revoke_certificate(certificate, *arguments)
+ client = new(*arguments)
+ client.revoke_certificate(certificate)
+ end
+
+ def connection
+ @connection ||= Faraday.new(@endpoint, **@connection_options) do |configuration|
+ configuration.use Acme::Client::FaradayMiddleware, client: self
+ configuration.adapter Faraday.default_adapter
+ end
+ end
+
+ private
+
+ def fetch_chain(response, limit = 10)
+ links = response.headers['link']
+ if limit.zero? || links.nil? || links['up'].nil?
+ []
+ else
+ issuer = connection.get(links['up'])
+ [OpenSSL::X509::Certificate.new(issuer.body), *fetch_chain(issuer, limit - 1)]
+ end
+ end
+
+ def load_directory!
+ @operation_endpoints = if @directory_uri
+ response = connection.get(@directory_uri)
+ body = response.body
+ {
+ 'new-reg' => body.fetch('new-reg'),
+ 'new-authz' => body.fetch('new-authz'),
+ 'new-cert' => body.fetch('new-cert'),
+ 'revoke-cert' => body.fetch('revoke-cert'),
+ }
+ else
+ DIRECTORY_DEFAULT
+ end
+ end
+end
diff --git a/vendor/acme-client/lib/acme/client/certificate.rb b/vendor/acme-client/lib/acme/client/certificate.rb
new file mode 100644
index 0000000..6c68cc5
--- /dev/null
+++ b/vendor/acme-client/lib/acme/client/certificate.rb
@@ -0,0 +1,30 @@
+class Acme::Client::Certificate
+ extend Forwardable
+
+ attr_reader :x509, :x509_chain, :request, :private_key, :url
+
+ def_delegators :x509, :to_pem, :to_der
+
+ def initialize(certificate, url, chain, request)
+ @x509 = certificate
+ @url = url
+ @x509_chain = chain
+ @request = request
+ end
+
+ def chain_to_pem
+ x509_chain.map(&:to_pem).join
+ end
+
+ def x509_fullchain
+ [x509, *x509_chain]
+ end
+
+ def fullchain_to_pem
+ x509_fullchain.map(&:to_pem).join
+ end
+
+ def common_name
+ x509.subject.to_a.find { |name, _, _| name == 'CN' }[1]
+ end
+end
diff --git a/vendor/acme-client/lib/acme/client/certificate_request.rb b/vendor/acme-client/lib/acme/client/certificate_request.rb
new file mode 100644
index 0000000..8eae0c6
--- /dev/null
+++ b/vendor/acme-client/lib/acme/client/certificate_request.rb
@@ -0,0 +1,111 @@
+class Acme::Client::CertificateRequest
+ extend Forwardable
+
+ DEFAULT_KEY_LENGTH = 2048
+ DEFAULT_DIGEST = OpenSSL::Digest::SHA256
+ SUBJECT_KEYS = {
+ common_name: 'CN',
+ country_name: 'C',
+ organization_name: 'O',
+ organizational_unit: 'OU',
+ state_or_province: 'ST',
+ locality_name: 'L'
+ }.freeze
+
+ SUBJECT_TYPES = {
+ 'CN' => OpenSSL::ASN1::UTF8STRING,
+ 'C' => OpenSSL::ASN1::UTF8STRING,
+ 'O' => OpenSSL::ASN1::UTF8STRING,
+ 'OU' => OpenSSL::ASN1::UTF8STRING,
+ 'ST' => OpenSSL::ASN1::UTF8STRING,
+ 'L' => OpenSSL::ASN1::UTF8STRING
+ }.freeze
+
+ attr_reader :private_key, :common_name, :names, :subject
+
+ def_delegators :csr, :to_pem, :to_der
+
+ def initialize(common_name: nil, names: [], private_key: generate_private_key, subject: {}, digest: DEFAULT_DIGEST.new)
+ @digest = digest
+ @private_key = private_key
+ @subject = normalize_subject(subject)
+ @common_name = common_name || @subject[SUBJECT_KEYS[:common_name]] || @subject[:common_name]
+ @names = names.to_a.dup
+ normalize_names
+ @subject[SUBJECT_KEYS[:common_name]] ||= @common_name
+ validate_subject
+ end
+
+ def csr
+ @csr ||= generate
+ end
+
+ private
+
+ def generate_private_key
+ OpenSSL::PKey::RSA.new(DEFAULT_KEY_LENGTH)
+ end
+
+ def normalize_subject(subject)
+ @subject = subject.each_with_object({}) do |(key, value), hash|
+ hash[SUBJECT_KEYS.fetch(key, key)] = value.to_s
+ end
+ end
+
+ def normalize_names
+ if @common_name
+ @names.unshift(@common_name) unless @names.include?(@common_name)
+ else
+ raise ArgumentError, 'No common name and no list of names given' if @names.empty?
+ @common_name = @names.first
+ end
+ end
+
+ def validate_subject
+ validate_subject_attributes
+ validate_subject_common_name
+ end
+
+ def validate_subject_attributes
+ extra_keys = @subject.keys - SUBJECT_KEYS.keys - SUBJECT_KEYS.values
+ return if extra_keys.empty?
+ raise ArgumentError, "Unexpected subject attributes given: #{extra_keys.inspect}"
+ end
+
+ def validate_subject_common_name
+ return if @common_name == @subject[SUBJECT_KEYS[:common_name]]
+ raise ArgumentError, 'Conflicting common name given in arguments and subject'
+ end
+
+ def generate
+ OpenSSL::X509::Request.new.tap do |csr|
+ csr.public_key = @private_key.public_key
+ csr.subject = generate_subject
+ csr.version = 2
+ add_extension(csr)
+ csr.sign @private_key, @digest
+ end
+ end
+
+ def generate_subject
+ OpenSSL::X509::Name.new(
+ @subject.map {|name, value|
+ [name, value, SUBJECT_TYPES[name]]
+ }
+ )
+ end
+
+ def add_extension(csr)
+ return if @names.size <= 1
+
+ extension = OpenSSL::X509::ExtensionFactory.new.create_extension(
+ 'subjectAltName', @names.map { |name| "DNS:#{name}" }.join(', '), false
+ )
+ csr.add_attribute(
+ OpenSSL::X509::Attribute.new(
+ 'extReq',
+ OpenSSL::ASN1::Set.new([OpenSSL::ASN1::Sequence.new([extension])])
+ )
+ )
+ end
+end
diff --git a/vendor/acme-client/lib/acme/client/crypto.rb b/vendor/acme-client/lib/acme/client/crypto.rb
new file mode 100644
index 0000000..dfa5cdc
--- /dev/null
+++ b/vendor/acme-client/lib/acme/client/crypto.rb
@@ -0,0 +1,98 @@
+class Acme::Client::Crypto
+ attr_reader :private_key
+
+ def initialize(private_key)
+ @private_key = private_key
+ end
+
+ def generate_signed_jws(header:, payload:)
+ header = { typ: 'JWT', alg: jws_alg, jwk: jwk }.merge(header)
+
+ encoded_header = urlsafe_base64(header.to_json)
+ encoded_payload = urlsafe_base64(payload.to_json)
+ signature_data = "#{encoded_header}.#{encoded_payload}"
+
+ signature = private_key.sign digest, signature_data
+ encoded_signature = urlsafe_base64(signature)
+
+ {
+ protected: encoded_header,
+ payload: encoded_payload,
+ signature: encoded_signature
+ }.to_json
+ end
+
+ def thumbprint
+ urlsafe_base64 digest.digest(jwk.to_json)
+ end
+
+ def digest
+ OpenSSL::Digest::SHA256.new
+ end
+
+ def urlsafe_base64(data)
+ Base64.urlsafe_encode64(data).sub(/[\s=]*\z/, '')
+ end
+
+ private
+
+ def jws_alg
+ { 'RSA' => 'RS256', 'EC' => 'ES256' }.fetch(jwk[:kty])
+ end
+
+ def jwk
+ @jwk ||= case private_key
+ when OpenSSL::PKey::RSA
+ rsa_jwk
+ when OpenSSL::PKey::EC
+ ec_jwk
+ else
+ raise ArgumentError, "Can't handle #{private_key} as private key, only OpenSSL::PKey::RSA and OpenSSL::PKey::EC"
+ end
+ end
+
+ def rsa_jwk
+ {
+ e: urlsafe_base64(public_key.e.to_s(2)),
+ kty: 'RSA',
+ n: urlsafe_base64(public_key.n.to_s(2))
+ }
+ end
+
+ def ec_jwk
+ {
+ crv: curve_name,
+ kty: 'EC',
+ x: urlsafe_base64(coordinates[:x].to_s(2)),
+ y: urlsafe_base64(coordinates[:y].to_s(2))
+ }
+ end
+
+ def curve_name
+ {
+ 'prime256v1' => 'P-256',
+ 'secp384r1' => 'P-384',
+ 'secp521r1' => 'P-521'
+ }.fetch(private_key.group.curve_name) { raise ArgumentError, 'Unknown EC curve' }
+ end
+
+ # rubocop:disable Metrics/AbcSize
+ def coordinates
+ @coordinates ||= begin
+ hex = public_key.to_bn.to_s(16)
+ data_len = hex.length - 2
+ hex_x = hex[2, data_len / 2]
+ hex_y = hex[2 + data_len / 2, data_len / 2]
+
+ {
+ x: OpenSSL::BN.new([hex_x].pack('H*'), 2),
+ y: OpenSSL::BN.new([hex_y].pack('H*'), 2)
+ }
+ end
+ end
+ # rubocop:enable Metrics/AbcSize
+
+ def public_key
+ @public_key ||= private_key.public_key
+ end
+end
diff --git a/vendor/acme-client/lib/acme/client/error.rb b/vendor/acme-client/lib/acme/client/error.rb
new file mode 100644
index 0000000..2b35623
--- /dev/null
+++ b/vendor/acme-client/lib/acme/client/error.rb
@@ -0,0 +1,16 @@
+class Acme::Client::Error < StandardError
+ class NotFound < Acme::Client::Error; end
+ class BadCSR < Acme::Client::Error; end
+ class BadNonce < Acme::Client::Error; end
+ class Connection < Acme::Client::Error; end
+ class Dnssec < Acme::Client::Error; end
+ class Malformed < Acme::Client::Error; end
+ class ServerInternal < Acme::Client::Error; end
+ class Acme::Tls < Acme::Client::Error; end
+ class Unauthorized < Acme::Client::Error; end
+ class UnknownHost < Acme::Client::Error; end
+ class Timeout < Acme::Client::Error; end
+ class RateLimited < Acme::Client::Error; end
+ class RejectedIdentifier < Acme::Client::Error; end
+ class UnsupportedIdentifier < Acme::Client::Error; end
+end
diff --git a/vendor/acme-client/lib/acme/client/faraday_middleware.rb b/vendor/acme-client/lib/acme/client/faraday_middleware.rb
new file mode 100644
index 0000000..21e29c9
--- /dev/null
+++ b/vendor/acme-client/lib/acme/client/faraday_middleware.rb
@@ -0,0 +1,123 @@
+# frozen_string_literal: true
+
+class Acme::Client::FaradayMiddleware < Faraday::Middleware
+ attr_reader :env, :response, :client
+
+ repo_url = 'https://github.com/unixcharles/acme-client'
+ USER_AGENT = "Acme::Client v#{Acme::Client::VERSION} (#{repo_url})".freeze
+
+ def initialize(app, client:)
+ super(app)
+ @client = client
+ end
+
+ def call(env)
+ @env = env
+ @env[:request_headers]['User-Agent'] = USER_AGENT
+ @env.body = crypto.generate_signed_jws(header: { nonce: pop_nonce }, payload: env.body)
+ @app.call(env).on_complete { |response_env| on_complete(response_env) }
+ rescue Faraday::TimeoutError
+ raise Acme::Client::Error::Timeout
+ end
+
+ def on_complete(env)
+ @env = env
+
+ raise_on_not_found!
+ store_nonce
+ env.body = decode_body
+ env.response_headers['Link'] = decode_link_headers
+
+ return if env.success?
+
+ raise_on_error!
+ end
+
+ private
+
+ def raise_on_not_found!
+ raise Acme::Client::Error::NotFound, env.url.to_s if env.status == 404
+ end
+
+ def raise_on_error!
+ raise error_class, error_message
+ end
+
+ def error_message
+ if env.body.is_a? Hash
+ env.body['detail']
+ else
+ "Error message: #{env.body}"
+ end
+ end
+
+ def error_class
+ if error_name && !error_name.empty? && Acme::Client::Error.const_defined?(error_name)
+ Object.const_get("Acme::Client::Error::#{error_name}")
+ else
+ Acme::Client::Error
+ end
+ end
+
+ def error_name
+ @error_name ||= begin
+ return unless env.body.is_a?(Hash)
+ return unless env.body.key?('type')
+
+ env.body['type'].gsub('urn:acme:error:', '').split(/[_-]/).map(&:capitalize).join
+ end
+ end
+
+ def decode_body
+ content_type = env.response_headers['Content-Type']
+
+ if content_type == 'application/json' || content_type == 'application/problem+json'
+ JSON.load(env.body)
+ else
+ env.body
+ end
+ end
+
+ LINK_MATCH = /<(.*?)>;rel="([\w-]+)"/
+
+ def decode_link_headers
+ return unless env.response_headers.key?('Link')
+ link_header = env.response_headers['Link']
+
+ links = link_header.split(', ').map { |entry|
+ _, link, name = *entry.match(LINK_MATCH)
+ [name, link]
+ }
+
+ Hash[*links.flatten]
+ end
+
+ def store_nonce
+ nonces << env.response_headers['replay-nonce']
+ end
+
+ def pop_nonce
+ if nonces.empty?
+ get_nonce
+ else
+ nonces.pop
+ end
+ end
+
+ def get_nonce
+ response = Faraday.head(env.url, nil, 'User-Agent' => USER_AGENT)
+ response.headers['replay-nonce']
+ end
+
+ def nonces
+ client.nonces
+ end
+
+ def private_key
+ client.private_key
+ end
+
+ def crypto
+ @crypto ||= Acme::Client::Crypto.new(private_key)
+ end
+end
diff --git a/vendor/acme-client/lib/acme/client/resources.rb b/vendor/acme-client/lib/acme/client/resources.rb
new file mode 100644
index 0000000..ad55688
--- /dev/null
+++ b/vendor/acme-client/lib/acme/client/resources.rb
@@ -0,0 +1,5 @@
+module Acme::Client::Resources; end
+
+require 'acme/client/resources/registration'
+require 'acme/client/resources/challenges'
+require 'acme/client/resources/authorization'
diff --git a/vendor/acme-client/lib/acme/client/resources/authorization.rb b/vendor/acme-client/lib/acme/client/resources/authorization.rb
new file mode 100644
index 0000000..9ca2e76
--- /dev/null
+++ b/vendor/acme-client/lib/acme/client/resources/authorization.rb
@@ -0,0 +1,44 @@
+class Acme::Client::Resources::Authorization
+ HTTP01 = Acme::Client::Resources::Challenges::HTTP01
+ DNS01 = Acme::Client::Resources::Challenges::DNS01
+ TLSSNI01 = Acme::Client::Resources::Challenges::TLSSNI01
+
+ attr_reader :client, :uri, :domain, :status, :expires, :http01, :dns01, :tls_sni01
+
+ def initialize(client, uri, response)
+ @client = client
+ @uri = uri
+ assign_attributes(response.body)
+ end
+
+ def verify_status
+ response = @client.connection.get(@uri)
+
+ assign_attributes(response.body)
+ status
+ end
+
+ private
+
+ def assign_attributes(body)
+ @expires = Time.iso8601(body['expires']) if body.key? 'expires'
+ @domain = body['identifier']['value']
+ @status = body['status']
+ assign_challenges(body['challenges'])
+ end
+
+ def assign_challenges(challenges)
+ challenges.each do |attributes|
+ challenge = case attributes.fetch('type')
+ when 'http-01'
+ @http01 ||= HTTP01.new(self)
+ when 'dns-01'
+ @dns01 ||= DNS01.new(self)
+ when 'tls-sni-01'
+ @tls_sni01 ||= TLSSNI01.new(self)
+ end
+
+ challenge.assign_attributes(attributes) if challenge
+ end
+ end
+end
diff --git a/vendor/acme-client/lib/acme/client/resources/challenges.rb b/vendor/acme-client/lib/acme/client/resources/challenges.rb
new file mode 100644
index 0000000..ec92d47
--- /dev/null
+++ b/vendor/acme-client/lib/acme/client/resources/challenges.rb
@@ -0,0 +1,6 @@
+module Acme::Client::Resources::Challenges; end
+
+require 'acme/client/resources/challenges/base'
+require 'acme/client/resources/challenges/http01'
+require 'acme/client/resources/challenges/dns01'
+require 'acme/client/resources/challenges/tls_sni01'
diff --git a/vendor/acme-client/lib/acme/client/resources/challenges/base.rb b/vendor/acme-client/lib/acme/client/resources/challenges/base.rb
new file mode 100644
index 0000000..c78c74e
--- /dev/null
+++ b/vendor/acme-client/lib/acme/client/resources/challenges/base.rb
@@ -0,0 +1,43 @@
+class Acme::Client::Resources::Challenges::Base
+ attr_reader :authorization, :status, :uri, :token, :error
+
+ def initialize(authorization)
+ @authorization = authorization
+ end
+
+ def client
+ authorization.client
+ end
+
+ def verify_status
+ authorization.verify_status
+
+ status
+ end
+
+ def request_verification
+ response = client.connection.post(@uri, resource: 'challenge', type: challenge_type, keyAuthorization: authorization_key)
+ response.success?
+ end
+
+ def assign_attributes(attributes)
+ @status = attributes.fetch('status', 'pending')
+ @uri = attributes.fetch('uri')
+ @token = attributes.fetch('token')
+ @error = attributes['error']
+ end
+
+ private
+
+ def challenge_type
+ self.class::CHALLENGE_TYPE
+ end
+
+ def authorization_key
+ "#{token}.#{crypto.thumbprint}"
+ end
+
+ def crypto
+ @crypto ||= Acme::Client::Crypto.new(client.private_key)
+ end
+end
diff --git a/vendor/acme-client/lib/acme/client/resources/challenges/dns01.rb b/vendor/acme-client/lib/acme/client/resources/challenges/dns01.rb
new file mode 100644
index 0000000..543f438
--- /dev/null
+++ b/vendor/acme-client/lib/acme/client/resources/challenges/dns01.rb
@@ -0,0 +1,19 @@
+# frozen_string_literal: true
+
+class Acme::Client::Resources::Challenges::DNS01 < Acme::Client::Resources::Challenges::Base
+ CHALLENGE_TYPE = 'dns-01'.freeze
+ RECORD_NAME = '_acme-challenge'.freeze
+ RECORD_TYPE = 'TXT'.freeze
+
+ def record_name
+ RECORD_NAME
+ end
+
+ def record_type
+ RECORD_TYPE
+ end
+
+ def record_content
+ crypto.urlsafe_base64(crypto.digest.digest(authorization_key))
+ end
+end
diff --git a/vendor/acme-client/lib/acme/client/resources/challenges/http01.rb b/vendor/acme-client/lib/acme/client/resources/challenges/http01.rb
new file mode 100644
index 0000000..4966091
--- /dev/null
+++ b/vendor/acme-client/lib/acme/client/resources/challenges/http01.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class Acme::Client::Resources::Challenges::HTTP01 < Acme::Client::Resources::Challenges::Base
+ CHALLENGE_TYPE = 'http-01'.freeze
+ CONTENT_TYPE = 'text/plain'.freeze
+
+ def content_type
+ CONTENT_TYPE
+ end
+
+ def file_content
+ authorization_key
+ end
+
+ def filename
+ ".well-known/acme-challenge/#{token}"
+ end
+end
diff --git a/vendor/acme-client/lib/acme/client/resources/challenges/tls_sni01.rb b/vendor/acme-client/lib/acme/client/resources/challenges/tls_sni01.rb
new file mode 100644
index 0000000..8f455f5
--- /dev/null
+++ b/vendor/acme-client/lib/acme/client/resources/challenges/tls_sni01.rb
@@ -0,0 +1,24 @@
+# frozen_string_literal: true
+
+class Acme::Client::Resources::Challenges::TLSSNI01 < Acme::Client::Resources::Challenges::Base
+ CHALLENGE_TYPE = 'tls-sni-01'.freeze
+
+ def hostname
+ digest = crypto.digest.hexdigest(authorization_key)
+ "#{digest[0..31]}.#{digest[32..64]}.acme.invalid"
+ end
+
+ def certificate
+ self_sign_certificate.certificate
+ end
+
+ def private_key
+ self_sign_certificate.private_key
+ end
+
+ private
+
+ def self_sign_certificate
+ @self_sign_certificate ||= Acme::Client::SelfSignCertificate.new(subject_alt_names: [hostname])
+ end
+end
diff --git a/vendor/acme-client/lib/acme/client/resources/registration.rb b/vendor/acme-client/lib/acme/client/resources/registration.rb
new file mode 100644
index 0000000..b7a4c11
--- /dev/null
+++ b/vendor/acme-client/lib/acme/client/resources/registration.rb
@@ -0,0 +1,37 @@
+class Acme::Client::Resources::Registration
+ attr_reader :id, :key, :contact, :uri, :next_uri, :recover_uri, :term_of_service_uri
+
+ def initialize(client, response)
+ @client = client
+ @uri = response.headers['location']
+ assign_links(response.headers['Link'])
+ assign_attributes(response.body)
+ end
+
+ def get_terms
+ return unless @term_of_service_uri
+
+ @client.connection.get(@term_of_service_uri).body
+ end
+
+ def agree_terms
+ return true unless @term_of_service_uri
+
+ response = @client.connection.post(@uri, resource: 'reg', agreement: @term_of_service_uri)
+ response.success?
+ end
+
+ private
+
+ def assign_links(links)
+ @next_uri = links['next']
+ @recover_uri = links['recover']
+ @term_of_service_uri = links['terms-of-service']
+ end
+
+ def assign_attributes(body)
+ @id = body['id']
+ @key = body['key']
+ @contact = body['contact']
+ end
+end
diff --git a/vendor/acme-client/lib/acme/client/self_sign_certificate.rb b/vendor/acme-client/lib/acme/client/self_sign_certificate.rb
new file mode 100644
index 0000000..2e7d98c
--- /dev/null
+++ b/vendor/acme-client/lib/acme/client/self_sign_certificate.rb
@@ -0,0 +1,60 @@
+class Acme::Client::SelfSignCertificate
+ attr_reader :private_key, :subject_alt_names, :not_before, :not_after
+
+ extend Forwardable
+ def_delegators :certificate, :to_pem, :to_der
+
+ def initialize(subject_alt_names:, not_before: default_not_before, not_after: default_not_after, private_key: generate_private_key)
+ @private_key = private_key
+ @subject_alt_names = subject_alt_names
+ @not_before = not_before
+ @not_after = not_after
+ end
+
+ def certificate
+ @certificate ||= begin
+ certificate = generate_certificate
+
+ extension_factory = generate_extension_factory(certificate)
+ subject_alt_name_entry = subject_alt_names.map { |d| "DNS: #{d}" }.join(',')
+ subject_alt_name_extension = extension_factory.create_extension('subjectAltName', subject_alt_name_entry)
+ certificate.add_extension(subject_alt_name_extension)
+
+ certificate.sign(private_key, digest)
+ end
+ end
+
+ private
+
+ def generate_private_key
+ OpenSSL::PKey::RSA.new(2048)
+ end
+
+ def default_not_before
+ Time.now - 3600
+ end
+
+ def default_not_after
+ Time.now + 30 * 24 * 3600
+ end
+
+ def digest
+ OpenSSL::Digest::SHA256.new
+ end
+
+ def generate_certificate
+ certificate = OpenSSL::X509::Certificate.new
+ certificate.not_before = not_before
+ certificate.not_after = not_after
+ certificate.public_key = private_key.public_key
+ certificate.version = 2
+ certificate
+ end
+
+ def generate_extension_factory(certificate)
+ extension_factory = OpenSSL::X509::ExtensionFactory.new
+ extension_factory.subject_certificate = certificate
+ extension_factory.issuer_certificate = certificate
+ extension_factory
+ end
+end
diff --git a/vendor/acme-client/lib/acme/client/version.rb b/vendor/acme-client/lib/acme/client/version.rb
new file mode 100644
index 0000000..c989c12
--- /dev/null
+++ b/vendor/acme-client/lib/acme/client/version.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+module Acme
+ class Client
+ VERSION = '0.4.1'.freeze
+ end
+end
diff --git a/vendor/base32/LICENSE b/vendor/base32/LICENSE
new file mode 100644
index 0000000..cdc04d9
--- /dev/null
+++ b/vendor/base32/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2007-2011 Samuel Tesla
+
+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.
diff --git a/vendor/base32/base32.gemspec b/vendor/base32/base32.gemspec
new file mode 100644
index 0000000..4e84cea
--- /dev/null
+++ b/vendor/base32/base32.gemspec
@@ -0,0 +1,10 @@
+$:.push File.expand_path('../lib', __FILE__)
+
+Gem::Specification.new do |s|
+ s.name = 'base32'
+ s.version = '0.3.2'
+ s.authors = ['Samuel Tesla']
+ s.email = 'samuel.tesla@gmail.com'
+ s.summary = 'Ruby extension for base32 encoding and decoding'
+ s.require_paths = ['lib']
+end
diff --git a/vendor/base32/lib/base32.rb b/vendor/base32/lib/base32.rb
new file mode 100644
index 0000000..4df2b1a
--- /dev/null
+++ b/vendor/base32/lib/base32.rb
@@ -0,0 +1,67 @@
+require 'openssl'
+
+# Module for encoding and decoding in Base32 per RFC 3548
+module Base32
+ TABLE = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'.freeze
+
+ class Chunk
+ def initialize(bytes)
+ @bytes = bytes
+ end
+
+ def decode
+ bytes = @bytes.take_while {|c| c != 61} # strip padding
+ n = (bytes.length * 5.0 / 8.0).floor
+ p = bytes.length < 8 ? 5 - (n * 8) % 5 : 0
+ c = bytes.inject(0) {|m,o| (m << 5) + Base32.table.index(o.chr)} >> p
+ (0..n-1).to_a.reverse.collect {|i| ((c >> i * 8) & 0xff).chr}
+ end
+
+ def encode
+ n = (@bytes.length * 8.0 / 5.0).ceil
+ p = n < 8 ? 5 - (@bytes.length * 8) % 5 : 0
+ c = @bytes.inject(0) {|m,o| (m << 8) + o} << p
+ [(0..n-1).to_a.reverse.collect {|i| Base32.table[(c >> i * 5) & 0x1f].chr},
+ ("=" * (8-n))]
+ end
+ end
+
+ def self.chunks(str, size)
+ result = []
+ bytes = str.bytes
+ while bytes.any? do
+ result << Chunk.new(bytes.take(size))
+ bytes = bytes.drop(size)
+ end
+ result
+ end
+
+ def self.encode(str)
+ chunks(str, 5).collect(&:encode).flatten.join
+ end
+
+ def self.decode(str)
+ chunks(str, 8).collect(&:decode).flatten.join
+ end
+
+ def self.random_base32(length=16, padding=true)
+ random = ''
+ OpenSSL::Random.random_bytes(length).each_byte do |b|
+ random << self.table[b % 32]
+ end
+ padding ? random.ljust((length / 8.0).ceil * 8, '=') : random
+ end
+
+ def self.table=(table)
+ raise ArgumentError, "Table must have 32 unique characters" unless self.table_valid?(table)
+ @table = table
+ end
+
+ def self.table
+ @table || TABLE
+ end
+
+ def self.table_valid?(table)
+ table.bytes.to_a.size == 32 && table.bytes.to_a.uniq.size == 32
+ end
+end
diff --git a/vendor/certificate_authority/certificate_authority.gemspec b/vendor/certificate_authority/certificate_authority.gemspec
index b7e8676..71ffb4a 100644
--- a/vendor/certificate_authority/certificate_authority.gemspec
+++ b/vendor/certificate_authority/certificate_authority.gemspec
@@ -2,15 +2,17 @@
# DO NOT EDIT THIS FILE DIRECTLY
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
# -*- encoding: utf-8 -*-
+# stub: certificate_authority 0.2.0 ruby lib
Gem::Specification.new do |s|
s.name = "certificate_authority"
s.version = "0.2.0"
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
+ s.require_paths = ["lib"]
s.authors = ["Chris Chandler"]
- s.date = "2012-09-16"
- s.email = "chris@flatterline.com"
+ s.date = "2016-06-21"
+ s.email = "squanderingtime@gmail.com"
s.extra_rdoc_files = [
"README.rdoc"
]
@@ -24,6 +26,7 @@ Gem::Specification.new do |s|
"lib/certificate_authority.rb",
"lib/certificate_authority/certificate.rb",
"lib/certificate_authority/certificate_revocation_list.rb",
+ "lib/certificate_authority/core_extensions.rb",
"lib/certificate_authority/distinguished_name.rb",
"lib/certificate_authority/extensions.rb",
"lib/certificate_authority/key_material.rb",
@@ -33,6 +36,7 @@ Gem::Specification.new do |s|
"lib/certificate_authority/serial_number.rb",
"lib/certificate_authority/signing_entity.rb",
"lib/certificate_authority/signing_request.rb",
+ "lib/certificate_authority/validations.rb",
"lib/tasks/certificate_authority.rake",
"spec/samples/certs/DigiCertHighAssuranceEVCA-1.pem",
"spec/samples/certs/apple_wwdr_issued_cert.pem",
@@ -63,27 +67,20 @@ Gem::Specification.new do |s|
]
s.homepage = "https://github.com/cchandler/certificate_authority"
s.licenses = ["MIT"]
- s.require_paths = ["lib"]
- s.rubygems_version = "1.8.15"
+ s.rubygems_version = "2.2.2"
s.summary = "Ruby gem for managing the core functions outlined in RFC-3280 for PKI"
if s.respond_to? :specification_version then
- s.specification_version = 3
+ s.specification_version = 4
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
- s.add_runtime_dependency(%q<activemodel>, [">= 3.0.6"])
- s.add_runtime_dependency(%q<activesupport>, [">= 3.0.6"])
s.add_development_dependency(%q<rspec>, [">= 0"])
s.add_development_dependency(%q<jeweler>, [">= 1.5.2"])
else
- s.add_dependency(%q<activemodel>, [">= 3.0.6"])
- s.add_dependency(%q<activesupport>, [">= 3.0.6"])
s.add_dependency(%q<rspec>, [">= 0"])
s.add_dependency(%q<jeweler>, [">= 1.5.2"])
end
else
- s.add_dependency(%q<activemodel>, [">= 3.0.6"])
- s.add_dependency(%q<activesupport>, [">= 3.0.6"])
s.add_dependency(%q<rspec>, [">= 0"])
s.add_dependency(%q<jeweler>, [">= 1.5.2"])
end
diff --git a/vendor/certificate_authority/lib/certificate_authority.rb b/vendor/certificate_authority/lib/certificate_authority.rb
index a697c1b..c52e4b6 100644
--- a/vendor/certificate_authority/lib/certificate_authority.rb
+++ b/vendor/certificate_authority/lib/certificate_authority.rb
@@ -2,11 +2,12 @@ $:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) ||
#Exterior requirements
require 'openssl'
-require 'active_model'
#Internal modules
+require 'certificate_authority/core_extensions'
require 'certificate_authority/signing_entity'
require 'certificate_authority/revocable'
+require 'certificate_authority/validations'
require 'certificate_authority/distinguished_name'
require 'certificate_authority/serial_number'
require 'certificate_authority/key_material'
diff --git a/vendor/certificate_authority/lib/certificate_authority/certificate.rb b/vendor/certificate_authority/lib/certificate_authority/certificate.rb
index 496d91e..cdf432c 100644
--- a/vendor/certificate_authority/lib/certificate_authority/certificate.rb
+++ b/vendor/certificate_authority/lib/certificate_authority/certificate.rb
@@ -1,6 +1,6 @@
module CertificateAuthority
class Certificate
- include ActiveModel::Validations
+ include Validations
include Revocable
attr_accessor :distinguished_name
@@ -15,7 +15,7 @@ module CertificateAuthority
attr_accessor :parent
- validate do |certificate|
+ def validate
errors.add :base, "Distinguished name must be valid" unless distinguished_name.valid?
errors.add :base, "Key material must be valid" unless key_material.valid?
errors.add :base, "Serial number must be valid" unless serial_number.valid?
@@ -32,8 +32,8 @@ module CertificateAuthority
self.distinguished_name = DistinguishedName.new
self.serial_number = SerialNumber.new
self.key_material = MemoryKeyMaterial.new
- self.not_before = Time.now
- self.not_after = Time.now + 60 * 60 * 24 * 365 # One year
+ self.not_before = Date.today.utc
+ self.not_after = Date.today.advance(:years => 1).utc
self.parent = self
self.extensions = load_extensions()
diff --git a/vendor/certificate_authority/lib/certificate_authority/certificate_revocation_list.rb b/vendor/certificate_authority/lib/certificate_authority/certificate_revocation_list.rb
index c84d588..cb3aaf7 100644
--- a/vendor/certificate_authority/lib/certificate_authority/certificate_revocation_list.rb
+++ b/vendor/certificate_authority/lib/certificate_authority/certificate_revocation_list.rb
@@ -1,20 +1,22 @@
module CertificateAuthority
class CertificateRevocationList
- include ActiveModel::Validations
+ include Validations
attr_accessor :certificates
attr_accessor :parent
attr_accessor :crl_body
attr_accessor :next_update
+ attr_accessor :last_update_skew_seconds
- validate do |crl|
- errors.add :next_update, "Next update must be a positive value" if crl.next_update < 0
- errors.add :parent, "A parent entity must be set" if crl.parent.nil?
+ def validate
+ errors.add :next_update, "Next update must be a positive value" if self.next_update < 0
+ errors.add :parent, "A parent entity must be set" if self.parent.nil?
end
def initialize
self.certificates = []
self.next_update = 60 * 60 * 4 # 4 hour default
+ self.last_update_skew_seconds = 0
end
def <<(revocable)
@@ -54,7 +56,7 @@ module CertificateAuthority
end
crl.version = 1
- crl.last_update = Time.now
+ crl.last_update = Time.now - self.last_update_skew_seconds
crl.next_update = Time.now + self.next_update
signing_cert = OpenSSL::X509::Certificate.new(self.parent.to_pem)
diff --git a/vendor/certificate_authority/lib/certificate_authority/core_extensions.rb b/vendor/certificate_authority/lib/certificate_authority/core_extensions.rb
new file mode 100644
index 0000000..0508f9a
--- /dev/null
+++ b/vendor/certificate_authority/lib/certificate_authority/core_extensions.rb
@@ -0,0 +1,46 @@
+#
+# ActiveSupport has these modifications. Now that we don't use ActiveSupport,
+# these are added here as a kindness.
+#
+
+require 'date'
+
+unless nil.respond_to?(:blank?)
+ class NilClass
+ def blank?
+ true
+ end
+ end
+end
+
+unless String.respond_to?(:blank?)
+ class String
+ def blank?
+ self.empty?
+ end
+ end
+end
+
+class Date
+
+ def today
+ t = Time.now.utc
+ Date.new(t.year, t.month, t.day)
+ end
+
+ def utc
+ self.to_datetime.to_time.utc
+ end
+
+ unless Date.respond_to?(:advance)
+ def advance(options)
+ options = options.dup
+ d = self
+ d = d >> options.delete(:years) * 12 if options[:years]
+ d = d >> options.delete(:months) if options[:months]
+ d = d + options.delete(:weeks) * 7 if options[:weeks]
+ d = d + options.delete(:days) if options[:days]
+ d
+ end
+ end
+end
diff --git a/vendor/certificate_authority/lib/certificate_authority/distinguished_name.rb b/vendor/certificate_authority/lib/certificate_authority/distinguished_name.rb
index 32d9c1e..3b83582 100644
--- a/vendor/certificate_authority/lib/certificate_authority/distinguished_name.rb
+++ b/vendor/certificate_authority/lib/certificate_authority/distinguished_name.rb
@@ -1,8 +1,12 @@
module CertificateAuthority
class DistinguishedName
- include ActiveModel::Validations
+ include Validations
- validates_presence_of :common_name
+ def validate
+ if self.common_name.nil? || self.common_name.empty?
+ errors.add :common_name, 'cannot be blank'
+ end
+ end
attr_accessor :common_name
alias :cn :common_name
diff --git a/vendor/certificate_authority/lib/certificate_authority/extensions.rb b/vendor/certificate_authority/lib/certificate_authority/extensions.rb
index 7bc4fab..2b9478b 100644
--- a/vendor/certificate_authority/lib/certificate_authority/extensions.rb
+++ b/vendor/certificate_authority/lib/certificate_authority/extensions.rb
@@ -31,13 +31,20 @@ module CertificateAuthority
OPENSSL_IDENTIFIER = "basicConstraints"
include ExtensionAPI
- include ActiveModel::Validations
+ include Validations
attr_accessor :critical
attr_accessor :ca
attr_accessor :path_len
- validates :critical, :inclusion => [true,false]
- validates :ca, :inclusion => [true,false]
+
+ def validate
+ unless [true, false].include? self.critical
+ errors.add :critical, 'must be true or false'
+ end
+ unless [true, false].include? self.ca
+ errors.add :ca, 'must be true or false'
+ end
+ end
def initialize
@critical = false
diff --git a/vendor/certificate_authority/lib/certificate_authority/key_material.rb b/vendor/certificate_authority/lib/certificate_authority/key_material.rb
index 1fd4dd9..ae3a530 100644
--- a/vendor/certificate_authority/lib/certificate_authority/key_material.rb
+++ b/vendor/certificate_authority/lib/certificate_authority/key_material.rb
@@ -38,7 +38,7 @@ module CertificateAuthority
class MemoryKeyMaterial
include KeyMaterial
- include ActiveModel::Validations
+ include Validations
attr_accessor :keypair
attr_accessor :private_key
@@ -47,11 +47,13 @@ module CertificateAuthority
def initialize
end
- validates_each :private_key do |record, attr, value|
- record.errors.add :private_key, "cannot be blank" if record.private_key.nil?
- end
- validates_each :public_key do |record, attr, value|
- record.errors.add :public_key, "cannot be blank" if record.public_key.nil?
+ def validate
+ if private_key.nil?
+ errors.add :private_key, "cannot be blank"
+ end
+ if public_key.nil?
+ errors.add :public_key, "cannot be blank"
+ end
end
def is_in_hardware?
@@ -80,10 +82,10 @@ module CertificateAuthority
class SigningRequestKeyMaterial
include KeyMaterial
- include ActiveModel::Validations
+ include Validations
- validates_each :public_key do |record, attr, value|
- record.errors.add :public_key, "cannot be blank" if record.public_key.nil?
+ def validate
+ errors.add :public_key, "cannot be blank" if public_key.nil?
end
attr_accessor :public_key
diff --git a/vendor/certificate_authority/lib/certificate_authority/ocsp_handler.rb b/vendor/certificate_authority/lib/certificate_authority/ocsp_handler.rb
index e101f98..0f2661c 100644
--- a/vendor/certificate_authority/lib/certificate_authority/ocsp_handler.rb
+++ b/vendor/certificate_authority/lib/certificate_authority/ocsp_handler.rb
@@ -68,7 +68,7 @@ module CertificateAuthority
## DEPRECATED
class OCSPHandler
- include ActiveModel::Validations
+ include Validations
attr_accessor :ocsp_request
attr_accessor :certificate_ids
@@ -78,10 +78,10 @@ module CertificateAuthority
attr_accessor :ocsp_response_body
- validate do |crl|
+ def validate
errors.add :parent, "A parent entity must be set" if parent.nil?
+ all_certificates_available
end
- validate :all_certificates_available
def initialize
self.certificates = {}
diff --git a/vendor/certificate_authority/lib/certificate_authority/pkcs11_key_material.rb b/vendor/certificate_authority/lib/certificate_authority/pkcs11_key_material.rb
index d4ebc47..8a83f0e 100644
--- a/vendor/certificate_authority/lib/certificate_authority/pkcs11_key_material.rb
+++ b/vendor/certificate_authority/lib/certificate_authority/pkcs11_key_material.rb
@@ -1,8 +1,6 @@
module CertificateAuthority
class Pkcs11KeyMaterial
include KeyMaterial
- include ActiveModel::Validations
- include ActiveModel::Serialization
attr_accessor :engine
attr_accessor :token_id
diff --git a/vendor/certificate_authority/lib/certificate_authority/serial_number.rb b/vendor/certificate_authority/lib/certificate_authority/serial_number.rb
index b9a43cc..99f3002 100644
--- a/vendor/certificate_authority/lib/certificate_authority/serial_number.rb
+++ b/vendor/certificate_authority/lib/certificate_authority/serial_number.rb
@@ -2,12 +2,18 @@ require 'securerandom'
module CertificateAuthority
class SerialNumber
- include ActiveModel::Validations
+ include Validations
include Revocable
attr_accessor :number
- validates :number, :presence => true, :numericality => {:greater_than => 0}
+ def validate
+ if self.number.nil?
+ errors.add :number, "must not be empty"
+ elsif self.number.to_i <= 0
+ errors.add :number, "must be greater than zero"
+ end
+ end
def initialize
self.number = SecureRandom.random_number(2**128-1)
diff --git a/vendor/certificate_authority/lib/certificate_authority/validations.rb b/vendor/certificate_authority/lib/certificate_authority/validations.rb
new file mode 100644
index 0000000..a429c96
--- /dev/null
+++ b/vendor/certificate_authority/lib/certificate_authority/validations.rb
@@ -0,0 +1,31 @@
+#
+# This is a super simple replacement for ActiveSupport::Validations
+#
+
+module CertificateAuthority
+ class Errors < Array
+ def add(symbol, msg)
+ self.push([symbol, msg])
+ end
+ def full_messages
+ self.map {|i| i[0].to_s + ": " + i[1]}.join("\n")
+ end
+ end
+
+ module Validations
+ def valid?
+ @errors = Errors.new
+ validate
+ errors.empty?
+ end
+
+ # must be overridden
+ def validate
+ raise NotImplementedError
+ end
+
+ def errors
+ @errors ||= Errors.new
+ end
+ end
+end
diff --git a/vendor/rsync_command/README.md b/vendor/rsync_command/README.md
index 4b53a5c..5e44845 100644
--- a/vendor/rsync_command/README.md
+++ b/vendor/rsync_command/README.md
@@ -11,13 +11,15 @@ Installation
Usage
------------------------------------
- rsync = RsyncCommand.new(:logger => logger, :ssh => {:auth_methods => 'publickey'}, :flags => '-a')
- source = '/source/path'
+ rsync = RsyncCommand.new(:ssh => {:auth_methods => 'publickey'}, :flags => '-a')
servers = ['red', 'green', 'blue']
- rsync.asynchronously(servers) do |server|
- dest = {:user => 'root', :host => server, :path => '/dest/path'}
- rsync.exec(source, dest)
+ rsync.asynchronously(servers) do |sync, server|
+ sync.user = 'root'
+ sync.host = server
+ sync.source = '/from'
+ sync.dest = '/to'
+ sync.exec
end
if rsync.failed?
diff --git a/vendor/rsync_command/lib/rsync_command.rb b/vendor/rsync_command/lib/rsync_command.rb
index 39e5945..bdcafe0 100644
--- a/vendor/rsync_command/lib/rsync_command.rb
+++ b/vendor/rsync_command/lib/rsync_command.rb
@@ -4,6 +4,44 @@ require "rsync_command/thread_pool"
require 'monitor'
+class RsyncRunner
+ attr_accessor :logger
+ attr_accessor :source, :dest, :flags, :includes, :excludes
+ attr_accessor :user, :host
+ attr_accessor :chdir, :ssh
+ def initialize(rsync_command)
+ @logger = nil
+ @source = ""
+ @dest = ""
+ @flags = ""
+ @includes = []
+ @excludes = []
+ @rsync_command = rsync_command
+ end
+ def log(*args)
+ @logger.log(*args)
+ end
+ def valid?
+ !@source.empty? || !@dest.empty?
+ end
+ def to_hash
+ fields = [:flags, :includes, :excludes, :logger, :ssh, :chdir]
+ fields.inject({}){|hsh, i|
+ hsh[i] = self.send(i); hsh
+ }
+ end
+ def exec
+ return unless valid?
+ dest = {
+ :user => self.user,
+ :host => self.host,
+ :path => self.dest
+ }
+ src = self.source
+ @rsync_command.exec_rsync(src, dest, self.to_hash)
+ end
+end
+
class RsyncCommand
attr_accessor :failures, :logger
@@ -21,15 +59,23 @@ class RsyncCommand
def asynchronously(array, &block)
pool = ThreadPool.new
array.each do |item|
- pool.schedule(item, &block)
+ pool.schedule(RsyncRunner.new(self), item, &block)
end
pool.shutdown
end
#
+ # returns true if last exec returned a failure
+ #
+ def failed?
+ @failures && @failures.any?
+ end
+
+ #
# runs rsync, recording failures
#
- def exec(src, dest, options={})
+ def exec_rsync(src, dest, options={})
+ logger = options[:logger] || @logger
@failures.synchronize do
@failures.clear
end
@@ -37,7 +83,7 @@ class RsyncCommand
if options[:chdir]
rsync_cmd = "cd '#{options[:chdir]}'; #{rsync_cmd}"
end
- @logger.debug rsync_cmd if @logger
+ logger.debug rsync_cmd if logger
ok = system(rsync_cmd)
unless ok
@failures.synchronize do
@@ -47,13 +93,6 @@ class RsyncCommand
end
#
- # returns true if last exec returned a failure
- #
- def failed?
- @failures && @failures.any?
- end
-
- #
# build rsync command
#
def command(src, dest, options={})
@@ -70,8 +109,6 @@ class RsyncCommand
"rsync #{flags.compact.join(' ')} #{src} #{dest}"
end
- private
-
#
# Creates an rsync location if the +address+ is a hash with keys :user, :host, and :path
# (each component is optional). If +address+ is a string, we just pass it through.