Skip to content

Commit

Permalink
Integrate public-keys variable into full JWT Authentication flow
Browse files Browse the repository at this point in the history
When Conjur is unable to reach remote JWKS URI endpoint public-keys variable can be used in order to provide static JWK Set to the authenticator.
Variable value is a JSON object contains two fields: type and value. The type filed should be set to "jwks" string and the value field should be set to a relevant JWKS set.
  • Loading branch information
sashaCher committed Jan 13, 2022
1 parent 54d0c93 commit 71097ea
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 13 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.

## [Unreleased]

### Added
- Added an ability to JWT generic vendor configuration to receive signing keys for
JWT token verification from a variable. Variable name is `public-keys`
[#2463](https://github.com/cyberark/conjur/pull/2463)
[#2461](https://github.com/cyberark/conjur/pull/2461)
[#2456](https://github.com/cyberark/conjur/pull/2456)
[#2455](https://github.com/cyberark/conjur/pull/2455)
[#2454](https://github.com/cyberark/conjur/pull/2454)
[#2450](https://github.com/cyberark/conjur/pull/2450)
[#2447](https://github.com/cyberark/conjur/pull/2447)
[#2437](https://github.com/cyberark/conjur/pull/2437)

## [1.15.0] - 2021-12-21

### Added
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ module SigningKey
build_signing_key_settings: Authentication::AuthnJwt::SigningKey::SigningKeySettingsBuilder.new,
fetch_provider_uri_signing_key_class: Authentication::AuthnJwt::SigningKey::FetchProviderUriSigningKey,
fetch_jwks_uri_signing_key_class: Authentication::AuthnJwt::SigningKey::FetchJwksUriSigningKey,
fetch_public_keys_signing_key_class: Authentication::AuthnJwt::SigningKey::FetchPublicKeysSigningKey,
logger: Rails.logger
},
inputs: %i[authenticator_input]
Expand Down Expand Up @@ -52,6 +53,8 @@ def create_signing_key_provider
fetch_jwks_uri_signing_key
when PROVIDER_URI_INTERFACE_NAME
fetch_provider_uri_signing_key
when PUBLIC_KEYS_INTERFACE_NAME
fetch_public_keys_signing_key
else
raise Errors::Authentication::AuthnJwt::InvalidSigningKeyType, signing_key_settings.type
end
Expand All @@ -76,6 +79,15 @@ def fetch_jwks_uri_signing_key
fetch_signing_key: @fetch_signing_key
)
end

def fetch_public_keys_signing_key
@logger.info(
LogMessages::Authentication::AuthnJwt::SelectedSigningKeyInterface.new(PUBLIC_KEYS_INTERFACE_NAME)
)
@fetch_public_keys_signing_key ||= @fetch_public_keys_signing_key_class.new(
signing_keys: signing_key_settings.signing_keys
)
end
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,19 @@ module SigningKey
class FetchPublicKeysSigningKey

def initialize(
public_keys:,
signing_keys:,
logger: Rails.logger
)
@logger = logger
@public_keys = public_keys
@signing_keys = signing_keys
end

def call(*)
@logger.info(LogMessages::Authentication::AuthnJwt::ParsingStaticSigningKeys.new)
signing_keys = Authentication::AuthnJwt::SigningKey::PublicSigningKeys.new(JSON.parse(@public_keys))
signing_keys.validate!
public_signing_keys = Authentication::AuthnJwt::SigningKey::PublicSigningKeys.new(JSON.parse(@signing_keys))
public_signing_keys.validate!
@logger.debug(LogMessages::Authentication::AuthnJwt::ParsedStaticSigningKeys.new)
{ keys: JSON::JWK::Set.new(signing_keys.value) }
{ keys: JSON::JWK::Set.new(public_signing_keys.value) }
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,6 @@ Feature: JWT Authenticator - Check registered claim
CONJ00011E Failed to discover Identity Provider (Provider URI: 'incorrect.com'). Reason: '#<AttrRequired::AttrMissing: 'host' required.>'
"""

@skip
Scenario: ONYX-15323: public-keys with invalid issuer variable
Given I extend the policy with:
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -659,7 +659,6 @@ Feature: JWT Authenticator - Fetch signing key
CONJ00035E Failed to decode token (3rdPartyError ='#<JWT::DecodeError: No key id (kid) found from token headers>')
"""

@skip
@sanity
Scenario: ONYX-15322: public-keys happy path
Given I load a policy:
Expand Down Expand Up @@ -709,7 +708,6 @@ Feature: JWT Authenticator - Fetch signing key
cucumber:host:myapp successfully authenticated with authenticator authn-jwt service cucumber:webservice:conjur/authn-jwt/raw
"""

@skip
Scenario: ONYX-15325: public-keys value is in invalid format
Given I load a policy:
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ Feature: JWT Authenticator - Validate And Decode
CONJ00035E Failed to decode token (3rdPartyError ='#<JWT::VerificationError: Signature verification raised>')>
"""

@skip
Scenario: ONYX-15324: public-keys with valid issuer, token is signed by other key
Given I extend the policy with:
"""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,18 @@
type: "provider-uri"
)
}
let(:mocked_signing_key_settings_type_public_keys) {
Authentication::AuthnJwt::SigningKey::SigningKeySettings.new(
signing_keys: "public_keys",
type: "public-keys"
)
}

let(:mocked_fetch_signing_key_parameters) { double("MockedFetchSigningKeyParameters") }
let(:mocked_build_signing_key_settings_type_is_wrong) { double("MockedBuildSigningKeySettingsTypeIsWrong") }
let(:mocked_build_signing_key_settings_type_jwks_uri) { double("MockedBuildSigningKeySettingsTypeJwksUri") }
let(:mocked_build_signing_key_settings_type_provider_uri) { double("MockedBuildSigningKeySettingsTypeProviderUri") }
let(:mocked_build_signing_key_settings_type_public_keys) { double("MockedBuildSigningKeySettingsTypePublicKeys") }

let(:mocked_logger) { double("Mocked logger") }

Expand Down Expand Up @@ -74,6 +81,12 @@
.with(signing_key_parameters: mocked_signing_key_parameters)
.and_return(mocked_signing_key_settings_type_provider_uri)
)

allow(mocked_build_signing_key_settings_type_public_keys).to(
receive(:call)
.with(signing_key_parameters: mocked_signing_key_parameters)
.and_return(mocked_signing_key_settings_type_public_keys)
)
end

# ____ _ _ ____ ____ ____ ___ ____ ___
Expand Down Expand Up @@ -122,6 +135,26 @@
end
end

context "Signing key settings type is public-keys" do
subject do
::Authentication::AuthnJwt::SigningKey::CreateSigningKeyProvider.new(
fetch_signing_key_parameters: mocked_fetch_signing_key_parameters,
build_signing_key_settings: mocked_build_signing_key_settings_type_public_keys,
logger: logger
).call(
authenticator_input: mocked_authenticator_input
)
end

it "returns FetchProviderUriSigningKey instance and writes appropriate logs" do
expect(subject).to be_a(Authentication::AuthnJwt::SigningKey::FetchPublicKeysSigningKey)
expect(log_output.string.split("\n")).to eq([
"DEBUG,CONJ00075D Selecting signing key interface...",
"INFO,CONJ00076I Selected signing key interface: 'public-keys'"
])
end
end

context "Signing key settings type is wrong" do
subject do
::Authentication::AuthnJwt::SigningKey::CreateSigningKeyProvider.new(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
context "fails when the value is not a JSON" do
subject do
::Authentication::AuthnJwt::SigningKey::FetchPublicKeysSigningKey.new(
public_keys: string_value
signing_keys: string_value
).call(force_fetch: false)
end

Expand All @@ -46,7 +46,7 @@
context "fails when the value is not valid" do
subject do
::Authentication::AuthnJwt::SigningKey::FetchPublicKeysSigningKey.new(
public_keys: invalid_public_keys_value
signing_keys: invalid_public_keys_value
).call(force_fetch: false)
end

Expand All @@ -59,7 +59,7 @@
context "returns a JWKS object" do
subject do
::Authentication::AuthnJwt::SigningKey::FetchPublicKeysSigningKey.new(
public_keys: valid_public_keys_value
signing_keys: valid_public_keys_value
).call(force_fetch: false)
end

Expand All @@ -79,7 +79,7 @@
context "writes logs" do
subject do
::Authentication::AuthnJwt::SigningKey::FetchPublicKeysSigningKey.new(
public_keys: valid_public_keys_value,
signing_keys: valid_public_keys_value,
logger: logger
).call(force_fetch: false)
log_output.string.split("\n")
Expand Down

0 comments on commit 71097ea

Please sign in to comment.