website: Documentation for the "terraform login" command (#22727)

Co-authored-by: Alisdair McDiarmid <alisdair@users.noreply.github.com>
This commit is contained in:
Martin Atkins
2020-02-04 06:30:40 -10:00
committed by GitHub
parent f34cba407f
commit 778f1ab138
7 changed files with 423 additions and 30 deletions

View File

@@ -0,0 +1,171 @@
---
layout: "docs"
page_title: "Credentials Helpers"
sidebar_current: "docs-internals-credentials-helpers"
description: |-
Credentials helpers are external programs that know how to store and retrieve API tokens for remote Terraform services.
---
# Credentials Helpers
For Terraform-specific features that interact with remote network services,
such as [module registries](/docs/registry/) and
[remote operations](/docs/cloud/run/cli.html), Terraform by default looks for
API credentials to use in these calls in
[the CLI configuration](/docs/commands/cli-config.html).
Credentials helpers offer an alternative approach that allows you to customize
how Terraform obtains credentials using an external program, which can then
directly access an existing secrets management system in your organization.
This page is about how to write and install a credentials helper. To learn
how to configure a credentials helper that was already installed, see
[the CLI config Credentials Helpers section](/docs/commands/cli-config.html#credentials-helpers).
## How Terraform finds Credentials Helpers
A credentials helper is a normal executable program that is installed in a
particular location and whose name follows a specific naming convention.
A credentials helper called "credstore", for example, would be implemented as
an executable program named `terraform-credentials-credstore` (with an `.exe`
extension on Windows only), and installed in one of the
[default plugin search locations](/docs/extend/how-terraform-works.html#plugin-locations).
## How Terraform runs Credentials Helpers
Once Terraform has located the configured credentials helper, it will execute
it once for each credentials request that cannot be satisfied by a `credentials`
block in the CLI configuration.
For the following examples, we'll assume a "credstore" credentials helper
configured as follows:
```
credentials_helper "credstore" {
args = ["--host=credstore.example.com"]
}
```
Terraform runs the helper program with each of the arguments given in `args`,
followed by an _verb_ and then the hostname that the verb will apply to.
The current set of verbs are:
* `get`: retrieve the credentials for the given hostname
* `store`: store new credentials for the given hostname
* `forget`: delete any stored credentials for the given hostname
To represent credentials, the credentials helper protocol uses a JSON object
whose contents correspond with the contents of
[`credentials` blocks in the CLI configuration](/docs/commands/cli-config.html#credentials).
To represent an API token, the object contains a property called "token" whose
value is the token string:
```json
{
"token": "example-token-value"
}
```
The following sections describe the specific expected behaviors for each of the
three verbs.
## `get`: retrieve the credentials for the given hostname
To retrieve credentials for `app.terraform.io`, Terraform would run the
"credstore" helper as follows:
```
terraform-credentials-credstore --host=credstore.example.com get app.terraform.io
```
If the credentials helper is able to provide credentials for the given host
then it must print a JSON credentials object to its stdout stream and then
exit with status code zero to indicate success.
If it is unable to provide the requested credentials for any reason, it must
print an end-user-oriented plain text error message to its stderr stream and
then exit with a _non-zero_ status code.
## `store`: store new credentials for the given hostname
To store new credentials for `app.terraform.io`, Terraform would run the
"credstore" helper as follows:
```
terraform-credentials-credstore --host=credstore.example.com store app.terraform.io
```
Terraform then writes a JSON credentials object to the helper program's stdin
stream. If the helper is able to store the given credentials then it must do
so and then exit with status code zero and no output on stdout or stderr to
indicate success.
If it is unable to store the given credentials for any reason, it _must_ still
fully read its stdin until EOF and then print an end-user-oriented plain text
error message to its stderr stream before exiting with a non-zero status
code.
The new credentials must fully replace any existing credentials stored for the
given hostname.
## `forget`: delete any stored credentials for the given hostname
To forget any existing credentials for `app.terraform.io`, Terraform would run
the "credstore" helper as follows:
```
terraform-credentials-credstore --host=credstore.example.com forget app.terraform.io
```
No JSON credentials objects are used for the `forget` verb.
If the helper program is able to delete its stored credentials for the given
hostname or if there are no such credentials stored already then it must
exist with status code zero and produce no output on stdout or stderr.
If it is unable to forget the stored credentials for any reason, particularly
if the helper cannot be sure that the credentials are no longer available for
retrieval, the helper program must print an end-user-oriented plain text error
message to its stderr stream and then exit with a non-zero status code.
## Handling Other Commands
The credentials helper protocol may be extended with additional verbs in future,
so for forward-compatibility a credentials helper must react to any unsupported
verb by printing an end-user-oriented plain text error message to its stderr
stream and then exiting with a non-zero status code.
## Handling Unsupported Credentials Object Properties
Currently Terraform defines only the `token` property within JSON credentials
objects, but this format might be extended in future.
If a credentials helper is asked to store an object that has any properties
other than `token` and if it is not able to faithfully retain them then it
must behave as if the object is unstorable, returning an error. It must _not_
store the `token` value in isolation and silently drop other properties, as
that might change the meaning of the credentials object.
If technically possible within the constraints of the target system, a
credentials helper should prefer to store the whole JSON object as-is for
later retrieval. For systems that are more constrained, it's acceptable to
store only the `token` string so long as the program rejects objects containing
other properties as described above.
## Installing a Credentials Helper
Terraform does not have any automatic installation mechanism for credentials
helpers. Instead, the user must extract the helper program executable into
one of the [default plugin search locations](/docs/extend/how-terraform-works.html#plugin-locations).
If you are packaging a credentials helper for distribution, place it in an
named with the expected naming scheme (`terraform-credentials-example`) and,
if the containing archive format supports it and it's meaningful for the
target operating system, mark the file as executable to increase the chances
that it will work immediately after extraction.
Terraform does _not_ honor the `-plugin-dir` argument to `terraform init` when
searching for credentials helpers, because credentials are also used by other
commands that can be run prior to `terraform init`. Only the default search
locations are supported.

View File

@@ -0,0 +1,114 @@
---
layout: "docs"
page_title: "Login Protocol"
sidebar_current: "docs-internals-login-protocol"
description: |-
The login protocol is used for authenticating Terraform against servers providing Terraform-native services.
---
# Server-side Login Protocol
~> **Note:** You don't need to read these docs to _use_
[`terraform login`](/docs/commands/login.html). The information below is for
anyone intending to implement the server side of `terraform login` in order to
offer Terraform-native services in a third-party system.
The `terraform login` command supports performing an OAuth 2.0 authorization
request using configuration provided by the target host. You may wish to
implement this protocol if you are producing a third-party implementation of
any [Terraform-native services](/docs/internals/remote-service-discovery.html),
such as a Terraform module registry.
First, Terraform uses
[remote service discovery](/docs/internals/remote-service-discovery.html) to
find the OAuth configuration for the host. The host must support the service
name `login.v1` and define for it an object containing OAuth client
configuration values, like this:
```json
{
"login.v1": {
"client": "terraform-cli",
"grant_types": ["authz_code"],
"authz": "/oauth/authorization",
"token": "/oauth/token",
"ports": [10000, 10010],
}
}
```
The properties within the discovery object are as follows:
* `client` (Required): The `client_id` value to use when making requests, as
defined in [RFC 6749 section 2.2](https://tools.ietf.org/html/rfc6749#section-2.2).
Because Terraform is a _public client_ (it is installed on end-user systems
and thus cannot protect an OAuth client secret), the `client_id` is purely
advisory and the server must not use it as a guarantee that an authorization
request is truly coming from Terraform.
* `grant_types` (Optional): A JSON array of strings describing a set of OAuth
2.0 grant types the server is able to support. A "grant type" selects a
specific mechanism by which an OAuth server authenticates the request and
issues an authorization token.
Terraform CLI currently only supports a single grant type:
* `authz_code`: [authorization code grant](https://tools.ietf.org/html/rfc6749#section-4.1).
Both the `authz` and `token` properties are required when `authz_code` is
present.
Other grant types may be supported in future versions of Terraform CLI,
and may impose different requirements on the `authz` and `token` properties.
If not specified, `grant_types` defaults to `["authz_code"]`.
* `authz` (Required if needed for a given grant type): the server's
[authorization endpoint](https://tools.ietf.org/html/rfc6749#section-3.1).
If given as a relative URL, it is resolved from the location of the
service discovery document.
* `token` (Required if needed for a given grant type): the server's
[token endpoint](https://tools.ietf.org/html/rfc6749#section-3.2).
If given as a relative URL, it is resolved from the location of the
service discovery document.
* `ports` (Optional): A two-element JSON array giving an inclusive range of
TCP ports that Terraform may use for the temporary HTTP server it will start
to provide the [redirection endpoint](https://tools.ietf.org/html/rfc6749#section-3.1.2)
for the first step of an authorization code grant. Terraform opens a TCP
listen port on the loopback interface in order to receive the response from
the server's authorization endpoint.
If not specified, Terraform is free to select any TCP port greater than or
equal to 1024.
Terraform allows constraining this port range for interoperability with OAuth
server implementations that require each `client_id` to be associated with
a fixed set of valid redirection endpoint URLs. Configure such a server
to expect a range of URLs of the form `http://localhost:10000/`
with different consecutive port numbers, and then specify that port range
using `ports`.
We recommend allowing at least 10 distinct port numbers if possible, and
assigning them to numbers greater than or equal to 10000, to minimize the
risk that all of the possible ports will already be in use on a particular
system.
When requesting an authorization code grant, Terraform CLI implements the
[Proof Key for Code Exchange](https://tools.ietf.org/html/rfc7636) extension in
order to protect against other applications on the system intercepting the
incoming request to the redirection endpoint. We strongly recommend that you
select an OAuth server implementation that also implements this extension and
verifies the code challenge sent to the token endpoint.
Terraform CLI does not support OAuth refresh tokens or token expiration. If your
server issues time-limited tokens, Terraform CLI will simply begin receiving
authorization errors once the token expires, after which the user can run
`terraform login` again to obtain a new token.
-> **Note:** As a special case, Terraform can use a
[Resource Owner Password Credentials Grant](https://tools.ietf.org/html/rfc6749#section-4.3)
only when interacting with `app.terraform.io` ([Terraform Cloud](/docs/cloud/index.html)),
under the recommendation in the OAuth specification to use this grant type only
when the client and server are closely related. The `password` grant type is
not supported for any other hostname and will be ignored.

View File

@@ -83,8 +83,9 @@ version 1 of the module registry protocol:
## Supported Services
At present, only one service identifier is in use:
At present, the following service identifiers are in use:
* `login.v1`: [login protocol version 1](/docs/commands/login.html#protocol-v1)
* `modules.v1`: [module registry API version 1](/docs/registry/api.html)
## Authentication