mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
feat(credentials): allow hyphens to be encoded as __ in variables
Hyphen characters are allowed in environment variable names, but are not valid POSIX variable names. Usually, it's still possible to set variable names with hyphens using utilities like env or docker. But, as a fallback, host names may encode their hyphens as double underscores in the variable name. For the example "café.fr", the variable name "TF_TOKEN_xn____caf__dma_fr" or "TF_TOKEN_xn--caf-dma_fr" may be used.
This commit is contained in:
parent
dff6a8431c
commit
fda05f3d44
@ -115,12 +115,19 @@ func (c *Config) credentialsSource(helperType string, helper svcauth.Credentials
|
|||||||
}
|
}
|
||||||
|
|
||||||
// hostCredentialsFromEnv returns a token credential by searching for a hostname-specific
|
// hostCredentialsFromEnv returns a token credential by searching for a hostname-specific
|
||||||
// environment variable. If the variable based on the hostname is not defined, nil is returned.
|
// environment variable. The host parameter is expected to be in the "comparison" form,
|
||||||
// Variable names must have dot characters translated to underscores, which are normally not
|
// for example, hostnames containing non-ASCII characters like "café.fr"
|
||||||
// allowed in DNS names. For example, token credentials for app.terraform.io should be set
|
// should be expressed as "xn--caf-dma.fr". If the variable based on the hostname is not
|
||||||
// in the variable named TF_TOKEN_app_terraform_io. Internationalized hostnames containing
|
// defined, nil is returned. Variable names must have dot characters translated to
|
||||||
// non-ASCII characters expressed as variable names are expected to be in the "comparison" form,
|
// underscores, which are not allowed in DNS names. For example, token credentials
|
||||||
// such as "TF_TOKEN_xn--caf-dma_fr" for the hostname "café.fr"
|
// for app.terraform.io should be set in the variable named TF_TOKEN_app_terraform_io.
|
||||||
|
//
|
||||||
|
// Hyphen characters are allowed in environment variable names, but are not valid POSIX
|
||||||
|
// variable names. Usually, it's still possible to set variable names with hyphens using
|
||||||
|
// utilities like env or docker. But, as a fallback, host names may encode their
|
||||||
|
// hyphens as double underscores in the variable name. For the example "café.fr",
|
||||||
|
// the variable name "TF_TOKEN_xn____caf__dma_fr" or "TF_TOKEN_xn--caf-dma_fr"
|
||||||
|
// may be used.
|
||||||
func hostCredentialsFromEnv(host svchost.Hostname) svcauth.HostCredentials {
|
func hostCredentialsFromEnv(host svchost.Hostname) svcauth.HostCredentials {
|
||||||
if len(host) == 0 {
|
if len(host) == 0 {
|
||||||
return nil
|
return nil
|
||||||
@ -128,12 +135,23 @@ func hostCredentialsFromEnv(host svchost.Hostname) svcauth.HostCredentials {
|
|||||||
|
|
||||||
// Convert dots to underscores when looking for environment configuration for a specific host.
|
// Convert dots to underscores when looking for environment configuration for a specific host.
|
||||||
// DNS names do not allow underscore characters so this is unambiguous.
|
// DNS names do not allow underscore characters so this is unambiguous.
|
||||||
variableName := fmt.Sprintf("TF_TOKEN_%s", strings.ReplaceAll(host.String(), ".", "_"))
|
translated := strings.ReplaceAll(host.String(), ".", "_")
|
||||||
|
|
||||||
if token, ok := os.LookupEnv(variableName); ok {
|
if token, ok := os.LookupEnv(fmt.Sprintf("TF_TOKEN_%s", translated)); ok {
|
||||||
return svcauth.HostCredentialsToken(token)
|
return svcauth.HostCredentialsToken(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if strings.ContainsRune(translated, '-') {
|
||||||
|
// This host name contains a hyphen. Replace hyphens with double underscores as a fallback
|
||||||
|
// (see godoc above for details)
|
||||||
|
translated = strings.ReplaceAll(host.String(), "-", "__")
|
||||||
|
translated = strings.ReplaceAll(translated, ".", "_")
|
||||||
|
|
||||||
|
if token, ok := os.LookupEnv(fmt.Sprintf("TF_TOKEN_%s", translated)); ok {
|
||||||
|
return svcauth.HostCredentialsToken(token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -130,6 +130,31 @@ func TestCredentialsForHost(t *testing.T) {
|
|||||||
t.Errorf("wrong result\ngot: %s\nwant: %s", got, expectedToken)
|
t.Errorf("wrong result\ngot: %s\nwant: %s", got, expectedToken)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("hyphens can be encoded as double underscores", func(t *testing.T) {
|
||||||
|
envName := "TF_TOKEN_env_xn____caf__dma_fr"
|
||||||
|
expectedToken := "configured-by-fallback"
|
||||||
|
t.Cleanup(func() {
|
||||||
|
os.Unsetenv(envName)
|
||||||
|
})
|
||||||
|
|
||||||
|
os.Setenv(envName, expectedToken)
|
||||||
|
|
||||||
|
hostname, _ := svchost.ForComparison("env.café.fr")
|
||||||
|
creds, err := credSrc.ForHost(hostname)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if creds == nil {
|
||||||
|
t.Fatal("no credentials found")
|
||||||
|
}
|
||||||
|
|
||||||
|
if got := creds.Token(); got != expectedToken {
|
||||||
|
t.Errorf("wrong result\ngot: %s\nwant: %s", got, expectedToken)
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCredentialsStoreForget(t *testing.T) {
|
func TestCredentialsStoreForget(t *testing.T) {
|
||||||
|
@ -118,12 +118,22 @@ Terraform Cloud responds to API calls at both its current hostname
|
|||||||
### Environment Variable Credentials
|
### Environment Variable Credentials
|
||||||
|
|
||||||
If you would prefer not to store your API tokens directly in the CLI
|
If you would prefer not to store your API tokens directly in the CLI
|
||||||
configuration, you may use a host-specific environment variable. Environment variable names should be the prefix `TF_TOKEN_` added to the domain name. For example,
|
configuration, you may use a host-specific environment variable. Environment variable names should
|
||||||
the value of a variable named `TF_TOKEN_app_terraform_io` will be used as a bearer authorization token when the CLI makes service requests to the hostname "app.terraform.io".
|
have the prefix `TF_TOKEN_` added to the domain name, with periods encoded as underscores.
|
||||||
|
For example, the value of a variable named `TF_TOKEN_app_terraform_io` will be used as a
|
||||||
|
bearer authorization token when the CLI makes service requests to the hostname "app.terraform.io".
|
||||||
|
|
||||||
Internationalized domain names should be converted to their [punycode equivalent](https://www.charset.org/punycode)
|
Domain names containing non-ASCII characters should be converted to
|
||||||
|
their [punycode equivalent](https://www.charset.org/punycode)
|
||||||
with an ACE prefix when used as a variable name. For example, token credentials
|
with an ACE prefix when used as a variable name. For example, token credentials
|
||||||
for 例えば.com should be set in a variable called `TF_TOKEN_xn--r8j3dr99h_com`.
|
for 例えば.com must be set in a variable called `TF_TOKEN_xn--r8j3dr99h_com`.
|
||||||
|
|
||||||
|
Hyphens are allowed within variable names by certain tools, such as the `env` utility,
|
||||||
|
but are not valid POSIX variable names. Therefore, it can be tricky to
|
||||||
|
set them with interactive tools such as bash or zsh so you may encode
|
||||||
|
hyphens as double underscores. For example, a token for the domain name "café.fr" can
|
||||||
|
be set by either `TF_TOKEN_xn--caf-dma_fr` or `TF_TOKEN_xn____caf__dma_fr` if that is more
|
||||||
|
convenient. If both are defined, the variable containing hyphens is preferred.
|
||||||
|
|
||||||
### Credentials Helpers
|
### Credentials Helpers
|
||||||
|
|
||||||
@ -153,6 +163,16 @@ To learn how to write and install your own credentials helpers to integrate
|
|||||||
with existing in-house credentials management systems, see
|
with existing in-house credentials management systems, see
|
||||||
[the guide to Credentials Helper internals](/internals/credentials-helpers).
|
[the guide to Credentials Helper internals](/internals/credentials-helpers).
|
||||||
|
|
||||||
|
### Credentials Source Priority Order
|
||||||
|
|
||||||
|
Credentials found in an environment variable for a particular service host
|
||||||
|
as described above will be preferred over those in CLI config as set by `terraform login`.
|
||||||
|
If neither are set, any configured credentials helper will be consulted.
|
||||||
|
|
||||||
|
~> **Note:** For users of [terraform-credentials-helper](https://github.com/apparentlymart/terraform-credentials-env), this priority has been effectively reversed following the
|
||||||
|
release of Terraform 1.2. Previously, credentials found within CLI config or set by
|
||||||
|
`terraform login` were preferred to `TF_TOKEN_*` variables.
|
||||||
|
|
||||||
## Provider Installation
|
## Provider Installation
|
||||||
|
|
||||||
The default way to install provider plugins is from a provider registry. The
|
The default way to install provider plugins is from a provider registry. The
|
||||||
|
Loading…
Reference in New Issue
Block a user