-
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
Add safer data-handling in ConjurCA #1688
Conversation
app/domain/repos/conjur_ca.rb
Outdated
private | ||
|
||
def self.fetch_secret | ||
@fetch_secret ||= ::Conjur::FetchRequiredSecrets.new |
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.
let's give this variable the same name as the class it represents - @fetch_required_secrets
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.
Changed
app/domain/repos/conjur_ca.rb
Outdated
begin | ||
fetch_secret.(resource_ids: [ca_info.cert_id, ca_info.key_id]) | ||
rescue Errors::Conjur::RequiredResourceMissing | ||
raise Errors::Authentication::AuthnK8s::CaResourceMissing, resource_id |
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.
what is resource_id
in this context? what will be printed to the log?
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.
Also - which log message will be the most helpful for the user?
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.
which message will give them the best pin-pointed action item?
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.
Refactor exceptions messages
app/domain/repos/conjur_ca.rb
Outdated
@@ -14,12 +14,28 @@ def self.create(resource_id) | |||
# | |||
def self.ca(resource_id) | |||
ca_info = ::Conjur::CaInfo.new(resource_id) | |||
stored_cert = Resource[ca_info.cert_id].last_secret.value | |||
stored_key = Resource[ca_info.key_id].last_secret.value | |||
stored_cert, stored_key = fetch_ca_secrets(ca_info, resource_id) |
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.
i think this is quite risky, as it assumes the order of the retrieval. what happens if someone will change the behaviour of FetchRequiredSecrets
so that it retrieves the secrets in parallel? In this case the first secret in the array may not be stored_cert
. How can you overcome this?
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.
Changed
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.
WIP
app/domain/errors.rb
Outdated
@@ -306,6 +306,16 @@ module AuthnK8s | |||
msg: "Invalid Kubernetes host id: {0}. Must end with <namespace>/<resource_type>/<resource_id>", | |||
code: "CONJ00048E" | |||
) | |||
|
|||
CaResourceMissing = ::Util::TrackableErrorClass.new( | |||
msg: "Resource {0-resource-id} doesn't have saved resource for cert_id or key_id ", |
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.
Do we have validation for log messages from Docs or is it not needed here?
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.
From where are we getting the resource-id
?
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.
From the creation of the exception
app/domain/errors.rb
Outdated
|
||
CaResourceMissing = ::Util::TrackableErrorClass.new( | ||
msg: "Resource {0-resource-id} doesn't have saved resource for cert_id or key_id ", | ||
code: "CONJ00063E" |
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.
Those error codes need to be documeneted in a KB/Troubleshooting guide?
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.
@orenbm ?
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.
not at the moment. there is an effort led by @netacoral but i am not sure that it has started.
app/domain/repos/conjur_ca.rb
Outdated
@@ -14,12 +14,28 @@ def self.create(resource_id) | |||
# | |||
def self.ca(resource_id) | |||
ca_info = ::Conjur::CaInfo.new(resource_id) | |||
stored_cert = Resource[ca_info.cert_id].last_secret.value | |||
stored_key = Resource[ca_info.key_id].last_secret.value | |||
stored_cert, stored_key = fetch_ca_secrets(ca_info, resource_id) |
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.
What is the reasoning for using oneliner?
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.
Changed
app/domain/repos/conjur_ca.rb
Outdated
ca_cert = OpenSSL::X509::Certificate.new(stored_cert) | ||
ca_key = OpenSSL::PKey::RSA.new(stored_key) | ||
::Util::OpenSsl::CA.new(ca_cert, ca_key) | ||
end | ||
|
||
class << self |
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.
Are we sure we want to use this architacutre of class + private? Is it TDD - can we write tests?
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.
Changed
app/domain/repos/conjur_ca.rb
Outdated
raise Errors::Authentication::AuthnK8s::CaResourceMissing, ca_resource_id | ||
rescue Errors::Conjur::RequiredSecretMissing | ||
raise Errors::Authentication::AuthnK8s::CaResourceValueMissing, ca_resource_id | ||
|
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.
Extra empty line detected at begin
body end.
app/domain/repos/conjur_ca.rb
Outdated
end | ||
|
||
def self.fetch_ca_resource(ca_resource_id) | ||
begin |
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.
Redundant begin
block detected.
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.
def self.fetch_ca_resource(ca_resource_id)
begin
fetch_required_secrets.(resource_ids: [ca_resource_id])[ca_resource_id]
rescue Errors::Conjur::RequiredResourceMissing
raise Errors::Authentication::AuthnK8s::CaResourceMissing, ca_resource_id
rescue Errors::Conjur::RequiredSecretMissing
raise Errors::Authentication::AuthnK8s::CaResourceValueMissing, ca_resource_id
end
end
@orenbm When I delete the begin it has errors with the indentation of rescue (and to fix this they need to be in the same indent as def
which basically won't work). What's the right way?
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.
this should do it:
def self.fetch_ca_resource(ca_resource_id)
fetch_required_secrets.(resource_ids: [ca_resource_id])[ca_resource_id]
rescue Errors::Conjur::RequiredResourceMissing
raise Errors::Authentication::AuthnK8s::CaResourceMissing, ca_resource_id
rescue Errors::Conjur::RequiredSecretMissing
raise Errors::Authentication::AuthnK8s::CaResourceValueMissing, ca_resource_id
end
app/domain/repos/conjur_ca.rb
Outdated
stored_cert = fetch_ca_resource(ca_info.cert_id) | ||
stored_key = fetch_ca_resource(ca_info.key_id) |
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.
this will make 2 calls to the DB instead of 1 so it's not the ideal solution. I would retrieve them together and then take each var from the retrieved list. you can see how we did it in FetchAuthenticatorSecrets
.
app/domain/repos/conjur_ca.rb
Outdated
rescue Errors::Conjur::RequiredResourceMissing | ||
raise Errors::Authentication::AuthnK8s::CaResourceMissing, ca_resource_id | ||
rescue Errors::Conjur::RequiredSecretMissing | ||
raise Errors::Authentication::AuthnK8s::CaResourceValueMissing, ca_resource_id |
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.
do you see value in raising the error CaResourceValueMissing
instead of the error RequiredResourceMissing
? what value does the user get from this message that they don't get from the original?
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.
Beautiful!
Care to fix your git history?
@liavyona you will also need to rebase on master |
app/domain/repos/conjur_ca.rb
Outdated
@@ -14,12 +14,16 @@ def self.create(resource_id) | |||
# | |||
def self.ca(resource_id) | |||
ca_info = ::Conjur::CaInfo.new(resource_id) | |||
stored_cert = Resource[ca_info.cert_id].last_secret.value | |||
stored_key = Resource[ca_info.key_id].last_secret.value | |||
ca_secrets = fetch_required_secrets.(resource_ids: [ca_info.cert_id, ca_info.key_id]) |
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.
Repos::ConjurCA#self.ca calls 'ca_info.cert_id' 2 times
app/domain/repos/conjur_ca.rb
Outdated
@@ -14,12 +14,16 @@ def self.create(resource_id) | |||
# | |||
def self.ca(resource_id) | |||
ca_info = ::Conjur::CaInfo.new(resource_id) | |||
stored_cert = Resource[ca_info.cert_id].last_secret.value | |||
stored_key = Resource[ca_info.key_id].last_secret.value | |||
ca_secrets = fetch_required_secrets.(resource_ids: [ca_info.cert_id, ca_info.key_id]) |
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.
Repos::ConjurCA#self.ca calls 'ca_info.key_id' 2 times
cd5fd49
to
d738424
Compare
Add fetch_required_secrets to handle malformed ca There are 3 types of malformed ca data: a. No resource - The ca has no key/cert saved on the db. b. No value - The resource exists but has an empty value (not initialized yet). c. Bad value - The value is not the right one. The added function is meant to take care of the first two cases by raising relevant exception to each case. The third one is being taken care by the OpenSSL library.
d738424
to
65b26a6
Compare
Done |
Done |
Code Climate has analyzed commit 65b26a6 and detected 0 issues on this pull request. The test coverage on the diff in this pull request is 14.2% (50% is the threshold). This pull request will bring the total coverage in the repository to 86.2% (0.0% change). View more on Code Climate. |
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.
My comments are totally personal taste, up to you.
LGTM well done
stored_key = Resource[ca_info.key_id].last_secret.value | ||
ca_cert_id = ca_info.cert_id | ||
ca_key_id = ca_info.key_id | ||
ca_secrets = fetch_required_secrets.(resource_ids: [ca_cert_id, ca_key_id]) |
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.
ca_secrets = fetch_required_secrets.(resource_ids: [ca_cert_id, ca_key_id]) | |
ca_secrets = fetch_required_secrets.(resource_ids: [ca_info.cert_id, ca_info.key_id]) |
ca_cert_id = ca_info.cert_id | ||
ca_key_id = ca_info.key_id | ||
ca_secrets = fetch_required_secrets.(resource_ids: [ca_cert_id, ca_key_id]) | ||
stored_cert = ca_secrets[ca_cert_id] |
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.
stored_cert = ca_secrets[ca_cert_id] | |
stored_cert = ca_secrets[ca_info.cert_id] |
ca_key_id = ca_info.key_id | ||
ca_secrets = fetch_required_secrets.(resource_ids: [ca_cert_id, ca_key_id]) | ||
stored_cert = ca_secrets[ca_cert_id] | ||
stored_key = ca_secrets[ca_key_id] |
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.
stored_key = ca_secrets[ca_key_id] | |
stored_key = ca_secrets[ca_info.key_id] |
What does this PR do?
In order to avoid NoMethodError that can be raised when the ConjurCA relevant resources is missing/have no value, added custom exceptions which inform the proper error.
What ticket does this PR close?
resolves #1315
Checklists
Change log