Support custom state storage as a "Terraform-native Service" protocol, with "terraform login" support
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
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!
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:
- the usage of bearer in rather than basic authentication (as you have explained) and the compatibility with
terraform login - the usage of workspaces and organizations for using
terraform workspacecommands. Very useful when users have a lot of workspaces, they can navigate to the workspaces and switch easily with the command line without editing the backend.tf file - the management of the bearer expiration with a automatic renew or with the
terraform login
Thanks
Thanks for that extra context, @sylvainmouquet.
There are some existing issues that overlap with some of that feedback:
- https://github.com/hashicorp/terraform/issues/26797 represents support for multiple workspaces
- https://github.com/hashicorp/terraform/issues/22526 actually seems to already represent bearer token support, which I missed in my search when I was replying the first time
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:
- Define a new Terraform-native service type
statestorage.v1, which can be declared in a Terraform service discovery document alongsidelogin.v1. It would be map to a single base URL for a predefined protocol for state storage, similar to Terraform's existing module and provider registry protocols. - The
remotebackend already performs service discovery to find the HCP Terraform API, so it could also notice that the service discovery document supportsstatestorage.v1and use that protocol for state storage, instead of the proprietary HCP Terraform API, when available. - That new protocol can be designed to directly support each of the operations a remote state backend needs to support, using a predefined set of HTTP methods and relative URLs instead of the client-side configuration we have for the
httpbackend:- List all existing workspaces
- Create a new workspace
- Delete a workspace (including the option to force when the workspace state is tracking at least one remote object)
- Get the latest state snapshot for a specific workspace
- Write a new state snapshot for a specific workspace
- Acquire an advisory lock for a specific workspace
- Release a previously-acquired advisory lock
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.
can I take it ?