Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New ca_cert parameter in FetchJwksUriSigningKey class #2457

Merged
merged 1 commit into from
Jan 6, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class FetchJwksUriSigningKey
def initialize(
authenticator_input:,
fetch_signing_key:,
ca_cert: nil,
fetch_authenticator_secrets: Authentication::Util::FetchAuthenticatorSecrets.new,
http_lib: Net::HTTP,
create_jwks_from_http_response: CreateJwksFromHttpResponse.new,
Expand All @@ -23,6 +24,7 @@ def initialize(

@authenticator_input = authenticator_input
@fetch_signing_key = fetch_signing_key
@ca_cert = ca_cert
end

def call(force_fetch:)
Expand All @@ -36,6 +38,7 @@ def call(force_fetch:)
def fetch_signing_key
fetch_jwks_uri
fetch_jwks_keys
create_jwks_from_http_response
end

private
Expand All @@ -58,19 +61,63 @@ def jwks_uri_secret
end

def fetch_jwks_keys
begin
uri = URI(jwks_uri)
@logger.info(LogMessages::Authentication::AuthnJwt::FetchingJwksFromProvider.new(jwks_uri))
response = @http_lib.get_response(uri)
@logger.debug(LogMessages::Authentication::AuthnJwt::FetchJwtUriKeysSuccess.new)
rescue => e
jwks_keys
end

def jwks_keys
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Complex method Authentication::AuthnJwt::SigningKey::FetchJwksUriSigningKey#jwks_keys (25.4)

return @jwks_keys if defined?(@jwks_keys)

uri = URI(jwks_uri)
@logger.info(LogMessages::Authentication::AuthnJwt::FetchingJwksFromProvider.new(jwks_uri))
@jwks_keys = net_http_start(
uri.host,
uri.port,
uri.scheme == 'https'
) { |http| http.get(uri) }
@logger.debug(LogMessages::Authentication::AuthnJwt::FetchJwtUriKeysSuccess.new)
rescue => e
raise Errors::Authentication::AuthnJwt::FetchJwksKeysFailed.new(
jwks_uri,
e.inspect
)
end

def net_http_start(host, port, use_ssl, &block)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Authentication::AuthnJwt::SigningKey::FetchJwksUriSigningKey takes parameters ['host', 'port', 'use_ssl'] to 3 methods

if @ca_cert && !use_ssl
raise Errors::Authentication::AuthnJwt::FetchJwksKeysFailed.new(
jwks_uri,
e.inspect
"TLS misconfiguration - ca-cert is provided but jwks-uri URI scheme is http"
)
end

@create_jwks_from_http_response.call(http_response: response)
if @ca_cert
net_http_start_with_ca_cert(host, port, use_ssl, &block)
else
net_http_start_without_ca_cert(host, port, use_ssl, &block)
end
end

def net_http_start_with_ca_cert(host, port, use_ssl, &block)
@http_lib.start(
host,
port,
use_ssl: use_ssl,
cert_store: @ca_cert,
&block
)
end

def net_http_start_without_ca_cert(host, port, use_ssl, &block)
@http_lib.start(
host,
port,
use_ssl: use_ssl,
&block
)
end

def create_jwks_from_http_response
@create_jwks_from_http_response.call(http_response: jwks_keys)
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,22 @@
let(:mocked_logger) { double("Mocked Logger") }
let(:mocked_fetch_signing_key) { double("MockedFetchSigningKey") }
let(:mocked_fetch_signing_key_refresh_value) { double("MockedFetchSigningKeyRefreshValue") }
let(:mocked_fetch_authenticator_secrets_exist_values) { double("MockedFetchAuthenticatorSecrets") }
let(:mocked_fetch_authenticator_secrets_empty_values) { double("MockedFetchAuthenticatorSecrets") }
let(:mocked_fetch_authenticator_secrets_exist_https) { double("MockedFetchAuthenticatorSecretsHttps") }
let(:mocked_fetch_authenticator_secrets_exist_http) { double("MockedFetchAuthenticatorSecretsHttp") }
let(:mocked_fetch_authenticator_secrets_empty_values) { double("MockedFetchAuthenticatorSecretsEmpty") }
let(:mocked_bad_http_response) { double("Mocked bad http response") }
let(:mocked_good_http_response) { double("Mocked good http response") }
let(:mocked_http_response_ca_cert_present) { double("MockedNet::HTTP.startCertStorePresent") }
let(:mocked_bad_response) { double("Mocked bad http body") }
let(:mocked_good_response) { double("Mocked good http body") }
let(:mocked_create_jwks_from_http_response) { double("Mocked good jwks") }
let(:mocked_create_jwks_from_http_responce_http_response) { double("MockedDummyJwks") }

let(:good_response) { "good-response"}
let(:bad_response) { "bad-response"}
let(:valid_jwks) { "valid-jwls" }
let(:cert_store_present) { "present" }
let(:cert_store_absent) { "absent" }

before(:each) do
allow(mocked_logger).to(
Expand All @@ -54,20 +59,41 @@
allow(mocked_fetch_signing_key).to receive(:call) { |params| params[:signing_key_provider].fetch_signing_key }
allow(mocked_fetch_signing_key_refresh_value).to receive(:call) { |params| params[:refresh] }

allow(mocked_fetch_authenticator_secrets_exist_values).to(
allow(mocked_fetch_authenticator_secrets_exist_https).to(
receive(:call).and_return('jwks-uri' => 'https://jwks-uri.com/jwks')
)

allow(mocked_fetch_authenticator_secrets_exist_http).to(
receive(:call).and_return('jwks-uri' => 'http://jwks-uri.com/jwks')
)

allow(mocked_fetch_authenticator_secrets_empty_values).to(
receive(:call).and_raise(required_secret_missing_error)
)

allow(mocked_bad_http_response).to(
receive(:get_response).and_return(bad_response)
receive(:start).and_return(bad_response)
)

allow(mocked_good_http_response).to(
receive(:get_response).and_return(good_response)
receive(:start).and_return(good_response)
)

allow(mocked_http_response_ca_cert_present).to(
receive(:start).with(
anything,
anything,
use_ssl: anything,
cert_store: cert_store_present
).and_return(cert_store_present)
)

allow(mocked_http_response_ca_cert_present).to(
receive(:start).with(
anything,
anything,
use_ssl: anything
).and_return(cert_store_absent)
)

allow(mocked_create_jwks_from_http_response).to(
Expand All @@ -77,6 +103,8 @@
allow(mocked_create_jwks_from_http_response).to(
receive(:call).with(http_response: bad_response).and_raise(bad_response_error)
)

allow(mocked_create_jwks_from_http_responce_http_response).to receive(:call) { |params| params[:http_response] }
end

# ____ _ _ ____ ____ ____ ___ ____ ___
Expand All @@ -90,7 +118,7 @@
::Authentication::AuthnJwt::SigningKey::FetchJwksUriSigningKey.new(authenticator_input: mocked_authenticator_input,
fetch_signing_key: mocked_fetch_signing_key_refresh_value,
logger: mocked_logger,
fetch_authenticator_secrets: mocked_fetch_authenticator_secrets_exist_values,
fetch_authenticator_secrets: mocked_fetch_authenticator_secrets_exist_https,
http_lib: mocked_bad_http_response,
create_jwks_from_http_response: mocked_create_jwks_from_http_response
).call(force_fetch: false)
Expand All @@ -106,7 +134,7 @@
::Authentication::AuthnJwt::SigningKey::FetchJwksUriSigningKey.new(authenticator_input: mocked_authenticator_input,
fetch_signing_key: mocked_fetch_signing_key_refresh_value,
logger: mocked_logger,
fetch_authenticator_secrets: mocked_fetch_authenticator_secrets_exist_values,
fetch_authenticator_secrets: mocked_fetch_authenticator_secrets_exist_https,
http_lib: mocked_bad_http_response,
create_jwks_from_http_response: mocked_create_jwks_from_http_response
).call(force_fetch: true)
Expand All @@ -117,12 +145,67 @@
end
end

context "processes ca_cert parameter" do
context "when it present" do
subject do
::Authentication::AuthnJwt::SigningKey::FetchJwksUriSigningKey.new(authenticator_input: mocked_authenticator_input,
ca_cert: cert_store_present,
fetch_signing_key: mocked_fetch_signing_key,
logger: mocked_logger,
fetch_authenticator_secrets: mocked_fetch_authenticator_secrets_exist_https,
http_lib: mocked_http_response_ca_cert_present,
create_jwks_from_http_response: mocked_create_jwks_from_http_responce_http_response
).call(force_fetch: false)
end

it "returns valid value" do
expect(subject).to eql(cert_store_present)
end
end

context "when it present but uri is http" do
subject do
::Authentication::AuthnJwt::SigningKey::FetchJwksUriSigningKey.new(authenticator_input: mocked_authenticator_input,
ca_cert: cert_store_present,
fetch_signing_key: mocked_fetch_signing_key,
logger: mocked_logger,
fetch_authenticator_secrets: mocked_fetch_authenticator_secrets_exist_http,
http_lib: mocked_http_response_ca_cert_present,
create_jwks_from_http_response: mocked_create_jwks_from_http_responce_http_response
).call(force_fetch: false)
end

it "raises error" do
expect { subject }.to raise_error(
Errors::Authentication::AuthnJwt::FetchJwksKeysFailed,
/CONJ00087E Failed to fetch JWKS from 'http:\/\/jwks-uri.com\/jwks'. Reason: 'TLS misconfiguration - ca-cert is provided but jwks-uri URI scheme is http'/
)
end
end

context "when it's absent" do
subject do
::Authentication::AuthnJwt::SigningKey::FetchJwksUriSigningKey.new(authenticator_input: mocked_authenticator_input,
fetch_signing_key: mocked_fetch_signing_key,
logger: mocked_logger,
fetch_authenticator_secrets: mocked_fetch_authenticator_secrets_exist_https,
http_lib: mocked_http_response_ca_cert_present,
create_jwks_from_http_response: mocked_create_jwks_from_http_responce_http_response
).call(force_fetch: false)
end

it "returns valid value" do
expect(subject).to eql(cert_store_absent)
end
end
end

context "'jwks-uri' secret is not valid" do
subject do
::Authentication::AuthnJwt::SigningKey::FetchJwksUriSigningKey.new(authenticator_input: mocked_authenticator_input,
fetch_signing_key: mocked_fetch_signing_key,
logger: mocked_logger,
fetch_authenticator_secrets: mocked_fetch_authenticator_secrets_exist_values,
fetch_authenticator_secrets: mocked_fetch_authenticator_secrets_exist_https,
http_lib: mocked_bad_http_response,
create_jwks_from_http_response: mocked_create_jwks_from_http_response
).call(force_fetch: false)
Expand All @@ -139,7 +222,7 @@
::Authentication::AuthnJwt::SigningKey::FetchJwksUriSigningKey.new(authenticator_input: mocked_authenticator_input,
fetch_signing_key: mocked_fetch_signing_key,
logger: mocked_logger,
fetch_authenticator_secrets: mocked_fetch_authenticator_secrets_exist_values,
fetch_authenticator_secrets: mocked_fetch_authenticator_secrets_exist_https,
http_lib: mocked_good_http_response,
create_jwks_from_http_response: mocked_create_jwks_from_http_response
).call(force_fetch: false)
Expand All @@ -155,7 +238,7 @@
::Authentication::AuthnJwt::SigningKey::FetchJwksUriSigningKey.new(authenticator_input: mocked_authenticator_input,
fetch_signing_key: mocked_fetch_signing_key,
logger: mocked_logger,
fetch_authenticator_secrets: mocked_fetch_authenticator_secrets_exist_values,
fetch_authenticator_secrets: mocked_fetch_authenticator_secrets_exist_https,
http_lib: mocked_bad_http_response,
create_jwks_from_http_response: mocked_create_jwks_from_http_response
).call(force_fetch: false)
Expand Down