Skip to content
This repository has been archived by the owner on Mar 5, 2024. It is now read-only.

Restrict metadata routes #110

Merged
merged 9 commits into from
Jul 13, 2018
Merged

Restrict metadata routes #110

merged 9 commits into from
Jul 13, 2018

Conversation

samb1729
Copy link
Contributor

@samb1729 samb1729 commented Jul 4, 2018

This set of changes adds a flag to kiam agent which allows the user to provide a regular expression that a request path must match to be proxied to the metadata service. The parameter doesn't affect any requests that are handled by kiam directly.

By default its value is set to .* which means all requests are allowed.

Resolves #60

@samb1729 samb1729 requested a review from pingles July 4, 2018 16:52
@pingles
Copy link
Contributor

pingles commented Jul 4, 2018

Thanks for this @Sambooo. If you don't mind let's take a look at what we can do to update the testing to bring in line with the (unfortunately mammoth, sorry) changes I made in #109.

@samb1729
Copy link
Contributor Author

samb1729 commented Jul 5, 2018

update the testing to bring in line with ... #109.

Sure, let's gets that PR merged and I'll rebase

@samb1729 samb1729 force-pushed the restrict-metadata-routes branch from 5f30658 to 93794bd Compare July 6, 2018 16:03
@samb1729 samb1729 changed the base branch from master to api-v3 July 6, 2018 16:03
@samb1729
Copy link
Contributor Author

samb1729 commented Jul 6, 2018

I've just pushed having rebased onto api-v3. Updated tests still to come.

@codecov
Copy link

codecov bot commented Jul 6, 2018

Codecov Report

Merging #110 into api-v3 will increase coverage by 1.93%.
The diff coverage is 58%.

Impacted file tree graph

@@            Coverage Diff             @@
##           api-v3     #110      +/-   ##
==========================================
+ Coverage   37.79%   39.73%   +1.93%     
==========================================
  Files          21       22       +1     
  Lines         799      828      +29     
==========================================
+ Hits          302      329      +27     
- Misses        469      471       +2     
  Partials       28       28
Impacted Files Coverage Δ
pkg/aws/metadata/handler_health.go 0% <0%> (ø) ⬆️
pkg/aws/metadata/server.go 5.76% <0%> (+0.31%) ⬆️
pkg/aws/metadata/handler_credentials.go 85% <100%> (+1.66%) ⬆️
pkg/aws/metadata/handler_role_name.go 90.9% <100%> (+0.9%) ⬆️
pkg/aws/metadata/handler_proxy.go 100% <100%> (ø)

@samb1729 samb1729 force-pushed the restrict-metadata-routes branch from 93794bd to 6ae2c26 Compare July 9, 2018 15:43
@@ -45,6 +47,7 @@ func (cmd *agentCommand) Bind(parser parser) {

parser.Flag("port", "HTTP port").Default("3100").IntVar(&cmd.port)
parser.Flag("allow-ip-query", "Allow client IP to be specified with ?ip. Development use only.").Default("false").BoolVar(&cmd.allowIPQuery)
parser.Flag("allowed-routes", "Proxy routes matching this regular expression").Default(".*").RegexpVar(&cmd.allowedRoutes)

Choose a reason for hiding this comment

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

Should the flag be plural - routes - if we only allow it to be specified once?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

it's a regular expression which can match many routes

Copy link
Contributor

Choose a reason for hiding this comment

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

Perhaps then we could rename to specify that it's a regexp? So, change it to:

kiam server --whitelist-route-regexp=.*

Thoughts @Sambooo and @ewbankkit? Agree about the plural name though- we don't support multiple regexes so it'd be good to name it singularly to avoid confusion.

Choose a reason for hiding this comment

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

Naming is the hardest problem 😄.
No particular opinion on this one but I think some documented examples would be good.

p.reverseProxy.ServeHTTP(writer, r)
return writer.status, nil
} else {
return http.StatusForbidden, fmt.Errorf("request blocked by allowedRoutes pattern %q: %s", p.allowedRoutes, route)

Choose a reason for hiding this comment

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

Is 403 the correct HTTP status code to return?
From RFC 7231:

An origin server that wishes to "hide" the current existence of a
forbidden target resource MAY instead respond with a status code of
404 (Not Found).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

the request is not allowed by (does not match) the allowed-routes regular expression, so the request is forbidden by the configuration. which status code should be returned in this case?

Choose a reason for hiding this comment

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

I don't think there's a "correct" answer. Either would be valid.

Copy link
Contributor

Choose a reason for hiding this comment

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

Given that RFC maybe we should favour 404?

We should still log that it was blocked via a warning because of the path regexp (so that its easy for operators to record/debug) but 404 feels like it leaks less information to clients.

@uswitch/cloud any other thoughts? Feels pretty close to a coin toss though 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have no issues with changing the status code here since I went with my gut and MAY means it's up to us. Flip that coin.

samb1729 added 2 commits July 12, 2018 17:11
At the moment the flag parsing library we use will tell a user that this
parameter is a regular expression, but it's possible that a migration to cobra
or similar will make that help string disappear or change to 'string'. Since we
don't test the output of `--help`, instead make the name reflect the type.
@pingles
Copy link
Contributor

pingles commented Jul 12, 2018

Awesome. Last piece of the puzzle is that we want to require metadata API routes to be whitelisted, rather than permitting all by default (this was originally raised in #60).

I think once that's changed we're good to merge!

Copy link
Contributor

@pingles pingles left a comment

Choose a reason for hiding this comment

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

Thanks for all this @Sambooo. Left a few comments for some final changes.

clientIP clientIPFunc
client server.Client
client server.Client
ipResolver clientIPFunc
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd rename ipResolver to getClientIP

ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()

allowedRoutes := regexp.MustCompile("^$")
Copy link
Contributor

Choose a reason for hiding this comment

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

If we're not going to move this statement inside newProxyHandler I'd like the expression stored in a const for something like WhitelistDefaultBlockEverything so that it can be referenced in both the package and test.

ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()

allowedRoutes := regexp.MustCompile("foo.*")
Copy link
Contributor

Choose a reason for hiding this comment

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

Passing in a non-default regexp is fine though

client server.Client
clientIP clientIPFunc
client server.Client
ipResolver clientIPFunc
Copy link
Contributor

Choose a reason for hiding this comment

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

As before, I'd prefer this to be named getClientIP.

}

func NewConfig(port int) *ServerConfig {
func NewConfig(port int, allowIPQuery bool, whitelistRouteRegexp *regexp.Regexp) *ServerConfig {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd rather we didn't expand NewConfig to include all options.

To be honest, I'd prefer it didn't specify a port but set good defaults for everything and then clients set individual fields.

Otherwise, as the struct grows we're just adding more and more params to the function which isn't nice.

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 rename the func to DefaultConfig too.

@pingles pingles merged commit afdb221 into api-v3 Jul 13, 2018
@pingles pingles deleted the restrict-metadata-routes branch July 13, 2018 14:37
mbarrien pushed a commit to mbarrien/helm-kiam that referenced this pull request Sep 15, 2018
pingles pushed a commit that referenced this pull request Oct 25, 2018
* Parameterise allowed metadata API routes
* Add filtered metadata routes in the same way as other handlers
* Add proxyHandler tests
* Add whitelist-route-regexp flag
* Block all non-kiam metadata api requests by default
* Extract handler constructors to put default under test
* Rename client IP func to getClientIP
* Embed agent server options into CLI flags
@pingles pingles mentioned this pull request Oct 25, 2018
pingles pushed a commit that referenced this pull request Oct 31, 2018
Restrict metadata routes (#110)

* Parameterise allowed metadata API routes
* Add filtered metadata routes in the same way as other handlers
* Add proxyHandler tests
* Add whitelist-route-regexp flag
* Block all non-kiam metadata api requests by default
* Extract handler constructors to put default under test
* Rename client IP func to getClientIP
* Embed agent server options into CLI flags
pingles added a commit that referenced this pull request Nov 5, 2018
* merging cherry-picked from missing v3 commit
Restrict metadata routes (#110)
* Parameterise allowed metadata API routes
* Add filtered metadata routes in the same way as other handlers
* Add proxyHandler tests
* Add whitelist-route-regexp flag
* Block all non-kiam metadata api requests by default
* Extract handler constructors to put default under test
* Rename client IP func to getClientIP
* Embed agent server options into CLI flags
* targets in Makefile to specify bin rather than phony
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants