rails-auth 2.1.2 → 2.2.2
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 +5 -5
- data/.rubocop.yml +14 -1
- data/.travis.yml +8 -5
- data/BUG-BOUNTY.md +3 -3
- data/CHANGES.md +45 -2
- data/CONTRIBUTING.md +11 -10
- data/Gemfile +6 -5
- data/Guardfile +2 -0
- data/Rakefile +3 -1
- data/lib/rails/auth/acl.rb +4 -0
- data/lib/rails/auth/acl/matchers/allow_all.rb +3 -0
- data/lib/rails/auth/acl/middleware.rb +3 -0
- data/lib/rails/auth/acl/resource.rb +7 -5
- data/lib/rails/auth/config_builder.rb +5 -1
- data/lib/rails/auth/controller_methods.rb +4 -0
- data/lib/rails/auth/credentials.rb +3 -1
- data/lib/rails/auth/credentials/injector_middleware.rb +6 -2
- data/lib/rails/auth/env.rb +4 -3
- data/lib/rails/auth/error_page/debug_middleware.rb +1 -1
- data/lib/rails/auth/error_page/middleware.rb +3 -0
- data/lib/rails/auth/exceptions.rb +2 -0
- data/lib/rails/auth/helpers.rb +3 -1
- data/lib/rails/auth/installed_constraint.rb +2 -0
- data/lib/rails/auth/monitor/middleware.rb +2 -0
- data/lib/rails/auth/rack.rb +1 -0
- data/lib/rails/auth/rspec.rb +2 -0
- data/lib/rails/auth/rspec/helper_methods.rb +6 -5
- data/lib/rails/auth/rspec/matchers/acl_matchers.rb +4 -2
- data/lib/rails/auth/version.rb +1 -1
- data/lib/rails/auth/x509/certificate.rb +35 -5
- data/lib/rails/auth/x509/filter/java.rb +4 -12
- data/lib/rails/auth/x509/filter/pem.rb +10 -1
- data/lib/rails/auth/x509/matcher.rb +2 -0
- data/lib/rails/auth/x509/middleware.rb +11 -9
- data/lib/rails/auth/x509/subject_alt_name_extension.rb +29 -0
- data/rails-auth.gemspec +5 -4
- data/spec/rails/auth/acl/matchers/allow_all_spec.rb +2 -0
- data/spec/rails/auth/acl/middleware_spec.rb +2 -0
- data/spec/rails/auth/acl/resource_spec.rb +2 -0
- data/spec/rails/auth/acl_spec.rb +2 -0
- data/spec/rails/auth/controller_methods_spec.rb +2 -0
- data/spec/rails/auth/credentials/injector_middleware_spec.rb +15 -0
- data/spec/rails/auth/credentials_spec.rb +2 -0
- data/spec/rails/auth/env_spec.rb +2 -0
- data/spec/rails/auth/error_page/debug_middleware_spec.rb +2 -0
- data/spec/rails/auth/error_page/middleware_spec.rb +2 -0
- data/spec/rails/auth/monitor/middleware_spec.rb +2 -0
- data/spec/rails/auth/rspec/helper_methods_spec.rb +2 -0
- data/spec/rails/auth/rspec/matchers/acl_matchers_spec.rb +12 -1
- data/spec/rails/auth/x509/certificate_spec.rb +103 -20
- data/spec/rails/auth/x509/matcher_spec.rb +2 -0
- data/spec/rails/auth/x509/middleware_spec.rb +13 -2
- data/spec/rails/auth/x509/subject_alt_name_extension_spec.rb +39 -0
- data/spec/rails/auth_spec.rb +2 -0
- data/spec/spec_helper.rb +5 -3
- data/spec/support/claims_matcher.rb +2 -0
- data/spec/support/create_certs.rb +57 -2
- metadata +14 -7
data/lib/rails/auth/rack.rb
CHANGED
data/lib/rails/auth/rspec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rails
|
2
4
|
module Auth
|
3
5
|
module RSpec
|
@@ -12,6 +14,7 @@ module Rails
|
|
12
14
|
# NOTE: Credentials will be *cleared* after the block. Nesting is not allowed.
|
13
15
|
def with_credentials(credentials = {})
|
14
16
|
raise TypeError, "expected Hash of credentials, got #{credentials.class}" unless credentials.is_a?(Hash)
|
17
|
+
|
15
18
|
test_credentials.clear
|
16
19
|
|
17
20
|
credentials.each do |type, value|
|
@@ -24,8 +27,8 @@ module Rails
|
|
24
27
|
# Creates an Rails::Auth::X509::Certificate instance double
|
25
28
|
def x509_certificate(cn: nil, ou: nil)
|
26
29
|
subject = ""
|
27
|
-
subject
|
28
|
-
subject
|
30
|
+
subject += "CN=#{cn}" if cn
|
31
|
+
subject += "OU=#{ou}" if ou
|
29
32
|
|
30
33
|
instance_double(Rails::Auth::X509::Certificate, subject, cn: cn, ou: ou).tap do |certificate|
|
31
34
|
allow(certificate).to receive(:[]) do |key|
|
@@ -47,9 +50,7 @@ module Rails
|
|
47
50
|
path = self.class.description
|
48
51
|
|
49
52
|
# Warn if methods are improperly used
|
50
|
-
unless path.chars[0] == "/"
|
51
|
-
raise ArgumentError, "expected #{path} to start with '/'"
|
52
|
-
end
|
53
|
+
raise ArgumentError, "expected #{path} to start with '/'" unless path.chars[0] == "/"
|
53
54
|
|
54
55
|
env = {
|
55
56
|
"REQUEST_METHOD" => method,
|
@@ -1,12 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
RSpec::Matchers.define(:permit) do |env|
|
2
4
|
description do
|
3
5
|
method = env["REQUEST_METHOD"]
|
4
6
|
credentials = Rails::Auth.credentials(env)
|
5
7
|
message = "allow #{method}s by "
|
6
8
|
|
7
|
-
return message
|
9
|
+
return message + "unauthenticated clients" if credentials.count.zero?
|
8
10
|
|
9
|
-
message
|
11
|
+
message + credentials.values.map(&:inspect).join(", ")
|
10
12
|
end
|
11
13
|
|
12
14
|
match { |acl| acl.match(env) }
|
data/lib/rails/auth/version.rb
CHANGED
@@ -18,7 +18,8 @@ module Rails
|
|
18
18
|
@certificate.subject.to_a.each do |name, data, _type|
|
19
19
|
@subject[name.freeze] = data.freeze
|
20
20
|
end
|
21
|
-
|
21
|
+
@subject_alt_names = SubjectAltNameExtension.new(certificate)
|
22
|
+
@subject_alt_names.freeze
|
22
23
|
@subject.freeze
|
23
24
|
end
|
24
25
|
|
@@ -27,23 +28,52 @@ module Rails
|
|
27
28
|
end
|
28
29
|
|
29
30
|
def cn
|
30
|
-
@subject["CN"
|
31
|
+
@subject["CN"]
|
31
32
|
end
|
32
33
|
alias common_name cn
|
33
34
|
|
35
|
+
def dns_names
|
36
|
+
@subject_alt_names.dns_names
|
37
|
+
end
|
38
|
+
|
39
|
+
def ips
|
40
|
+
@subject_alt_names.ips
|
41
|
+
end
|
42
|
+
|
34
43
|
def ou
|
35
|
-
@subject["OU"
|
44
|
+
@subject["OU"]
|
36
45
|
end
|
37
46
|
alias organizational_unit ou
|
38
47
|
|
48
|
+
def uris
|
49
|
+
@subject_alt_names.uris
|
50
|
+
end
|
51
|
+
|
52
|
+
# According to the SPIFFE standard only one SPIFFE ID can exist in the URI
|
53
|
+
# SAN:
|
54
|
+
# (https://github.com/spiffe/spiffe/blob/master/standards/X509-SVID.md#2-spiffe-id)
|
55
|
+
#
|
56
|
+
# @return [String, nil] string containing SPIFFE ID if one is present
|
57
|
+
# in the certificate
|
58
|
+
def spiffe_id
|
59
|
+
uris.detect { |uri| uri.start_with?("spiffe://") }
|
60
|
+
end
|
61
|
+
|
39
62
|
# Generates inspectable attributes for debugging
|
40
63
|
#
|
41
64
|
# @return [Hash] hash containing parts of the certificate subject (cn, ou)
|
65
|
+
# and subject alternative name extension (uris, dns_names) as well
|
66
|
+
# as SPIFFE ID (spiffe_id), which is just a convenience since those
|
67
|
+
# are already included in the uris
|
42
68
|
def attributes
|
43
69
|
{
|
44
70
|
cn: cn,
|
45
|
-
|
46
|
-
|
71
|
+
dns_names: dns_names,
|
72
|
+
ips: ips,
|
73
|
+
ou: ou,
|
74
|
+
spiffe_id: spiffe_id,
|
75
|
+
uris: uris
|
76
|
+
}.reject { |_, v| v.nil? || v.empty? }
|
47
77
|
end
|
48
78
|
|
49
79
|
# Compare ourself to another object by ensuring that it has the same type
|
@@ -1,23 +1,15 @@
|
|
1
|
-
|
2
|
-
require "stringio"
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
3
|
module Rails
|
5
4
|
module Auth
|
6
5
|
module X509
|
7
6
|
module Filter
|
8
|
-
# Extract OpenSSL::X509::Certificates from
|
7
|
+
# Extract OpenSSL::X509::Certificates from java.security.cert.Certificate
|
9
8
|
class Java
|
10
9
|
def call(certs)
|
11
|
-
return
|
12
|
-
OpenSSL::X509::Certificate.new(extract_der(certs[0])).freeze
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
10
|
+
return if certs.nil? || certs.empty?
|
16
11
|
|
17
|
-
|
18
|
-
stringio = StringIO.new
|
19
|
-
cert.derEncode(stringio.to_outputstream)
|
20
|
-
stringio.string
|
12
|
+
OpenSSL::X509::Certificate.new(certs[0].get_encoded).freeze
|
21
13
|
end
|
22
14
|
end
|
23
15
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Rails
|
2
4
|
module Auth
|
3
5
|
module X509
|
@@ -5,7 +7,14 @@ module Rails
|
|
5
7
|
# Extract OpenSSL::X509::Certificates from Privacy Enhanced Mail (PEM) certificates
|
6
8
|
class Pem
|
7
9
|
def call(pem)
|
8
|
-
|
10
|
+
# Normalize the whitespace in the certificate to the exact format
|
11
|
+
# certificates are normally formatted in otherwise parsing with fail
|
12
|
+
# with a 'nested asn1 error'. split(" ") handles sequential whitespace
|
13
|
+
# characters like \t, \n, and space.
|
14
|
+
OpenSSL::X509::Certificate.new(pem.split(" ").instance_eval do
|
15
|
+
[[self[0], self[1]].join(" "), self[2...-2], [self[-2], self[-1]].join(" ")]
|
16
|
+
.flatten.join("\n")
|
17
|
+
end).freeze
|
9
18
|
end
|
10
19
|
end
|
11
20
|
end
|
@@ -12,20 +12,21 @@ module Rails
|
|
12
12
|
# Create a new X.509 Middleware object
|
13
13
|
#
|
14
14
|
# @param [Object] app next app in the Rack middleware chain
|
15
|
-
# @param [Hash] cert_filters maps Rack environment names to cert extractors
|
16
15
|
# @param [String] ca_file path to the CA bundle to verify client certs with
|
17
|
-
# @param [
|
16
|
+
# @param [Hash] cert_filters maps Rack environment names to cert extractors
|
17
|
+
# @param [Logger] logger place to log verification successes & failures
|
18
18
|
# @param [Boolean] require_cert causes middleware to raise if certs are unverified
|
19
|
+
# @param [OpenSSL::X509::Store] truststore (optional) provide your own truststore (for e.g. CRLs)
|
19
20
|
#
|
20
21
|
# @return [Rails::Auth::X509::Middleware] new X509 middleware instance
|
21
|
-
def initialize(app,
|
22
|
-
raise ArgumentError, "no ca_file given" unless ca_file
|
22
|
+
def initialize(app, ca_file: nil, cert_filters: {}, logger: nil, require_cert: false, truststore: nil)
|
23
|
+
raise ArgumentError, "no ca_file or truststore given" unless ca_file || truststore
|
23
24
|
|
24
25
|
@app = app
|
26
|
+
@cert_filters = cert_filters
|
25
27
|
@logger = logger
|
26
|
-
@truststore = truststore || OpenSSL::X509::Store.new.add_file(ca_file)
|
27
28
|
@require_cert = require_cert
|
28
|
-
@
|
29
|
+
@truststore = truststore || OpenSSL::X509::Store.new.add_file(ca_file)
|
29
30
|
|
30
31
|
@cert_filters.each do |key, filter|
|
31
32
|
next unless filter.is_a?(Symbol)
|
@@ -40,7 +41,7 @@ module Rails
|
|
40
41
|
|
41
42
|
def call(env)
|
42
43
|
credential = extract_credential(env)
|
43
|
-
Rails::Auth.add_credential(env, "x509"
|
44
|
+
Rails::Auth.add_credential(env, "x509", credential.freeze) if credential
|
44
45
|
|
45
46
|
@app.call(env)
|
46
47
|
end
|
@@ -62,6 +63,7 @@ module Rails
|
|
62
63
|
end
|
63
64
|
|
64
65
|
raise CertificateVerifyFailed, "no client certificate in request" if @require_cert
|
66
|
+
|
65
67
|
nil
|
66
68
|
end
|
67
69
|
|
@@ -72,8 +74,8 @@ module Rails
|
|
72
74
|
end
|
73
75
|
|
74
76
|
filter.call(raw_cert)
|
75
|
-
rescue =>
|
76
|
-
@logger.debug("rails-auth: Certificate error: #{
|
77
|
+
rescue StandardError => e
|
78
|
+
@logger.debug("rails-auth: Certificate error: #{e.class}: #{e.message}") if @logger
|
77
79
|
nil
|
78
80
|
end
|
79
81
|
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Rails
|
4
|
+
module Auth
|
5
|
+
module X509
|
6
|
+
# Provides convenience methods for subjectAltName extension of X.509 certificates
|
7
|
+
class SubjectAltNameExtension
|
8
|
+
attr_reader :dns_names, :ips, :uris
|
9
|
+
|
10
|
+
DNS_REGEX = /^DNS:/i.freeze
|
11
|
+
IP_REGEX = /^IP( Address)?:/i.freeze
|
12
|
+
URI_REGEX = /^URI:/i.freeze
|
13
|
+
|
14
|
+
def initialize(certificate)
|
15
|
+
unless certificate.is_a?(OpenSSL::X509::Certificate)
|
16
|
+
raise TypeError, "expecting OpenSSL::X509::Certificate, got #{certificate.class}"
|
17
|
+
end
|
18
|
+
|
19
|
+
extension = certificate.extensions.detect { |ext| ext.oid == "subjectAltName" }
|
20
|
+
values = (extension&.value&.split(",") || []).map(&:strip)
|
21
|
+
|
22
|
+
@dns_names = values.grep(DNS_REGEX) { |v| v.sub(DNS_REGEX, "") }.freeze
|
23
|
+
@ips = values.grep(IP_REGEX) { |v| v.sub(IP_REGEX, "") }.freeze
|
24
|
+
@uris = values.grep(URI_REGEX) { |v| v.sub(URI_REGEX, "") }.freeze
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/rails-auth.gemspec
CHANGED
@@ -1,5 +1,6 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path("lib", __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require "rails/auth/version"
|
5
6
|
|
@@ -25,10 +26,10 @@ Gem::Specification.new do |spec|
|
|
25
26
|
spec.bindir = "exe"
|
26
27
|
spec.require_paths = ["lib"]
|
27
28
|
|
28
|
-
spec.required_ruby_version = ">= 2.
|
29
|
+
spec.required_ruby_version = ">= 2.3.0"
|
29
30
|
|
30
31
|
spec.add_runtime_dependency "rack"
|
31
32
|
|
32
|
-
spec.add_development_dependency "bundler", "
|
33
|
+
spec.add_development_dependency "bundler", ">= 1.10", "< 3"
|
33
34
|
spec.add_development_dependency "rake", "~> 10.0"
|
34
35
|
end
|
data/spec/rails/auth/acl_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
RSpec.describe Rails::Auth::Credentials::InjectorMiddleware do
|
2
4
|
let(:request) { Rack::MockRequest.env_for("https://www.example.com") }
|
3
5
|
let(:app) { ->(env) { [200, env, "Hello, world!"] } }
|
@@ -8,4 +10,17 @@ RSpec.describe Rails::Auth::Credentials::InjectorMiddleware do
|
|
8
10
|
_response, env = middleware.call(request)
|
9
11
|
expect(env[Rails::Auth::Env::CREDENTIALS_ENV_KEY]).to eq credentials
|
10
12
|
end
|
13
|
+
|
14
|
+
context "with a proc for credentials" do
|
15
|
+
let(:credentials_proc) { instance_double(Proc) }
|
16
|
+
let(:middleware) { described_class.new(app, credentials_proc) }
|
17
|
+
|
18
|
+
it "overrides rails-auth credentials in the rack environment" do
|
19
|
+
expect(credentials_proc).to receive(:call).with(request).and_return(credentials)
|
20
|
+
|
21
|
+
_response, env = middleware.call(request)
|
22
|
+
|
23
|
+
expect(env[Rails::Auth::Env::CREDENTIALS_ENV_KEY]).to eq credentials
|
24
|
+
end
|
25
|
+
end
|
11
26
|
end
|
data/spec/rails/auth/env_spec.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
RSpec.describe "RSpec ACL matchers", acl_spec: true do
|
2
|
-
let(:example_certificate) { x509_certificate_hash(ou: "ponycopter") }
|
3
4
|
let(:another_certificate) { x509_certificate_hash(ou: "derpderp") }
|
5
|
+
let(:example_certificate) { x509_certificate_hash(ou: "ponycopter") }
|
4
6
|
|
5
7
|
subject do
|
6
8
|
Rails::Auth::ACL.from_yaml(
|
@@ -16,5 +18,14 @@ RSpec.describe "RSpec ACL matchers", acl_spec: true do
|
|
16
18
|
it { is_expected.to permit get_request(credentials: example_certificate) }
|
17
19
|
it { is_expected.not_to permit get_request(credentials: another_certificate) }
|
18
20
|
it { is_expected.not_to permit get_request }
|
21
|
+
|
22
|
+
it "has the correct description" do
|
23
|
+
expect(permit(get_request(credentials: example_certificate)).description)
|
24
|
+
.to eq('allow GETs by #<InstanceDouble(Rails::Auth::X509::Certificate) "OU=ponycopter">')
|
25
|
+
expect(permit(get_request(credentials: another_certificate)).description)
|
26
|
+
.to eq('allow GETs by #<InstanceDouble(Rails::Auth::X509::Certificate) "OU=derpderp">')
|
27
|
+
expect(permit(get_request).description)
|
28
|
+
.to eq("allow GETs by unauthenticated clients")
|
29
|
+
end
|
19
30
|
end
|
20
31
|
end
|
@@ -1,38 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
RSpec.describe Rails::Auth::X509::Certificate do
|
2
4
|
let(:example_cert) { OpenSSL::X509::Certificate.new(cert_path("valid.crt").read) }
|
5
|
+
let(:example_cert_with_extension) { OpenSSL::X509::Certificate.new(cert_path("valid_with_ext.crt").read) }
|
3
6
|
let(:example_certificate) { described_class.new(example_cert) }
|
7
|
+
let(:example_certificate_with_extension) { described_class.new(example_cert_with_extension) }
|
4
8
|
|
5
9
|
let(:example_cn) { "127.0.0.1" }
|
10
|
+
let(:example_dns_names) { %w[example.com exemplar.com somethingelse.com] }
|
11
|
+
let(:example_ips) { %w[0.0.0.0 127.0.0.1 192.168.1.1] }
|
6
12
|
let(:example_ou) { "ponycopter" }
|
13
|
+
let(:example_spiffe) { "spiffe://example.com/exemplar" }
|
14
|
+
let(:example_uris) { [example_spiffe, "https://www.example.com/page1", "https://www.example.com/page2"] }
|
15
|
+
|
16
|
+
describe "without extensions" do
|
17
|
+
describe "#[]" do
|
18
|
+
it "allows access to subject components via strings" do
|
19
|
+
expect(example_certificate["CN"]).to eq example_cn
|
20
|
+
expect(example_certificate["OU"]).to eq example_ou
|
21
|
+
end
|
7
22
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
23
|
+
it "allows access to subject components via symbols" do
|
24
|
+
expect(example_certificate[:cn]).to eq example_cn
|
25
|
+
expect(example_certificate[:ou]).to eq example_ou
|
26
|
+
end
|
12
27
|
end
|
13
28
|
|
14
|
-
it "
|
15
|
-
expect(example_certificate
|
16
|
-
expect(example_certificate[:ou]).to eq example_ou
|
29
|
+
it "knows its #cn" do
|
30
|
+
expect(example_certificate.cn).to eq example_cn
|
17
31
|
end
|
18
|
-
end
|
19
32
|
|
20
|
-
|
21
|
-
|
22
|
-
|
33
|
+
it "has no #dns_names" do
|
34
|
+
expect(example_certificate.dns_names).to be_empty
|
35
|
+
end
|
23
36
|
|
24
|
-
|
25
|
-
|
26
|
-
|
37
|
+
it "has no #ips" do
|
38
|
+
expect(example_certificate.ips).to be_empty
|
39
|
+
end
|
40
|
+
|
41
|
+
it "knows its #ou" do
|
42
|
+
expect(example_certificate.ou).to eq example_ou
|
43
|
+
end
|
27
44
|
|
28
|
-
|
29
|
-
|
45
|
+
it "has no #uris" do
|
46
|
+
expect(example_certificate.uris).to be_empty
|
47
|
+
end
|
48
|
+
|
49
|
+
it "has no #spiffe_id" do
|
50
|
+
expect(example_certificate.spiffe_id).to be_nil
|
51
|
+
end
|
52
|
+
|
53
|
+
it "knows its attributes" do
|
54
|
+
expect(example_certificate.attributes).to eq(cn: example_cn, ou: example_ou)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "compares certificate objects by comparing their certificates" do
|
58
|
+
second_cert = OpenSSL::X509::Certificate.new(cert_path("valid.crt").read)
|
59
|
+
second_certificate = described_class.new(second_cert)
|
60
|
+
|
61
|
+
expect(example_certificate).to be_eql second_certificate
|
62
|
+
end
|
30
63
|
end
|
31
64
|
|
32
|
-
|
33
|
-
|
34
|
-
|
65
|
+
describe "with extensions" do
|
66
|
+
describe "#[]" do
|
67
|
+
it "allows access to subject components via strings" do
|
68
|
+
expect(example_certificate_with_extension["CN"]).to eq example_cn
|
69
|
+
expect(example_certificate_with_extension["OU"]).to eq example_ou
|
70
|
+
end
|
35
71
|
|
36
|
-
|
72
|
+
it "allows access to subject components via symbols" do
|
73
|
+
expect(example_certificate_with_extension[:cn]).to eq example_cn
|
74
|
+
expect(example_certificate_with_extension[:ou]).to eq example_ou
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
it "knows its #cn" do
|
79
|
+
expect(example_certificate_with_extension.cn).to eq example_cn
|
80
|
+
end
|
81
|
+
|
82
|
+
it "knows its #dns_names" do
|
83
|
+
expect(example_certificate_with_extension.dns_names).to eq example_dns_names
|
84
|
+
end
|
85
|
+
|
86
|
+
it "knows its #ips" do
|
87
|
+
expect(example_certificate_with_extension.ips).to eq example_ips
|
88
|
+
end
|
89
|
+
|
90
|
+
it "knows its #ou" do
|
91
|
+
expect(example_certificate_with_extension.ou).to eq example_ou
|
92
|
+
end
|
93
|
+
|
94
|
+
it "knows its #spiffe_id" do
|
95
|
+
expect(example_certificate_with_extension.spiffe_id).to eq example_spiffe
|
96
|
+
end
|
97
|
+
|
98
|
+
it "knows its #uris" do
|
99
|
+
expect(example_certificate_with_extension.uris).to eq example_uris
|
100
|
+
end
|
101
|
+
|
102
|
+
it "knows its attributes" do
|
103
|
+
expected_attrs = {
|
104
|
+
cn: example_cn,
|
105
|
+
dns_names: example_dns_names,
|
106
|
+
ips: example_ips,
|
107
|
+
ou: example_ou,
|
108
|
+
spiffe_id: example_spiffe,
|
109
|
+
uris: example_uris
|
110
|
+
}
|
111
|
+
expect(example_certificate_with_extension.attributes).to eq(expected_attrs)
|
112
|
+
end
|
113
|
+
|
114
|
+
it "compares certificate objects by comparing their certificates" do
|
115
|
+
second_cert = OpenSSL::X509::Certificate.new(cert_path("valid_with_ext.crt").read)
|
116
|
+
second_certificate = described_class.new(second_cert)
|
117
|
+
|
118
|
+
expect(example_certificate_with_extension).to be_eql second_certificate
|
119
|
+
end
|
37
120
|
end
|
38
121
|
end
|