Unit tests

v1
Aeris 2016-05-03 19:57:34 +02:00
parent eb82f8e1ae
commit a2c38b05b0
19 changed files with 418 additions and 196 deletions

1
.gitignore vendored
View File

@ -4,7 +4,6 @@ Gemfile.lock
.rakeTasks
.idea/
/html/
.rspec
/rakefile
/output/*.html
/db/*.sqlite3

2
.rspec 100644
View File

@ -0,0 +1,2 @@
--color
--require helpers

View File

@ -5,9 +5,21 @@ require 'yaml'
require 'cryptcheck/tls/fixture'
module CryptCheck
MAX_ANALYSIS_DURATION = 600
MAX_ANALYSIS_DURATION = 120
PARALLEL_ANALYSIS = 10
class AnalysisFailure
attr_reader :error
def initialize(error)
@error = error
end
def to_s
@error.to_s
end
end
autoload :Logger, 'cryptcheck/logger'
autoload :Tls, 'cryptcheck/tls'
module Tls
@ -50,38 +62,54 @@ module CryptCheck
def self.addresses(host)
begin
ip = IPAddr.new host
[[ip.family, ip.to_s, nil]]
return [[ip.family, ip.to_s, nil]]
rescue IPAddr::InvalidAddressError
end
::Addrinfo.getaddrinfo(host, nil, nil, :STREAM)
.collect { |a| [a.afamily, a.ip_address, host] }
end
def self.analyze_addresses(host, addresses, port, server, grade, *args, **kargs)
first = true
addresses.collect do |family, ip|
first ? (first = false) : Logger.info { '' }
key = [host, ip, port]
a = [host, family, ip, port, *args]
begin
::Addrinfo.getaddrinfo(host, nil, nil, :STREAM)
.collect { |a| [a.afamily, a.ip_address, host] }
rescue ::SocketError => e
Logger.error { "Unable to resolv #{host} : #{e}" }
[]
::Timeout::timeout MAX_ANALYSIS_DURATION do
s = if kargs.empty?
server.new *a
else
server.new *a, **kargs
end
g = grade.new s
Logger.info { '' }
g.display
[key, g]
end
rescue Exception => e
e = "Too long analysis (max #{MAX_ANALYSIS_DURATION.humanize})" if e.message == 'execution expired'
Logger.error e
[key, AnalysisFailure.new(e)]
end
end
end.to_h
end
def self.analyze_addresses(host, addresses, port, on_error = TLS_NOT_AVAILABLE, &block)
begin
::Timeout::timeout MAX_ANALYSIS_DURATION do
addresses.each { |family, ip, host| return block.call family, ip, host }
end
rescue ::Exception => e
Logger.error e
def self.analyze(host, port, server, grade, *args, **kargs)
addresses = begin
addresses host
rescue ::SocketError => e
Logger::error e
return AnalysisFailure.new "Unable to resolve #{host}"
end
on_error.call host, port
end
def self.analyze(host, port, on_error = Tls::TLS_NOT_AVAILABLE, &block)
analyze_addresses host, addresses(host), port, on_error, &block
analyze_addresses host, addresses, port, server, grade, *args, **kargs
end
def self.analyze_hosts(hosts, template, output, groups: nil, &block)
results = {}
semaphore = ::Mutex.new
::Parallel.each hosts, progress: 'Analysing', in_threads: PARALLEL_ANALYSIS, finish: lambda { |item, _, _| puts item[1] } do |description, host|
#hosts.each do |description, host|
#hosts.each do |description, host|
result = block.call host.strip
semaphore.synchronize do
if results.include? description

View File

@ -2,14 +2,6 @@ require 'socket'
module CryptCheck
module Ssh
class SshNotSupportedServer
attr_reader :host, :port
def initialize(host, port)
@host, @port = host, port
end
end
class Server
TCP_TIMEOUT = 10
class SshNotAvailableException < Exception

View File

@ -3,18 +3,8 @@ require 'parallel'
module CryptCheck
module Tls
TLS_NOT_AVAILABLE = Proc.new { |host, port|
TlsNotSupportedGrade.new TlsNotSupportedServer.new host, port
}
def self.analyze(host, port)
::CryptCheck.analyze host, port do |family, ip, host|
s = TcpServer.new family, ip, port, hostname: host
g = Grade.new s
Logger.info { '' }
g.display
g
end
::CryptCheck.analyze host, port, TcpServer, Grade
end
def self.colorize(cipher)

View File

@ -1,5 +1,18 @@
require 'openssl'
class Integer
def humanize
secs = self
[[60, :second], [60, :minute], [24, :hour], [30, :day], [12, :month]].map { |count, name|
if secs > 0
secs, n = self.divmod count
n = n.to_i
"#{n} #{name}#{n > 1 ? 's' : ''}"
end
}.compact.reverse.join(' ')
end
end
class ::OpenSSL::PKey::EC
def type
:ecc

View File

@ -1,13 +1,5 @@
module CryptCheck
module Tls
class TlsNotSupportedGrade
attr_reader :server, :score, :grade
def initialize(server)
@server, @score, @grade = server, -1, 'X'
end
end
class Grade
attr_reader :server, :protocol_score, :key_exchange_score, :cipher_strengths_score, :score, :grade, :error, :danger, :warning, :success

View File

@ -2,13 +2,7 @@ module CryptCheck
module Tls
module Https
def self.analyze(host, port=443)
::CryptCheck.analyze host, port do |family, ip, host|
s = Server.new family, ip, port, hostname: host
g = Grade.new s
Logger.info { '' }
g.display
g
end
::CryptCheck.analyze host, port, Server, Grade
end
def self.analyze_file(input, output)

View File

@ -6,7 +6,7 @@ module CryptCheck
class Server < Tls::TcpServer
attr_reader :hsts
def initialize(family, ip, port = 443, hostname: nil)
def initialize(hostname, family, ip, port=443)
super
fetch_hsts
end

View File

@ -4,14 +4,6 @@ require 'httparty'
module CryptCheck
module Tls
class TlsNotSupportedServer
attr_reader :hostname, :port
def initialize(host, port)
@hostname, @port = host, port
end
end
class Server
TCP_TIMEOUT = 10
SSL_TIMEOUT = 2*TCP_TIMEOUT
@ -25,18 +17,18 @@ module CryptCheck
end
class CipherNotAvailable < TLSException
end
class Timeout < TLSException
class Timeout < Exception
end
class TLSTimeout < TLSException
class TLSTimeout < Timeout
end
class ConnectionError < TLSException
class ConnectionError < Exception
end
attr_reader :family, :ip, :port, :hostname, :prefered_ciphers, :cert, :cert_valid, :cert_trusted, :dh
def initialize(family, ip, port, hostname: nil)
@family, @ip, @port, @hostname = family, ip, port, hostname
@dh = []
def initialize(hostname, family, ip, port)
@hostname, @family, @ip, @port = hostname, family, ip, port
@dh = []
Logger.info { name.colorize :blue }
extract_cert
Logger.info { '' }
@ -128,27 +120,21 @@ module CryptCheck
def connect(&block)
socket = ::Socket.new @family, sock_type
sockaddr = ::Socket.sockaddr_in @port, @ip
Logger.trace { "Connecting to #{name}" }
Logger.trace { "Connecting to #{@ip}:#{@port}" }
begin
status = socket.connect_nonblock sockaddr
Logger.trace { "Connecting to #{name} status : #{status}" }
Logger.trace { "Connecting to #{@ip}:#{@port} status : #{status}" }
raise ConnectionError, status unless status == 0
Logger.trace { "Connected to #{name}" }
Logger.trace { "Connected to #{@ip}:#{@port}" }
block_given? ? block.call(socket) : nil
rescue ::IO::WaitReadable
Logger.trace { "Waiting for read to #{name}" }
raise Timeout unless IO.select [socket], nil, nil, TCP_TIMEOUT
Logger.trace { "Waiting for read to #{@ip}:#{@port}" }
raise Timeout, "Timeout when connect to #{@ip}:#{@port} (max #{TCP_TIMEOUT.humanize})" unless IO.select [socket], nil, nil, TCP_TIMEOUT
retry
rescue ::IO::WaitWritable
Logger.trace { "Waiting for write to #{name}" }
raise Timeout unless IO.select nil, [socket], nil, TCP_TIMEOUT
Logger.trace { "Waiting for write to #{@ip}:#{@port}" }
raise Timeout, "Timeout when connect to #{@ip}:#{@port} (max #{TCP_TIMEOUT.humanize})" unless IO.select nil, [socket], nil, TCP_TIMEOUT
retry
rescue => e
case e.message
when /^Connection refused/
raise TLSNotAvailableException, e
end
raise
ensure
socket.close
end
@ -164,14 +150,14 @@ module CryptCheck
return block_given? ? block.call(ssl_socket) : nil
rescue ::IO::WaitReadable
Logger.trace { "Waiting for SSL read to #{name}" }
raise TLSTimeout unless IO.select [socket], nil, nil, SSL_TIMEOUT
raise TLSTimeout, "Timeout when TLS connect to #{@ip}:#{@port} (max #{SSL_TIMEOUT.humanize})" unless IO.select [ssl_socket], nil, nil, SSL_TIMEOUT
retry
rescue ::IO::WaitWritable
Logger.trace { "Waiting for SSL write to #{name}" }
raise TLSTimeout unless IO.select nil, [socket], nil, SSL_TIMEOUT
raise TLSTimeout, "Timeout when TLS connect to #{@ip}:#{@port} (max #{SSL_TIMEOUT.humanize})" unless IO.select nil, [ssl_socket], nil, SSL_TIMEOUT
retry
rescue ::OpenSSL::SSL::SSLError => e
case e.message
case e
when /state=SSLv2 read server hello A$/,
/state=SSLv3 read server hello A: wrong version number$/
raise MethodNotAvailable, e
@ -179,13 +165,11 @@ module CryptCheck
/state=SSLv3 read server hello A: sslv3 alert handshake failure$/
raise CipherNotAvailable, e
end
raise TLSException, e
rescue => e
case e.message
case e
when /^Connection reset by peer$/
raise MethodNotAvailable, e
end
raise TLSException, e
ensure
ssl_socket.close
end
@ -248,7 +232,7 @@ module CryptCheck
dh = ssl_client method, [cipher] { |s| s.tmp_key }
@dh << dh if dh
cipher = Cipher.new method, cipher, dh
dh = dh ? " (#{'DH'.colorize :green} : #{Tls.key_to_s dh})" : ''
dh = dh ? " (#{'DH'.colorize :green} : #{Tls.key_to_s dh})" : ''
Logger.info { "#{Tls.colorize method} / #{cipher.colorize} : Supported#{dh}" }
cipher
rescue TLSException => e

View File

@ -2,20 +2,13 @@ module CryptCheck
module Tls
module Smtp
def self.analyze(host, port=25, domain: nil)
domain ||= host
::CryptCheck.analyze host, port do |family, ip, host|
s = Server.new family, ip, port, hostname: host, domain: domain
g = Grade.new s
Logger.info { '' }
g.display
g
end
::CryptCheck.analyze host, port, Server, Grade, domain: domain
end
def self.analyze_domain(domain)
srv = Resolv::DNS.new.getresources(domain, Resolv::DNS::Resource::IN::MX).sort_by(&:preference).first
hostname = srv ? srv.exchange.to_s : domain
self.analyze hostname, domain: domain
srv = Resolv::DNS.new.getresources(domain, Resolv::DNS::Resource::IN::MX).sort_by &:preference
hosts = srv.empty? ? [domain] : srv.collect { |s| s.exchange.to_s }
hosts.collect { |h| self.analyze h, domain: domain }.flatten(1)
end
def self.analyze_file(input, output)

View File

@ -4,9 +4,9 @@ module CryptCheck
class Server < Tls::TcpServer
attr_reader :domain
def initialize(family, ip, port, hostname: nil, domain:)
def initialize(hostname, family, ip, port, domain:)
@domain = domain
super family, ip, port, hostname: hostname
super
end
def ssl_connect(socket, context, method, &block)

View File

@ -8,7 +8,7 @@ module CryptCheck
class Server < Tls::TcpServer
attr_reader :domain
def initialize(family, ip, port=nil, hostname: nil, domain: nil, type: :s2s)
def initialize(hostname, family, ip, port=nil, domain: nil, type: :s2s)
domain ||= hostname
@type, @domain = type, domain
port = case type

View File

@ -0,0 +1,136 @@
describe CryptCheck::Tls do
describe '#analyze' do
it 'return 1 grade with IPv4' do
grades = server(host: '127.0.0.1') do
CryptCheck::Tls.analyze '127.0.0.1', 5000
end
expect(grades.size).to be 1
expect_grade grades, '127.0.0.1', '127.0.0.1', 5000, :ipv4
end
it 'return 1 grade with IPv6' do
grades = server(host: '::1') do
CryptCheck::Tls.analyze '::1', 5000
end
expect(grades.size).to be 1
expect_grade grades, '::1', '::1', 5000, :ipv6
end
it 'return 2 grades with hostname (IPv4 & IPv6)' do
addresses = %w(127.0.0.1 ::1)
allow(Addrinfo).to receive(:getaddrinfo).with('localhost', nil, nil, :STREAM) do
addresses.collect { |a| Addrinfo.new Socket.sockaddr_in(nil, a) }
end
grades = server(host: '::') do
CryptCheck::Tls.analyze 'localhost', 5000
end
expect_grade grades, 'localhost', '127.0.0.1', 5000, :ipv4
expect_grade grades, 'localhost', '::1', 5000, :ipv6
end
it 'return error if DNS resolution problem' do
allow(Addrinfo).to receive(:getaddrinfo).with('localhost', nil, nil, :STREAM)
.and_raise SocketError, 'getaddrinfo: Name or service not known'
grades = server do
CryptCheck::Tls.analyze 'localhost', 5000
end
expect(grades).to be_a CryptCheck::AnalysisFailure
expect(grades.to_s).to eq 'Unable to resolve localhost'
end
it 'return error if analysis too long' do
stub_const 'CryptCheck::MAX_ANALYSIS_DURATION', 1
allow(CryptCheck::Tls::Server).to receive(:new) { sleep 2 }
grades = server do
CryptCheck::Tls.analyze 'localhost', 5000
end
expect_grade_error grades, 'localhost', '127.0.0.1', 5000,
'Too long analysis (max 1 second)'
end
it 'return error if unable to connect' do
addresses = %w(127.0.0.1 ::1)
allow(Addrinfo).to receive(:getaddrinfo).with('localhost', nil, nil, :STREAM) do
addresses.collect { |a| Addrinfo.new Socket.sockaddr_in(nil, a) }
end
grades = server(host: '::1') do
CryptCheck::Tls.analyze 'localhost', 5000
end
expect_grade_error grades, 'localhost', '127.0.0.1', 5000,
'Connection refused - connect(2) for 127.0.0.1:5000'
expect_grade grades, 'localhost', '::1', 5000, :ipv6
end
it 'return error if TCP timeout' do
stub_const 'CryptCheck::Tls::Server::TCP_TIMEOUT', 1
addresses = %w(127.0.0.1 ::1)
allow(Addrinfo).to receive(:getaddrinfo).with('localhost', nil, nil, :STREAM) do
addresses.collect { |a| Addrinfo.new Socket.sockaddr_in(nil, a) }
end
original = IO.method :select
allow(IO).to receive(:select) do |*args, &block|
socket = [args[0]&.first, args[1]&.first].compact.first
next nil if socket.is_a?(Socket) && (socket.local_address.afamily == Socket::AF_INET)
original.call *args, &block
end
grades = server(host: '::') do
CryptCheck::Tls.analyze 'localhost', 5000
end
expect_grade_error grades, 'localhost', '127.0.0.1', 5000,
'Timeout when connect to 127.0.0.1:5000 (max 1 second)'
expect_grade grades, 'localhost', '::1', 5000, :ipv6
end
it 'return error if TLS timeout' do
stub_const 'CryptCheck::Tls::Server::SSL_TIMEOUT', 1
addresses = %w(127.0.0.1 ::1)
allow(Addrinfo).to receive(:getaddrinfo).with('localhost', nil, nil, :STREAM) do
addresses.collect { |a| Addrinfo.new Socket.sockaddr_in(nil, a) }
end
original = IO.method :select
allow(IO).to receive(:select) do |*args, &block|
socket = [args[0]&.first, args[1]&.first].compact.first
next nil if socket.is_a?(OpenSSL::SSL::SSLSocket) && (socket.io.local_address.afamily == Socket::AF_INET)
original.call *args, &block
end
grades = server(host: '::') do
CryptCheck::Tls.analyze 'localhost', 5000
end
expect_grade_error grades, 'localhost', '127.0.0.1', 5000,
'Timeout when TLS connect to 127.0.0.1:5000 (max 1 second)'
expect_grade grades, 'localhost', '::1', 5000, :ipv6
end
it 'return error if plain server' do
stub_const 'CryptCheck::Tls::Server::SSL_TIMEOUT', 1
addresses = %w(127.0.0.1 ::1)
allow(Addrinfo).to receive(:getaddrinfo).with('localhost', nil, nil, :STREAM) do
addresses.collect { |a| Addrinfo.new Socket.sockaddr_in(nil, a) }
end
grades = plain_server(host: '127.0.0.1') do
server(host: '::1') do
CryptCheck::Tls.analyze 'localhost', 5000
end
end
expect_grade_error grades, 'localhost', '127.0.0.1', 5000,
'Timeout when TLS connect to 127.0.0.1:5000 (max 1 second)'
expect_grade grades, 'localhost', '::1', 5000, :ipv6
end
end
end

162
spec/helpers.rb 100644
View File

@ -0,0 +1,162 @@
$:.unshift File.expand_path File.join File.dirname(__FILE__), '../lib'
require 'rubygems'
require 'bundler/setup'
require 'cryptcheck'
CryptCheck::Logger.level = ENV['LOG'] || :none
module Helpers
OpenSSL::PKey::EC.send :alias_method, :private?, :private_key?
def key(name)
open(File.join(File.dirname(__FILE__), 'resources', "#{name}.pem"), 'r') { |f| OpenSSL::PKey.read f }
end
def dh(name)
open(File.join(File.dirname(__FILE__), 'resources', "dh-#{name}.pem"), 'r') { |f| OpenSSL::PKey::DH.new f }
end
def certificate(key, domain)
cert = OpenSSL::X509::Certificate.new
cert.version = 2
cert.serial = rand 2**(20*8-1) .. 2**(20*8)
cert.not_before = Time.now
cert.not_after = cert.not_before + 60*60
cert.public_key = case key
when OpenSSL::PKey::EC
curve = key.group.curve_name
public = OpenSSL::PKey::EC.new curve
public.public_key = key.public_key
public
else
key.public_key
end
name = OpenSSL::X509::Name.parse "CN=#{domain}"
cert.subject = name
cert.issuer = name
extension_factory = OpenSSL::X509::ExtensionFactory.new nil, cert
extension_factory.subject_certificate = cert
extension_factory.issuer_certificate = cert
cert.add_extension extension_factory.create_extension 'basicConstraints', 'CA:TRUE', true
cert.add_extension extension_factory.create_extension 'keyUsage', 'keyEncipherment, dataEncipherment, digitalSignature,nonRepudiation,keyCertSign'
cert.add_extension extension_factory.create_extension 'extendedKeyUsage', 'serverAuth, clientAuth'
cert.add_extension extension_factory.create_extension 'subjectKeyIdentifier', 'hash'
cert.add_extension extension_factory.create_extension 'authorityKeyIdentifier', 'keyid:always'
cert.add_extension extension_factory.create_extension 'subjectAltName', "DNS:#{domain}"
cert.sign key, OpenSSL::Digest::SHA512.new
end
def server(key: 'rsa-1024', domain: 'localhost', # Key & certificate
host: '127.0.0.1', port: 5000, # Binding
version: :TLSv1_2, ciphers: 'AES128-SHA', # TLS version and ciphers
dh: 1024, ecdh: 'secp256r1') # DHE & ECDHE
key = key key
cert = certificate key, domain
context = OpenSSL::SSL::SSLContext.new version
context.cert = cert
context.key = key
context.ciphers = ciphers
if dh
dh = dh dh
context.tmp_dh_callback = proc { dh }
end
if ecdh
ecdh = key ecdh
context.tmp_ecdh_callback = proc { ecdh }
end
IO.pipe do |stop_pipe_r, stop_pipe_w|
threads = []
mutex = Mutex.new
started = ConditionVariable.new
threads << Thread.start do
tcp_server = TCPServer.new host, port
ssl_server = OpenSSL::SSL::SSLServer.new tcp_server, context
mutex.synchronize { started.signal }
loop do
readable, = IO.select [ssl_server, stop_pipe_r]
break if readable.include? stop_pipe_r
begin
ssl_server.accept
rescue
end
end
ssl_server.close
tcp_server.close
end
mutex.synchronize { started.wait mutex }
begin
yield
ensure
stop_pipe_w.close
threads.each &:join
end
end
end
def plain_server(host: '127.0.0.1', port: 5000)
IO.pipe do |stop_pipe_r, stop_pipe_w|
threads = []
mutex = Mutex.new
started = ConditionVariable.new
threads << Thread.start do
tcp_server = TCPServer.new host, port
mutex.synchronize { started.signal }
loop do
readable, = IO.select [tcp_server, stop_pipe_r]
break if readable.include? stop_pipe_r
begin
tcp_server.accept
rescue
end
end
tcp_server.close
end
mutex.synchronize { started.wait mutex }
begin
yield
ensure
stop_pipe_w.close
threads.each &:join
end
end
end
def expect_grade(grades, host, ip, port, family)
server = grades[[host, ip, port]].server
expect(server).to be_a CryptCheck::Tls::Server
expect(server.hostname).to eq host
expect(server.ip).to eq ip
expect(server.port).to eq port
expect(server.family).to eq case family
when :ipv4 then Socket::AF_INET
when :ipv6 then Socket::AF_INET6
end
end
def expect_grade_error(grades, host, ip, port, error)
server = grades[[host, ip, port]]
expect(server).to be_a CryptCheck::AnalysisFailure
expect(server.to_s).to eq error
end
end
RSpec.configure do |c|
c.include Helpers
end

View File

@ -0,0 +1,5 @@
-----BEGIN DH PARAMETERS-----
MIGHAoGBANBrEWPccAuXK3fq8VtE1KeDmY1vk1dJ94ht8UPEqJTdsQEtAS2g7UKm
s49RRb7mG4JOVGWy1FWi32FrZTDUxInOP7k0wz8oqQSNBJWeAZjzETd1bjYutoSx
F1DMUlw650faSS2dSXalOXyRfY+2dqR9sa7FQNlOztYFCrtwXMb7AgEC
-----END DH PARAMETERS-----

View File

@ -0,0 +1,15 @@
-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQC0xBo+MgjnYqvszjUpslonvcQVI1TG7yxlGCWqpvN0a3zdgBpV
lpXv7q/821jUtlLc2BhNohRXuoejc2oiG7IOv7Md204NnoTQbxLo6gehnMyo86il
Q7KNAAW4tam79xNgOfdkkV0d80AfG148j+N6jDZCOoZ3dFwH4a6vcSWRgQIDAQAB
AoGBAJ7j+MVOqbDpdIG0R9qc4M4p6Z9C7RPny7gY35L/KOPeT2VLYtp0gNrjjWHP
VGe002U3tTUYEJWEahFsM5BDk+ASqyzesPD5lWzi6QSO3cIkvNSYLdBezNprcPk4
PEy1pX+IXrRFeDXE/wncovuYP2STF18SSP7YgCMBAAwgeZAhAkEA7xLuNz6Qt7HK
euShzsvmzNUIaoBXa9qiOWoIb7aHa/uK87SwXpy6iV85TdWowD34JPnPiRx6FSPk
4rOXYBq0lQJBAMGQYF/ItKUGYnwj7z2Q7N3/Pz5fTyoqzQI7Nza8aCEabFNzAdMv
nZ2ROyWC/qXZ1osgPuwTBBfu9ty7GH2p4j0CQQCk+jJLCzDAor7waV/Dne+qQAQr
wl8RfXFfH22s8Y+oE5CCtpjS4WLUM1MPBDcMWncnxP/TRUR13CwxyO7YEfW1AkBv
VRqJnUiB7sUwv/54O+Zx3cFDn9BJ4apfES411nJSL/+ElA7FqIqQuZr6fXj4be5f
wWFPqbReC72Dwj1Y8iDFAkAXpo8CtvqtxQYdbIh0Jmdj2xHWppkbBs9dT/qVAOdO
RIA5UKKyyweZc+6ZFbAMeouhHGljcL73zOZt5V4YloT7
-----END RSA PRIVATE KEY-----

View File

@ -0,0 +1,8 @@
-----BEGIN EC PARAMETERS-----
BggqhkjOPQMBBw==
-----END EC PARAMETERS-----
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIIg6KuMLLVhcR7IIU+joH9npRN5eVYfBQo6pRL56xUCuoAoGCCqGSM49
AwEHoUQDQgAE+h78G/a32+1ICT/euHP0Z5INER9Rh1nJNyn0HUSR0yWCistpoX1K
yCHpVwb0SAqB/6WrwOFKnrKIdI/HX1edGQ==
-----END EC PRIVATE KEY-----

View File

@ -1,91 +0,0 @@
require 'webmock/rspec'
# This file was generated by the `rspec --init` command. Conventionally, all
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
# The generated `.rspec` file contains `--require spec_helper` which will cause this
# file to always be loaded, without a need to explicitly require it in any files.
#
# Given that it is always loaded, you are encouraged to keep this file as
# light-weight as possible. Requiring heavyweight dependencies from this file
# will add to the boot time of your test suite on EVERY test run, even for an
# individual file that may not need all of that loaded. Instead, consider making
# a separate helper file that requires the additional dependencies and performs
# the additional setup, and require it from the spec files that actually need it.
#
# The `.rspec` file also contains a few flags that are not defaults but that
# users commonly want.
#
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
RSpec.configure do |config|
# rspec-expectations config goes here. You can use an alternate
# assertion/expectation library such as wrong or the stdlib/minitest
# assertions if you prefer.
config.expect_with :rspec do |expectations|
# This option will default to `true` in RSpec 4. It makes the `description`
# and `failure_message` of custom matchers include text for helper methods
# defined using `chain`, e.g.:
# be_bigger_than(2).and_smaller_than(4).description
# # => "be bigger than 2 and smaller than 4"
# ...rather than:
# # => "be bigger than 2"
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
# rspec-mocks config goes here. You can use an alternate test double
# library (such as bogus or mocha) by changing the `mock_with` option here.
config.mock_with :rspec do |mocks|
# Prevents you from mocking or stubbing a method that does not exist on
# a real object. This is generally recommended, and will default to
# `true` in RSpec 4.
mocks.verify_partial_doubles = true
end
# The settings below are suggested to provide a good initial experience
# with RSpec, but feel free to customize to your heart's content.
=begin
# These two settings work together to allow you to limit a spec run
# to individual examples or groups you care about by tagging them with
# `:focus` metadata. When nothing is tagged with `:focus`, all examples
# get run.
config.filter_run :focus
config.run_all_when_everything_filtered = true
# Limits the available syntax to the non-monkey patched syntax that is recommended.
# For more details, see:
# - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax
# - http://teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
# - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching
config.disable_monkey_patching!
# This setting enables warnings. It's recommended, but in some cases may
# be too noisy due to issues in dependencies.
config.warnings = true
# Many RSpec users commonly either run the entire suite or an individual
# file, and it's useful to allow more verbose output when running an
# individual spec file.
if config.files_to_run.one?
# Use the documentation formatter for detailed output,
# unless a formatter has already been configured
# (e.g. via a command-line flag).
config.default_formatter = 'doc'
end
# Print the 10 slowest examples and example groups at the
# end of the spec run, to help surface which specs are running
# particularly slow.
config.profile_examples = 10
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = :random
# Seed global randomization in this process using the `--seed` CLI option.
# Setting this allows you to use `--seed` to deterministically reproduce
# test failures related to randomization by passing the same `--seed` value
# as the one that triggered the failure.
Kernel.srand config.seed
=end
end