hashicorp / terraform

Terraform enables you to safely and predictably create, change, and improve infrastructure. It is a source-available tool that codifies APIs into declarative configuration files that can be shared amongst team members, treated as code, edited, reviewed, and versioned.
https://www.terraform.io/
Other
42.43k stars 9.51k forks source link

Support custom state storage as a "Terraform-native Service" protocol, with "terraform login" support #35399

Open sylvainmouquet opened 3 months ago

sylvainmouquet commented 3 months ago

Terraform Version

Terraform v1.9.0
on darwin_arm64

Use Cases

All http requests to blob storage https://archivist.terraform.io/ are done without an authorization header. When a user want to create his own remote backend (remote or cloud), some calls must to be defined without the authorization header (logs, ...) and it's not secured! It forces developer to implement a new security system based on other thing than the bearer. Or to add the bearer in the url path. To simplify, we can add the authorization bearer in all http requests and it's the accountability of the developer to check in the backend api the access to the resource.

More information about the blob storage authentication : https://developer.hashicorp.com/terraform/cloud-docs/api-docs#blob-storage-authentication

The goal of this issue is to add the authorization header for all http requests made by the cli

Attempted Solutions

In internal/cloud/backend.go and internal/backend/remote/backend.go, the authorization bearer is added in the default headers :

// Add the authorization bearer
cfg.Headers.Set("Authorization", "Bearer "+token)

Proposal

No response

References

No response

apparentlymart commented 3 months ago

Hi @sylvainmouquet! Thanks for this feedback.

From what you've described, it sounds like you are intending to create a server reimplementing some or all of HCP Terraform's API, and then use it with the client for that API that's embedded in Terraform CLI's HCP Terraform integration (the cloud block) and the remote backend.

The HCP Terraform API is not intended as an external integration point for third-party software. HCP Terraform and Terraform Enterprise are the only supported servers for that API, by design. As you've noticed, HCP Terraform's Archivist component does not use Bearer authentication and therefore Terraform CLI's client for it also does not. We do not intend to add any features to Terraform CLI's client for this API except those needed by new HCP Terraform features.


Terraform CLI's http backend is the intended integration point for third-party state storage implementations that are not already supported by one of the other state storage backends.

The http backend currently supports either Basic authentication with a username and password or TLS authentication using client certificates. It doesn't currently support the Bearer authentication scheme, but it could potentially do so. Would adding support for the Bearer scheme to the HTTP backend make it suitable for your goals?

If so, I'd like to reframe this as a feature request for the http backend.

Thanks again!

sylvainmouquet commented 3 months ago

Hello @apparentlymart thanks for you response.

In the past, i have already implemented a remote backend of type http but there is some lacks if we compare with the remote backend backend:

Thanks

apparentlymart commented 3 months ago

Thanks for that extra context, @sylvainmouquet.

There are some existing issues that overlap with some of that feedback:

I think therefore that only leaves the idea of integrating with terraform login, so let's use this issue to represent that.

That idea is interesting, but terraform login is designed primarily for "Terraform-native services" and the http backend is not designed as a Terraform-native service -- it uses explicit absolute URLs rather than a single hostname and service discovery .

Therefore I think supporting terraform login also implies supporting service discovery, because terraform login assumes that the service is identified only by a single hostname.


This reminds me of an old idea that we discussed a while ago but weren't able to prioritize, which involved something like this:

If we did what I described above then the Terraform configuration author would probably still write a backend "remote" block, and then internally the backend would either use the proprietary HCP Terraform API or this documented state storage API depending on the result of performing service discovery on the specified hostname. This is essentially the same design as for terraform login, which chooses between using the login protocol or the proprietary HCP Terraform API equivalent depending on the service discovery result.

I want to be up front that I doubt we'll be able to prioritize such a thing in the near future because our focus is elsewhere, and we're also still considering the possibility of allowing state storage to be implemented in provider plugins rather than as builtins (https://github.com/hashicorp/terraform/issues/5877) and that idea seems mutually-exclusive with this one. But nonetheless I'm going to relabel this issue to represent this alternative, which would put the target-specific logic in the remote server rather than in a client-side plugin.

If others find this issue and are also interested in potentially implementing a server-side implementation of a state storage protocol similar to what I described above, please add a :+1: vote to the original issue comment (not to this comment) which we use as one of the inputs prioritize work.