Skip to content

Conversation

@jbardin
Copy link
Member

@jbardin jbardin commented Jun 7, 2022

When checking for an unexpected protocol switch via X-Terraform-Get, we
first must run the configured detectors and check for a relative request
path, since X-Terraform-Get is not required to return a valid URL.

Fixes #368

When checking for an unexpected protocol switch via X-Terraform-Get, we
first must run the configured detectors and check for a relative request
path, since X-Terraform-Get is not required to return a valid URL.
@jbardin jbardin requested review from eastebry and nywilken June 7, 2022 16:07
@jbardin jbardin force-pushed the jbardin/protocol-check branch from 5d29c21 to 28c40be Compare June 7, 2022 16:11
Copy link
Contributor

@nywilken nywilken left a comment

Choose a reason for hiding this comment

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

The changes look good to me. I have a couple of questions on the handling of sub directory and relative path requests. I'm approving in advance in case my questions are just due to my gaps of knowledge around go-getter.

But feel free to ping me again for another review if the questions result in a change.

get_http.go Outdated
var opts []ClientOption
if subDir != "" {
// We have a subdir, time to jump some hoops
return g.getSubdir(ctx, dst, source, subDir)
Copy link
Contributor

Choose a reason for hiding this comment

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

I was a little confused about the call to getSubdir the first time I read this code. Is the source being used here the value returned from the X-Terraform-Get header?

If so, would we not want to run the protocol switch check before returning? Or will this be handled in the final call to Get that is made in the getSubdir function?

Copy link
Member Author

Choose a reason for hiding this comment

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

That's a good question. While the PR looks big because I dropped a level of indentation by returning early, I left the overall logic the same. I think you may be right that a subdir would bypass the the protocol checks since it goes on to call Get just like below -- I'll follow up with a refactor of getSubdir so we can pass in the same options

Copy link
Member Author

Choose a reason for hiding this comment

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

The new proto checks were bypassed by the addition of a subdirectory component to the url. I refactored this a bit to move the getSubdir call after the checks, and pass in the same options we would use for Get.

}

protocol := ""
// X-Terraform-Get allows paths relative to the previous request too,
Copy link
Contributor

Choose a reason for hiding this comment

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

For my knowledge in the case of a relative path request how does go-getter know the url used in the previous request? I don't see it being passed into the next Get request.

Copy link
Member Author

Choose a reason for hiding this comment

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

I don't think relative paths actually work in this mode, but I added the check for completeness, and so that we can return any intended error later, rather than a more confusing no getter available message.

Use the same protocol switching checks when there's a subdir, passing
the limited set of getters if there is wrapping client.
@jbardin jbardin requested a review from nywilken June 8, 2022 17:54
Copy link
Contributor

@nywilken nywilken 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 answering my questions. The updated check for subDir looks good to me. I pinged @picatz just for visibility as it changes how the getter logic was understood at first.

// If there's a subdirectory, we will also need a file getter to
// unpack it.
opts = append(opts, WithGetters(map[string]Getter{
"file": new(FileGetter),
Copy link
Contributor

Choose a reason for hiding this comment

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

@picatz pinging for visibility as the need changes the mental model a little.

Copy link

Choose a reason for hiding this comment

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

Thank you for the ping!

The intent for this original check was to totally prevent the HttpGetter from allowing cross-protocol switching unless the getter was already supported by a Client. I understand the reasoning for the FileGetter with a subdirectory component, but I hate this is allowed at all. It has the potential to be dangerous, and generally not desirable from a security standpoint.

Thankfully, I don't think it would cause problems for Nomad, who explicitly disable the FileGetter because it's dangerous in their context. They use a Client directly. But I could see this causing problems in other contexts. Likely outside of HashiCorp.

I would much rather this be a new option on the HttpGetter, rather than be implicitly allowed by default. Maybe something like:

httpGetter := &HttpGetter{
  AllowFileGetterForSubDirectoryComponent: true,
}

What do you think? Would that be an acceptable solution?

Copy link
Member Author

@jbardin jbardin Jun 9, 2022

Choose a reason for hiding this comment

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

To be clear, this is more limiting than the current release, since getSubdir was falling back to all the default getters. We can't really change this in version 1, since it's a breaking change. While X-Terraform-Get probably shouldn't have been so liberal in spec, the protocol does define any valid go-getter source string is a valid value, including subdirectories. I think the only valid way to avoid this is to disable X-Terraform-Get, which we have an option for already.

Copy link

Choose a reason for hiding this comment

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

To be clear getSubdir was falling back to all default getters when using the HttpGetter directly?

Aside from that clarification: I think I agreed with you, that disabling X-Terraform-Get would generally be the "right" solution, as opposed to an additional option.

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 now these checks are only run if subDir == "", otherwise we just call getSubDir, which runs Get with the default options, bypassing the forced http+https getters entirely. This change now at least will force the http+https getters with subdirectories too.

@jbardin jbardin requested review from picatz and removed request for eastebry June 9, 2022 17:34
@eastebry eastebry self-requested a review June 13, 2022 18:23
@jbardin jbardin merged commit ef2fcc6 into main Jun 13, 2022
@jbardin jbardin deleted the jbardin/protocol-check branch June 13, 2022 18:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

no getter available for X-Terraform-Get source protocol

4 participants