Skip to content

Commit

Permalink
Merge pull request #2933 from cyberark/oidc-configurable-truststore
Browse files Browse the repository at this point in the history
Wrap discovery and callback calls
  • Loading branch information
gl-johnson authored Sep 6, 2023
2 parents eb4b353 + 932bb49 commit b9130ad
Show file tree
Hide file tree
Showing 14 changed files with 99 additions and 9 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
[cyberark/conjur#2901](https://github.com/cyberark/conjur/pull/2901)

### Added
- Support an optional`ca-cert` variable for providing custom certs/chains to verify
OIDC providers or proxies when using the OIDC authenticator
[cyberark/conjur#2933](https://github.com/cyberark/conjur/pull/2933)
- New flag to `conjurctl server` command called `--no-migrate` which allows for skipping
the database migration step when starting the server.
[cyberark/conjur#2895](https://github.com/cyberark/conjur/pull/2895)
Expand Down
16 changes: 13 additions & 3 deletions app/domain/authentication/authn_oidc/v2/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,11 @@ def discovery_information(invalidate: false)
force: invalidate,
skip_nil: true
) do
@discovery_configuration.discover!(@authenticator.provider_uri)
self.class.discover(
provider_uri: @authenticator.provider_uri,
discovery_configuration: @discovery_configuration,
cert_string: @authenticator.ca_cert
)
rescue Errno::ETIMEDOUT => e
raise Errors::Authentication::OAuth::ProviderDiscoveryTimeout.new(@authenticator.provider_uri, e.message)
rescue => e
Expand All @@ -183,9 +187,15 @@ def self.discover(
provider_uri:,
discovery_configuration: ::OpenIDConnect::Discovery::Provider::Config,
cert_dir: OpenSSL::X509::DEFAULT_CERT_DIR,
cert_string: nil
cert_string: nil,
jwks: false
)
d = -> { discovery_configuration.discover!(provider_uri) }
case jwks
when false
d = -> { discovery_configuration.discover!(provider_uri) }
when true
d = -> { discovery_configuration.discover!(provider_uri).jwks }
end

return d.call if cert_string.blank?

Expand Down
5 changes: 3 additions & 2 deletions app/domain/authentication/authn_oidc/v2/strategy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@ def callback(args)
end

identity = resolve_identity(
jwt: @client.callback(
jwt: @client.callback_with_temporary_cert(
code: args[:code],
nonce: args[:nonce],
code_verifier: args[:code_verifier]
code_verifier: args[:code_verifier],
cert_string: @authenticator.ca_cert
)
)
unless identity.present?
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ def log_provider_uri
# is used is inside of FetchProviderKeys. This is unlikely change, and hence
# unlikely to be a problem
def discover_provider
@discovered_provider = @open_id_discovery_service.discover!(@provider_uri)
@discovered_provider = Authentication::AuthnOidc::V2::Client.discover(
provider_uri: @provider_uri,
discovery_configuration: @open_id_discovery_service,
cert_string: @ca_cert
)
@logger.debug(
LogMessages::Authentication::OAuth::IdentityProviderDiscoverySuccess.new
)
Expand Down
8 changes: 7 additions & 1 deletion app/domain/authentication/o_auth/fetch_provider_keys.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,14 @@ def discovered_provider
end

def fetch_provider_keys
# We have to wrap the call to the JWKS URI separately to accomodate
# custom CA certs in authn-oidc
jwks = {
keys: @discovered_provider.jwks
keys: Authentication::AuthnOidc::V2::Client.discover(
provider_uri: @provider_uri,
cert_string: @ca_cert,
jwks: true
)
}
algs = @discovered_provider.id_token_signing_alg_values_supported
@logger.debug(LogMessages::Authentication::OAuth::FetchProviderKeysSuccess.new)
Expand Down
9 changes: 9 additions & 0 deletions ci/test_suites/authenticators_oidc/test
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ function _hydrate_all_env_args() {
# shellcheck disable=SC2034
arr=(
"${keycloak_items[@]}"
"KEYCLOAK_CA_CERT=$($COMPOSE exec conjur cat /etc/ssl/certs/keycloak.pem)"
"PROVIDER_URI=https://keycloak:8443/auth/realms/master"
"PROVIDER_INTERNAL_URI=http://keycloak:8080/auth/realms/master/protocol/openid-connect"
"PROVIDER_ISSUER=http://keycloak:8080/auth/realms/master"
Expand All @@ -49,6 +50,14 @@ function main() {
create_keycloak_users
fetch_keycloak_certificate

# Delete the symlink so we can test with the 'ca-cert' variable
local conjur_parallel_services
read -ra conjur_parallel_services <<< "$(get_parallel_services 'conjur')"
for parallel_service in "${conjur_parallel_services[@]}"; do
hash=$($COMPOSE exec "${parallel_service}" openssl x509 -hash -in /etc/ssl/certs/keycloak.pem -out /dev/null)
$COMPOSE exec "${parallel_service}" rm "/etc/ssl/certs/$hash.0" || true
done

additional_services='ldap-server keycloak'
_run_cucumber_tests authenticators_oidc "$additional_services" \
_hydrate_all_env_args
Expand Down
5 changes: 5 additions & 0 deletions cucumber/authenticators_oidc/features/authn_oidc.feature
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Feature: OIDC Authenticator - Hosts can authenticate with OIDC authenticator
| oidc_client_secret | KEYCLOAK_CLIENT_SECRET | 1234 |
| oidc_provider_uri | PROVIDER_URI | https://keycloak:8443/auth/realms/master |
| oidc_id_token_user_property | ID_TOKEN_USER_PROPERTY | preferred_username |
| oidc_ca_cert | KEYCLOAK_CA_CERT | |

And I load a policy:
"""
Expand All @@ -31,6 +32,9 @@ Feature: OIDC Authenticator - Hosts can authenticate with OIDC authenticator
- !variable
id: id-token-user-property
- !variable
id: ca-cert
- !group users
- !permit
Expand All @@ -48,6 +52,7 @@ Feature: OIDC Authenticator - Hosts can authenticate with OIDC authenticator
| variable_id | context_variable |
| conjur/authn-oidc/keycloak/id-token-user-property | oidc_id_token_user_property |
| conjur/authn-oidc/keycloak/provider-uri | oidc_provider_uri |
| conjur/authn-oidc/keycloak/ca-cert | oidc_ca_cert |

@smoke
Scenario: A valid id token in header to get Conjur access token
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Feature: OIDC Authenticator - Bad authenticator configuration leads to an error
| oidc_client_secret | KEYCLOAK_CLIENT_SECRET | 1234 |
| oidc_provider_uri | PROVIDER_URI | https://keycloak:8443/auth/realms/master |
| oidc_id_token_user_property | ID_TOKEN_USER_PROPERTY | preferred_username |
| oidc_ca_cert | KEYCLOAK_CA_CERT | |

@negative @acceptance
Scenario: id-token-user-property variable missing in policy is denied
Expand All @@ -29,6 +30,9 @@ Feature: OIDC Authenticator - Bad authenticator configuration leads to an error
- !variable
id: provider-uri
- !variable
id: ca-cert
- !group users
Expand All @@ -46,6 +50,7 @@ Feature: OIDC Authenticator - Bad authenticator configuration leads to an error
And I set the following conjur variables:
| variable_id | context_variable |
| conjur/authn-oidc/keycloak/provider-uri | oidc_provider_uri |
| conjur/authn-oidc/keycloak/ca-cert | oidc_ca_cert |
And I fetch an ID Token for username "alice" and password "alice"
And I save my place in the log file
When I authenticate via OIDC with id token
Expand Down Expand Up @@ -108,6 +113,9 @@ Feature: OIDC Authenticator - Bad authenticator configuration leads to an error
- !variable
id: id-token-user-property
- !variable
id: ca-cert
- !group users
- !user alice
Expand All @@ -120,6 +128,7 @@ Feature: OIDC Authenticator - Bad authenticator configuration leads to an error
| variable_id | context_variable |
| conjur/authn-oidc/keycloak/id-token-user-property | oidc_id_token_user_property |
| conjur/authn-oidc/keycloak/provider-uri | oidc_provider_uri |
| conjur/authn-oidc/keycloak/ca-cert | oidc_ca_cert |
And I fetch an ID Token for username "alice" and password "alice"
And I save my place in the log file
When I authenticate via OIDC with id token
Expand All @@ -146,6 +155,9 @@ Feature: OIDC Authenticator - Bad authenticator configuration leads to an error
- !variable
id: id-token-user-property
- !variable
id: ca-cert
- !group users
- !permit
Expand All @@ -163,6 +175,7 @@ Feature: OIDC Authenticator - Bad authenticator configuration leads to an error
| variable_id | context_variable |
| conjur/authn-oidc/keycloak/id-token-user-property | oidc_id_token_user_property |
| conjur/authn-oidc/keycloak/provider-uri | oidc_provider_uri |
| conjur/authn-oidc/keycloak/ca-cert | oidc_ca_cert |
And I fetch an ID Token for username "alice" and password "alice"
And I save my place in the log file
When I authenticate via OIDC with id token
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Feature: OIDC Authenticator - Performance tests
| oidc_client_secret | KEYCLOAK_CLIENT_SECRET | 1234 |
| oidc_provider_uri | PROVIDER_URI | https://keycloak:8443/auth/realms/master |
| oidc_id_token_user_property | ID_TOKEN_USER_PROPERTY | preferred_username |
| oidc_ca_cert | KEYCLOAK_CA_CERT | |

And I load a policy:
"""
Expand All @@ -31,6 +32,9 @@ Feature: OIDC Authenticator - Performance tests
- !variable
id: id-token-user-property
- !variable
id: ca-cert
- !group users
- !permit
Expand All @@ -48,6 +52,7 @@ Feature: OIDC Authenticator - Performance tests
| variable_id | context_variable |
| conjur/authn-oidc/keycloak/id-token-user-property | oidc_id_token_user_property |
| conjur/authn-oidc/keycloak/provider-uri | oidc_provider_uri |
| conjur/authn-oidc/keycloak/ca-cert | oidc_ca_cert |

@performance
Scenario: successful requests
Expand Down
5 changes: 5 additions & 0 deletions cucumber/authenticators_oidc/features/authn_oidc_v2.feature
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Feature: OIDC Authenticator V2 - Users can authenticate with OIDC authenticator
| oidc_provider_uri | PROVIDER_URI | https://keycloak:8443/auth/realms/master |
| oidc_claim_mapping | ID_TOKEN_USER_PROPERTY | preferred_username |
| oidc_redirect_url | KEYCLOAK_REDIRECT_URI | http://conjur:3000/authn-oidc/keycloak2/cucumber/authenticate |
| oidc_ca_cert | KEYCLOAK_CA_CERT | |

And I load a policy:
"""
Expand All @@ -36,6 +37,7 @@ Feature: OIDC Authenticator V2 - Users can authenticate with OIDC authenticator
- !variable redirect-uri
- !variable provider-scope
- !variable token-ttl
- !variable ca-cert
- !group users
- !permit
role: !group users
Expand All @@ -59,6 +61,7 @@ Feature: OIDC Authenticator V2 - Users can authenticate with OIDC authenticator
- !variable redirect-uri
- !variable provider-scope
- !variable token-ttl
- !variable ca-cert
- !group users
- !permit
role: !group users
Expand All @@ -83,13 +86,15 @@ Feature: OIDC Authenticator V2 - Users can authenticate with OIDC authenticator
| conjur/authn-oidc/keycloak2/claim-mapping | oidc_claim_mapping | |
| conjur/authn-oidc/keycloak2/redirect-uri | oidc_redirect_url | |
| conjur/authn-oidc/keycloak2/response-type | | code |
| conjur/authn-oidc/keycloak2/ca-cert | oidc_ca_cert | |
| conjur/authn-oidc/keycloak2-long-lived/provider-uri | oidc_provider_uri | |
| conjur/authn-oidc/keycloak2-long-lived/client-id | oidc_client_id | |
| conjur/authn-oidc/keycloak2-long-lived/client-secret | oidc_client_secret | |
| conjur/authn-oidc/keycloak2-long-lived/claim-mapping | oidc_claim_mapping | |
| conjur/authn-oidc/keycloak2-long-lived/redirect-uri | oidc_redirect_url | |
| conjur/authn-oidc/keycloak2-long-lived/response-type | | code |
| conjur/authn-oidc/keycloak2-long-lived/token-ttl | | PT2H |
| conjur/authn-oidc/keycloak2-long-lived/ca-cert | oidc_ca_cert | |

@smoke
Scenario: A valid code to get Conjur access token from webservice with default token TTL
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Feature: OIDC Authenticator - Users can authenticate with OIDC & LDAP authentica
| oidc_client_secret | KEYCLOAK_CLIENT_SECRET | 1234 |
| oidc_provider_uri | PROVIDER_URI | https://keycloak:8443/auth/realms/master |
| oidc_id_token_user_property | ID_TOKEN_USER_PROPERTY | preferred_username |
| oidc_ca_cert | KEYCLOAK_CA_CERT | |

# Configure OIDC authenticator
And I load a policy:
Expand All @@ -28,6 +29,8 @@ Feature: OIDC Authenticator - Users can authenticate with OIDC & LDAP authentica
id: provider-uri
- !variable
id: id-token-user-property
- !variable
id: ca-cert
- !group users
- !permit
role: !group users
Expand All @@ -42,6 +45,7 @@ Feature: OIDC Authenticator - Users can authenticate with OIDC & LDAP authentica
| variable_id | context_variable |
| conjur/authn-oidc/keycloak/id-token-user-property | oidc_id_token_user_property |
| conjur/authn-oidc/keycloak/provider-uri | oidc_provider_uri |
| conjur/authn-oidc/keycloak/ca-cert | oidc_ca_cert |

# Configure LDAP authenticator
And I extend the policy with:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ Feature: OIDC Authenticator - Status Check
| context_variable | environment_variable | default_value |
| oidc_provider_uri | PROVIDER_URI | https://keycloak:8443/auth/realms/master |
| oidc_claim_mapping | ID_TOKEN_USER_PROPERTY | preferred_username |
| oidc_ca_cert | KEYCLOAK_CA_CERT | |

@smoke
Scenario: A properly configured OIDC authenticator returns a successful response
Expand All @@ -28,6 +29,9 @@ Feature: OIDC Authenticator - Status Check
- !variable
id: id-token-user-property
- !variable
id: ca-cert
- !group users
Expand Down Expand Up @@ -60,7 +64,7 @@ Feature: OIDC Authenticator - Status Check
| variable_id | context_variable | default_value |
| conjur/authn-oidc/keycloak/provider-uri | oidc_provider_uri | |
| conjur/authn-oidc/keycloak/id-token-user-property | oidc_claim_mapping | |

| conjur/authn-oidc/keycloak/ca-cert | oidc_ca_cert | |
And I login as "alice"
When I GET "/authn-oidc/keycloak/cucumber/status"
Then the HTTP response status code is 200
Expand Down
3 changes: 3 additions & 0 deletions dev/start
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,9 @@ configure_oidc_v2() {
client_add_secret "conjur/authn-oidc/$service_id/redirect_uri" "http://localhost:3000/authn-oidc/$service_id/cucumber/authenticate"
if [ "$service_id" = "keycloak2" ]; then
client_add_secret "conjur/authn-oidc/$service_id/ca-cert" "$($COMPOSE exec conjur cat /etc/ssl/certs/keycloak.pem)"
# Delete the symlink so we can test with the 'ca-cert' variable
hash=$($COMPOSE exec conjur openssl x509 -hash -in /etc/ssl/certs/keycloak.pem -out /dev/null)
$COMPOSE exec conjur rm "/etc/ssl/certs/$hash.0" || true
fi

client_load_policy "/src/conjur-server/dev/policies/authenticators/authn-oidc/$service_id-users.yml"
Expand Down
20 changes: 19 additions & 1 deletion spec/app/domain/authentication/authn-oidc/v2/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,8 @@ def client(config)
let(:target) { Authentication::AuthnOidc::V2::Client }
let(:provider_uri) { "https://oidcprovider.com" }
let(:mock_discovery) { double("Mock Discovery Config") }
let(:mock_response) { "Mock Discovery Response" }
let(:mock_response) { double("Mock Discovery Response") }
let(:mock_jwks_response) { "Mock JWKS Response" }

before(:each) do
@cert_dir = Dir.mktmpdir
Expand Down Expand Up @@ -401,6 +402,23 @@ def client(config)
cert_string: ""
)).to eq(mock_response)
end

it 'invokes the jwks uri when requested' do
allow(mock_discovery).to receive(:discover!).with(String).and_return(
mock_response
)
allow(mock_response).to receive(:jwks).and_return(
mock_jwks_response
)

expect(target.discover(
provider_uri: provider_uri,
discovery_configuration: mock_discovery,
cert_dir: @cert_dir,
cert_string: "",
jwks: true
)).to eq(mock_jwks_response)
end
end

context 'when valid cert is provided' do
Expand Down

0 comments on commit b9130ad

Please sign in to comment.