-
Notifications
You must be signed in to change notification settings - Fork 123
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
AuthnOIDC V2: write custom certs to non-default directory #2988
Changes from all commits
5ffed27
2b65a73
158b283
1d079cd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,6 +18,19 @@ def initialize( | |
@logger = logger | ||
end | ||
|
||
# Writing certificates to the default system cert store requires | ||
# superuser privilege. Instead, Conjur will use ${CONJUR_ROOT}/tmp/certs. | ||
def self.default_cert_dir(dir: Dir, fileutils: FileUtils) | ||
if @default_cert_dir.blank? | ||
conjur_root = __dir__.slice(0..(__dir__.index('/app'))) | ||
@default_cert_dir = File.join(conjur_root, "tmp/certs") | ||
end | ||
|
||
fileutils.mkdir_p(@default_cert_dir) unless dir.exist?(@default_cert_dir.to_s) | ||
|
||
@default_cert_dir | ||
end | ||
|
||
def oidc_client | ||
@oidc_client ||= begin | ||
issuer_uri = URI(@authenticator.provider_uri) | ||
|
@@ -99,7 +112,7 @@ def callback(code:, nonce:, code_verifier: nil) | |
|
||
# callback_with_temporary_cert wraps the callback method with commands | ||
# to write & clean up a given certificate or cert chain in a given | ||
# directory. By default, Conjur's default cert store is used. | ||
# directory. By default, ${CONJUR_ROOT}/tmp/certs is used. | ||
# | ||
# The temporary certificate file name is "x.n", where x is the hash of | ||
# the certificate subject name, and n is incrememnted from 0 in case of | ||
|
@@ -114,7 +127,7 @@ def callback_with_temporary_cert( | |
code:, | ||
nonce:, | ||
code_verifier: nil, | ||
cert_dir: OpenSSL::X509::DEFAULT_CERT_DIR, | ||
cert_dir: Authentication::AuthnOidc::V2::Client.default_cert_dir, | ||
cert_string: nil | ||
) | ||
c = -> { callback(code: code, nonce: nonce, code_verifier: code_verifier) } | ||
|
@@ -148,6 +161,27 @@ def callback_with_temporary_cert( | |
symlink_a << symlink | ||
end | ||
|
||
if OpenIDConnect.http_config.nil? || OpenIDConnect.http_client.ssl.ca_path != cert_dir | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Authentication::AuthnOidc::V2::Client#callback_with_temporary_cert performs a nil-check |
||
config_proc = proc do |config| | ||
config.ssl.ca_path = cert_dir | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Authentication::AuthnOidc::V2::Client#callback_with_temporary_cert calls 'config.ssl' 2 times |
||
config.ssl.verify_mode = OpenSSL::SSL::VERIFY_PEER | ||
end | ||
|
||
# OpenIDConnect gem only accepts a single Faraday configuration | ||
# through calls to its .http_config method, and future calls to | ||
# the #http_config method return the first config instance. | ||
# | ||
# On the first call to OpenIDConnect.http_config, it will pass the | ||
# new Faraday configuration to its dependency gems that also have | ||
# nil configs. We can't be certain that each gem is configured | ||
# with the same Faraday config and need them synchronized, so we | ||
# inject them manually. | ||
OpenIDConnect.class_variable_set(:@@http_config, config_proc) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace class var :@@http_config with a class instance var. |
||
WebFinger.instance_variable_set(:@http_config, config_proc) | ||
SWD.class_variable_set(:@@http_config, config_proc) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace class var :@@http_config with a class instance var. |
||
Rack::OAuth2.class_variable_set(:@@http_config, config_proc) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace class var :@@http_config with a class instance var. |
||
end | ||
|
||
c.call | ||
ensure | ||
symlink_a.each{ |s| File.unlink(s) if s.present? && File.symlink?(s) } | ||
|
@@ -174,7 +208,7 @@ def discovery_information(invalidate: false) | |
|
||
# discover wraps ::OpenIDConnect::Discovery::Provider::Config.discover! | ||
# with commands to write & clean up a given certificate or cert chain in | ||
# a given directory. By default, Conjur's default cert store is used. | ||
# a given directory. By default, ${CONJUR_ROOT}/tmp/certs is used. | ||
# | ||
# The temporary certificate file name is "x.n", where x is the hash of | ||
# the certificate subject name, and n is incremented from 0 in case of | ||
|
@@ -186,7 +220,7 @@ def discovery_information(invalidate: false) | |
def self.discover( | ||
provider_uri:, | ||
discovery_configuration: ::OpenIDConnect::Discovery::Provider::Config, | ||
cert_dir: OpenSSL::X509::DEFAULT_CERT_DIR, | ||
cert_dir: default_cert_dir, | ||
cert_string: nil, | ||
jwks: false | ||
) | ||
|
@@ -226,6 +260,27 @@ def self.discover( | |
symlink_a << symlink | ||
end | ||
|
||
if OpenIDConnect.http_config.nil? || OpenIDConnect.http_client.ssl.ca_path != cert_dir | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Authentication::AuthnOidc::V2::Client#self.discover performs a nil-check |
||
config_proc = proc do |config| | ||
config.ssl.ca_path = cert_dir | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Authentication::AuthnOidc::V2::Client#self.discover calls 'config.ssl' 2 times |
||
config.ssl.verify_mode = OpenSSL::SSL::VERIFY_PEER | ||
end | ||
|
||
# OpenIDConnect gem only accepts a single Faraday configuration | ||
# through calls to its .http_config method, and future calls to | ||
# the #http_config method return the first config instance. | ||
# | ||
# On the first call to OpenIDConnect.http_config, it will pass the | ||
# new Faraday configuration to its dependency gems that also have | ||
# nil configs. We can't be certain that each gem is configured | ||
# with the same Faraday config and need them synchronized, so we | ||
# inject them manually. | ||
OpenIDConnect.class_variable_set(:@@http_config, config_proc) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace class var :@@http_config with a class instance var. |
||
WebFinger.instance_variable_set(:@http_config, config_proc) | ||
SWD.class_variable_set(:@@http_config, config_proc) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace class var :@@http_config with a class instance var. |
||
Rack::OAuth2.class_variable_set(:@@http_config, config_proc) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Replace class var :@@http_config with a class instance var. |
||
end | ||
|
||
d.call | ||
ensure | ||
symlink_a.each{ |s| File.unlink(s) if s.present? && File.symlink?(s) } | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any particular reason we're using instance variables instead of variables scoped to the method?
Ah, I think I understand what you're trying to accomplish here. We only want to set the
@default_cert_dir
if it hasn't yet been set. This is in a singleton so you can pass it into thecallback_with_temporary_cert
method below.