Skip to content
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

Deny location mapping in case of specific errors #95

Merged
merged 4 commits into from
Jan 13, 2017

Conversation

aledbf
Copy link
Member

@aledbf aledbf commented Dec 29, 2016

fixes #16
fixes #108

@aledbf aledbf self-assigned this Dec 29, 2016
@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Dec 29, 2016
@k8s-reviewable
Copy link

This change is Reviewable

@aledbf aledbf added backend/generic nginx and removed cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. labels Dec 29, 2016
Copy link
Contributor

@euank euank left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are two problems I see with this change:

  1. Misconfigured annotations should be a server error (5xx), not client.

There are a few reasons for this. These errors are actually server configuration problems, so that's more honest.

More importantly, most monitoring/notification systems ignore 4xx (as you must in the day of mass internet scanning, brute forcing, and DoSing), so the error is far less likely to be noticed by the operator.

  1. There's still no error printed at a reasonable V. The message is nice (thanks!), but if it's printed at V5 no one will see it.

I'm okay with 2 in a followup. 1 I think needs to be addressed.

@aledbf
Copy link
Member Author

aledbf commented Jan 5, 2017

Misconfigured annotations should be a server error (5xx), not client.

I choose 403 because most of the annotations are related to security.
I saw this from a user perspective. Exactly which code in the 5xx family you suggest?

@euank
Copy link
Contributor

euank commented Jan 5, 2017

500 or 503, probably 503

I think we should also have a similar error for all annotations, even those not closely related to security, but these are definitely the most important ones to cover.

@aledbf
Copy link
Member Author

aledbf commented Jan 5, 2017

There's still no error printed at a reasonable V. The message is nice (thanks!), but if it's printed at V5 no one will see it.

I think we can add an event and/or log the content of Denied error (just the first error to avoid flooding the log)

@k8s-ci-robot k8s-ci-robot added the cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. label Jan 5, 2017
@coveralls
Copy link

Coverage Status

Coverage decreased (-0.3%) to 40.398% when pulling 0a598daeaac2e5289b4da61176d697550a3cd53a on aledbf:deny into 5186e93 on kubernetes:master.

@aledbf aledbf force-pushed the deny branch 2 times, most recently from 5aca8b6 to 4d3ae91 Compare January 6, 2017 14:07
@coveralls
Copy link

Coverage Status

Coverage decreased (-0.004%) to 40.729% when pulling 4d3ae91b4d90b8016f848d0e1b33e7d415f2b4c3 on aledbf:deny into 5186e93 on kubernetes:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.6%) to 41.285% when pulling 1102cbd4378ac282bede827f97cb502b9271442d on aledbf:deny into 5186e93 on kubernetes:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.6%) to 41.35% when pulling 854af9eaa98484978c6423c68c872c68168d2f87 on aledbf:deny into 5186e93 on kubernetes:master.

Copy link
Contributor

@euank euank left a 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 a better model for annotation parsing.

My previous comment about error code still applies and I left a few more comments. I'll do another pass once both my comments and the 4xx vs 5xx bit are addressed.

)

func init() {
// TODO: check permissions required
os.MkdirAll(DefAuthDirectory, 0655)
os.MkdirAll(authDirectory, 0655)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we should move this to part of either NewParser or Parse and the authDirectory as an argument to NewParser?

Right now I think the unit test will run this init block and create /etc/ingress... on my machine before the test gets a chance to override it.

And init blocks that can be avoided probably should be.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And init blocks that can be avoided probably should be.

Right. I will try to remove the init func.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -65,40 +56,49 @@ type BasicDigest struct {
Secured bool `json:"secured"`
}

// ParseAnnotations parses the annotations contained in the ingress
type auth struct {
fn func(string) (*api.Secret, error)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: this can definitely be named better.

While we're refactoring though, this could also be an interface and I think that would be a bit more idiomatic.

e.g. SecretResolver { GetSecret(string) ...

And then cfg could just fulfil that interface and cfg could directly be passed in.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -39,27 +39,36 @@ type SSLCert struct {
PemSHA string `json:"pemSha"`
}

type authTLS struct {
fn func(secret string) (*SSLCert, error)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment above about interfaces

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}

if str == "" {
return &SSLCert{}, fmt.Errorf("an empty string is not a valid secret name")
return nil, ing_errors.LocationDenied{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for consistency, NewLocationDenied here, or use this sorta constructor everywhere and delete the New

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}

_, _, err = k8s.ParseNameNS(str)
if err != nil {
return &SSLCert{}, err
return nil, ing_errors.LocationDenied{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for this err

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done


func (e *annotationExtractor) Extract(ing *extensions.Ingress) map[string]interface{} {
anns := make(map[string]interface{}, 0)
for name, fn := range e.annotations {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fn isn't a func, so this naming is confusing.

Maybe name, annotationParser?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}
err := mergo.Map(loc, anns)
if err != nil {
glog.V(2).Infof("unexpected error merging extracted annotations in location type: %v", err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be a Warn or Error? When would this happen?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in theory never :)
I will switch this to default level and Error

@aledbf aledbf force-pushed the deny branch 2 times, most recently from a882646 to 5f6a472 Compare January 7, 2017 22:59
@coveralls
Copy link

Coverage Status

Coverage increased (+0.6%) to 41.858% when pulling 5f6a472b9ce5336a8ccb9a4321e46b7cc5909ba0 on aledbf:deny into b2d084a on kubernetes:master.

@aledbf
Copy link
Member Author

aledbf commented Jan 8, 2017

My previous comment about error code still applies and I left a few more comments.

With the new errors I changed the code to always print the errors. If the error is related to missing annotations (not an error really) that appears only in V(5).

I'll do another pass once both my comments and the 4xx vs 5xx bit are addressed.

Error code changed to 503

@coveralls
Copy link

Coverage Status

Coverage increased (+0.8%) to 42.069% when pulling 24d61bda0d010e4b3e789b3d81cc347ff8188b9a on aledbf:deny into e58f510 on kubernetes:master.

Copy link
Contributor

@euank euank left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly LGTM.

Would have been nice if the review comments were addressed in a new commit on top, not squashed in immediately.

@@ -69,6 +70,12 @@ func ReadConfig(conf *api.ConfigMap) config.Configuration {
to.SkipAccessLogURLs = skipUrls
to.WhitelistSourceRange = whitelist

h, err := dns.GetSystemNameServers()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change seems like it should be a separate PR; it doesn't seem related to the rest of this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right. Removed.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Moved to PR #123

func isLocationAllowed(input interface{}) bool {
loc, ok := input.(*ingress.Location)
if !ok {
return false
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

log an error too, this shouldn't ever happen

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

// AuthCertificate has a method that searchs for a secret
// that contains a SSL certificate.
// The secret must contain 3 keys named:
type AuthCertificate interface {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this also be in resolver for consistency (resolver.AuthCertificate to match resolver.Secret)?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's already there :( I'm not sure how to remove the cycle error that this introduces.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The easiest thing is probably to move the type up into resolver as well.

Something like this: euank@608cf8e

I think that's cleaner than the current interface duplication.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -93,3 +96,16 @@ func IsValidClass(ing *extensions.Ingress, class string) bool {

return cc == class
}

const denied = "Denied"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Export and re-use it as a key in the other places too

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@aledbf
Copy link
Member Author

aledbf commented Jan 10, 2017

Would have been nice if the review comments were addressed in a new commit on top, not squashed in immediately.

Sorry about that. I always be told to squash the commits.

@euank
Copy link
Contributor

euank commented Jan 10, 2017

Squash before merge, definitely, but it's often nicer to have review comments separate up until before merge.

@coveralls
Copy link

Coverage Status

Coverage increased (+1.2%) to 42.38% when pulling f45d5c65ff0e21f2a8d6797886dd823a1a8deff5 on aledbf:deny into f90e9ee on kubernetes:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+1.2%) to 42.38% when pulling f45d5c65ff0e21f2a8d6797886dd823a1a8deff5 on aledbf:deny into f90e9ee on kubernetes:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+1.2%) to 42.278% when pulling 8191245 on aledbf:deny into c49b03f on kubernetes:master.

val, err := annotationParser.Parse(ing)
glog.V(5).Infof("annotation %v in Ingress %v/%v: %v", name, ing.GetNamespace(), ing.GetName(), val)
if err != nil {
_, de := anns["Denied"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would be nice to use the const here too. It makes it easier to find where that key's set programmatically.

Copy link
Contributor

@euank euank Jan 12, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, 'de' -> 'alreadyDenied' would be more readable imo

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

}

return fn(str)
return a.certResolver.GetAuthCertificate(str)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it makes sense to wrap the error returned from this in a location denied.

This errors if the referenced cert can't be resolved, and that sounds like excellent grounds to deny.

glog.Errorf("error reading %v annotation in Ingress %v/%v: %v", name, ing.GetNamespace(), ing.GetName(), err)
continue
}
glog.V(5).Infof("error reading %v annotation in Ingress %v/%v: %v", name, ing.GetNamespace(), ing.GetName(), err)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The GetAuthCertificate thing above I think is an argument for changing the logic about setting the "Denied" key to default to true for any error, and only be skipped for a subset of recognized errors (e.g. AnnotationMissing).

For now we could just set denied here and refactor further if there are more errors that need to be treated differently.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right. Without this change we can end with the same error we have in 0.8.3.
Key "Denied" changes for any error now.

@euank
Copy link
Contributor

euank commented Jan 12, 2017

Review pass done, apologies for the delay on it. If you want to just handle the GetAuthCertificate bit now and consider more aggressive denying as a followup, I'm okay with that.

@coveralls
Copy link

Coverage Status

Coverage increased (+1.1%) to 42.225% when pulling 4a2146b on aledbf:deny into c49b03f on kubernetes:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+1.08%) to 42.192% when pulling 4a2146b on aledbf:deny into c49b03f on kubernetes:master.

Copy link
Contributor

@euank euank left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (with appropriate squashing ofc)

@aledbf aledbf merged commit 91c710f into kubernetes:master Jan 13, 2017
@aledbf
Copy link
Member Author

aledbf commented Jan 13, 2017

@euank thanks for the review!

@aledbf aledbf deleted the deny branch January 20, 2017 21:17
hnrytrn pushed a commit to hnrytrn/ingress-nginx that referenced this pull request Aug 9, 2018
haoqing0110 pushed a commit to stolostron/management-ingress that referenced this pull request Mar 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cncf-cla: yes Indicates the PR's author has signed the CNCF CLA. nginx
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Change default action for authentication annotation
5 participants