2020-02-04 17:30:40 +01:00
|
|
|
---
|
|
|
|
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.
|
|
|
|
|
2020-09-15 15:00:44 +02:00
|
|
|
If the credentials helper definitively has no credentials for the given host,
|
|
|
|
then it must print an empty JSON object to stdout and exit with status zero.
|
|
|
|
|
|
|
|
If the credentials helper is unable to provide the requested credentials for
|
|
|
|
any other 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.
|
2020-02-04 17:30:40 +01:00
|
|
|
|
|
|
|
## `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.
|