-
Notifications
You must be signed in to change notification settings - Fork 43
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 more validations to trust-policy parsing #43
Conversation
Signed-off-by: rgnote <5878554+rgnote@users.noreply.github.com>
go.mod
Outdated
@@ -6,3 +6,8 @@ require ( | |||
github.com/golang-jwt/jwt/v4 v4.4.1 | |||
github.com/opencontainers/go-digest v1.0.0 | |||
) | |||
|
|||
require ( | |||
github.com/go-ldap/ldap v3.0.3+incompatible // indirect |
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.
How is that ldap
is marked as indirect when it is directly referenced in our code?
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 should have run go mod tidy
. Also, I realized that I should use go-ldap v3 as mentioned here. Thanks for pointing this out. Will raise a new revision for this PR.
Signed-off-by: rgnote <5878554+rgnote@users.noreply.github.com>
@@ -3,6 +3,13 @@ module github.com/notaryproject/notation-go | |||
go 1.17 | |||
|
|||
require ( | |||
github.com/go-ldap/ldap/v3 v3.4.3 |
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.
go-ldap
has a dependency on github.com/Azure/go-ntlmssp
, but the functionality we need, DN validation does not. Is there a way to avoid this transitive dependency? Is the transitive dependency dropped during build as we do not use any types from github.com/Azure/go-ntlmssp
?
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.
AFAIK, final build will only include the specific methods and their dependencies. Although I could not confirm this with official Go docs, I found multiple online forums confirming this. Seems like https://github.com/jondot/goweight could help us see what's included in the final build. I added it to my TODO list to revisit later.
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.
unpopular opinion: Pulling in github.com/go-ldap/ldap
, which is a library to talk with LDAP servers, just for validating a DN, seems like using a sledgehammer to crack a nut.
I would argue it's better just to copy ldap.ParseDN
, and related tests, into notation-go
and remove that dependency.
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.
@qmuntal If we consume the whole package in our builds (like in java), then I agree with what you said. Thanks to Go static linking, our build will only include dn.ParseDN
and it's dependencies. I prefer to keep a dependency on go-ldap
to ensure we get the updates and security fixes. Also, go-ldap
is the most popular library for ldap in Go, I'm not too worried about having a dependency on it.
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.
Besides, I want to give them the credit rather than simply copying their code :)
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'm not that concerned about binary size, as Go is really good at prunning unnecessary code. I'm worried about having a sane dependency tree. Keeping it to the bare minimum is always a plus, even if it means duplicating code.
That said, this particular dependency is not a red line for me.
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.
One concern I had was, we would see patch updates to this package more frequently from go-ldap/ldap
package than we'd be actually impacted, as we are using a single type from the whole package. What is generally the process to handle patch updates to dependencies, will dependabot make this simpler?
@rgnote it's possible to copy a code files into our repo and still provide correct attribution to source repo.
I'd prefer copying the code in this case, it's not a one way decision, we can change it the other way if we wanted to later.
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.
Tracking this in #45
verification/helpers.go
Outdated
} | ||
|
||
// validateDistinguishedName validates if a DN name parsable and follows Notary V2 rules | ||
func validateDistinguishedName(name string) error { |
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.
IMO, this method should move into notation-core-go
. All X509 related parsing, validation, cert chain validation logic should be pushed there.
On second thought, this is Notary V2 specific DN validation based on what we allow in trust policy, so seems appropriate 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.
Should this method and validateRegistryScopeFormat
be part of policy.go, they are only used in the context of validating a trust policy statement.
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.
These helpers are for policy validation but I wanted to move them to a helper file so that policy.go is cleaner and deals with higher level functionality like policy verification. There is no side effect of having these methods in a helper class as Go package is a closure of everything under the package directory.
verification/helpers.go
Outdated
dn, err := ldapv3.ParseDN(name) | ||
|
||
if err != nil { | ||
return fmt.Errorf("distinguished name (DN) %q is not valid, make sure it is following rfc4514 standard", name) |
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.
return fmt.Errorf("distinguished name (DN) %q is not valid, make sure it is following rfc4514 standard", name) | |
return fmt.Errorf("distinguished name (DN) %q is not valid, it must contain 'C', 'ST', and 'O' RDN attributes at a minimum, and follow RFC 4514 standard", name) |
verification/helpers.go
Outdated
// Verify there are no duplicate RDNs (multi-valdued RDNs are not supported) | ||
for key := range rDnCount { | ||
if rDnCount[key] > 1 { | ||
return fmt.Errorf("distinguished name (DN) %q has duplicate RDNs, DN can only have unique RDNs", name) | ||
} | ||
} |
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.
Duplicate is different from multi valued RDN, correct?
Multi-valued - OU=Sales+CN=J. Smith,DC=example
Duplicate -OU=Sales,DC=example,DC=net
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.
End customers may not be familiar with terminology RDN
// Verify there are no duplicate RDNs (multi-valdued RDNs are not supported) | |
for key := range rDnCount { | |
if rDnCount[key] > 1 { | |
return fmt.Errorf("distinguished name (DN) %q has duplicate RDNs, DN can only have unique RDNs", name) | |
} | |
} | |
// Verify there are no duplicate RDNs (multi-valdued RDNs are not supported) | |
for key := range rDnCount { | |
if rDnCount[key] > 1 { | |
return fmt.Errorf("distinguished name (DN) %q has duplicate RDN attribute for %q, DN can only have unique RDN attributes", name, key ) | |
} | |
} |
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.
go-ldap
does support multi-valued RDNs, hence notation-go lib can also support them. However, we should reject duplicate RDNs (OU=Sales,DC=example,DC=net
) as there is no usecase for them in notary V2.
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.
We want notation-go lib to not support multi-valued RDNs as they are not commonly used, and confusing for end customers.
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.
Addressed
verification/helpers.go
Outdated
// Verify mandatory fields are present | ||
for _, field := range mandatoryFields { | ||
if rDnCount[field] != 1 { | ||
return fmt.Errorf("distinguished name (DN) %q has no mandatory RDN for %q", name, field) |
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.
return fmt.Errorf("distinguished name (DN) %q has no mandatory RDN for %q", name, field) | |
return fmt.Errorf("distinguished name (DN) %q has no mandatory RDN attribute for %q, it must contain 'C', 'ST', and 'O' RDN attributes at a minimum", name, field) |
@@ -3,6 +3,13 @@ module github.com/notaryproject/notation-go | |||
go 1.17 | |||
|
|||
require ( | |||
github.com/go-ldap/ldap/v3 v3.4.3 |
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.
One concern I had was, we would see patch updates to this package more frequently from go-ldap/ldap
package than we'd be actually impacted, as we are using a single type from the whole package. What is generally the process to handle patch updates to dependencies, will dependabot make this simpler?
@rgnote it's possible to copy a code files into our repo and still provide correct attribution to source repo.
I'd prefer copying the code in this case, it's not a one way decision, we can change it the other way if we wanted to later.
Signed-off-by: rgnote <5878554+rgnote@users.noreply.github.com>
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.
LGTM!
Signed-off-by: rgnote <5878554+rgnote@users.noreply.github.com>
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.
LGTM
Changes:
Testing:
Added more unit tests and extensively tested the logic with local dummy policy files
Signed-off-by: rgnote 5878554+rgnote@users.noreply.github.com