Skip to content

lfsapi: support cross-scheme redirection#2235

Merged
ttaylorr merged 7 commits into
masterfrom
x-scheme-redirect
May 19, 2017
Merged

lfsapi: support cross-scheme redirection#2235
ttaylorr merged 7 commits into
masterfrom
x-scheme-redirect

Conversation

@ttaylorr

Copy link
Copy Markdown
Contributor

This pull request addresses #2185, and supports cross-scheme redirects in the *lfsapi.Client type.

The issue is that, even though Go's *net/http.Client supports redirects (in response to a 3xx status code) directly, we explicitly disable that as[1]:

httpClient := &http.Client{
  Transport: tr,
  CheckRedirect: func(*http.Request, []*http.Request) error {
    return http.ErrUseLastResponse
  },
}

So we're forced to handle HTTP requests ourselves in the lfsapi.Client.doWithRedirects function. This is fine, since we already have logic to rewind the body and copy the headers over.

As an aside, ideally we could hook into the net/http.Client.CheckRedirect field to hand this responsibility over to the net/http package, but the HTTP client follows an older RFC (which it maintains for backwards compatibility reasons) that prevents the client from copying the HTTP verb the request was sent with when a 301, 302, or 303 response code is given: (see: https://github.com/golang/go/blob/go1.8.1/src/net/http/client.go#L423-L429). We cannot work around this, so we must handle it ourselves.

This pull request expands the list of 3xx response codes that we will redirect from and increases the permissiveness of HTTP header copying to only check that the from->to host transition is the same, without checking the scheme.

Closes: #2185


/cc @git-lfs/core @larsxschneider

@technoweenie technoweenie left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A few minor notes, but this looks good overall. Could use some basic tests in lfsapi/client_test.go (or wherever any redirect tests currently live).

Comment thread lfsapi/client.go

for key := range req.Header {
if key == "Authorization" {
if req.URL.Scheme != newReq.URL.Scheme || req.URL.Host != newReq.URL.Host {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

What do you think about preventing https => http redirects? That'd prevent the client from inadvertently sending creds over an insecure channel.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

That sounds sensible to me. I wonder if there could ever be a legitimate use case for a https ==> http redirect?!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I added some code in 36944dc in order to prevent insecure redirects. If a redirect is sent from HTTPS down to HTTP, the following error will be given:

lfsapi/client: refusing insecure redirect, https->http

Comment thread lfsapi/client.go
res.StatusCode != 302 &&
res.StatusCode != 303 &&
res.StatusCode != 307 &&
res.StatusCode != 308 {

@technoweenie technoweenie May 18, 2017

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This is kind of gross. I'd prefer a map or switch statement.

The code is direct, and is probably fine the way it is. I wouldn't worry about extracting something like a map or func unless this check needs to be shared.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Thanks 👍. I don't have strong feelings either way and don't want to reach for a map/func until we need to share this check somewhere else.

@ttaylorr

Copy link
Copy Markdown
Contributor Author

@technoweenie @larsxschneider thanks for the review! I added some tests in 38417f3 to cover this new behavior, and I think this is ready to merge.

A note about the tests: I initially wanted to test same and cross-host redirects, but I can't listen on the same serve in both HTTPs and HTTP in order to do a same-host secure upgrade, so the test coverage is as complete as possible.

@technoweenie technoweenie left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nice job on the test 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants