Skip to content

allow finding credentials for subdomain of terraform registry #4445

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions tf/cliconfig/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,22 @@ func (s *CredentialsSource) ForHost(host svchost.Hostname) svcauth.HostCredentia
return nil
}

func (s *CredentialsSource) ForHostSuffix(host svchost.Hostname) svcauth.HostCredentials {
// The first order of precedence for credentials is a host-specific environment variable
if envCreds := hostSuffixCredentialsFromEnv(host); envCreds != nil {
return envCreds
}

// Then, any credentials block with the suffix present in the CLI config
for key, token := range s.configured {
if strings.HasSuffix(host.String(), key.String()) {
return svcauth.HostCredentialsToken(token)
}
}

return nil
}

// hostCredentialsFromEnv returns a token credential by searching for a hostname-specific environment variable. The host parameter is expected to be in the "comparison" form, for example, hostnames containing non-ASCII characters like "café.fr" should be expressed as "xn--caf-dma.fr". If the variable based on the hostname is not defined, nil is returned.
//
// Hyphen and period characters are allowed in environment variable names, but are not valid POSIX variable names. However, it's still possible to set variable names with these characters using utilities like env or docker. Variable names may have periods translated to underscores and hyphens translated to double underscores in the variable name. For the example "café.fr", you may use the variable names "TF_TOKEN_xn____caf__dma_fr", "TF_TOKEN_xn--caf-dma_fr", or "TF_TOKEN_xn--caf-dma.fr"
Expand All @@ -39,6 +55,15 @@ func hostCredentialsFromEnv(host svchost.Hostname) svcauth.HostCredentials {
return svcauth.HostCredentialsToken(token)
}

func hostSuffixCredentialsFromEnv(host svchost.Hostname) svcauth.HostCredentials {
for key, token := range collectCredentialsFromEnv() {
if strings.HasSuffix(host.String(), key.String()) {
return svcauth.HostCredentialsToken(token)
}
}
return nil
}

func collectCredentialsFromEnv() map[svchost.Hostname]string {
const prefix = "TF_TOKEN_"

Expand Down
6 changes: 5 additions & 1 deletion tf/getter.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,10 +334,14 @@ func applyHostToken(req *http.Request) (*http.Request, error) {
return nil, err
}

// first try to find the exact hostname for the token
// then try to match the host suffix for the token
// finally fall back to the TG_TF_REGISTRY_TOKEN
if creds := cliCfg.CredentialsSource().ForHost(svchost.Hostname(req.URL.Hostname())); creds != nil {
creds.PrepareRequest(req)
} else if creds := cliCfg.CredentialsSource().ForHostSuffix(svchost.Hostname(req.URL.Hostname())); creds != nil {
creds.PrepareRequest(req)
} else {
// fall back to the TG_TF_REGISTRY_TOKEN
authToken := os.Getenv(authTokenEnvName)
if authToken != "" {
req.Header.Add("Authorization", "Bearer "+authToken)
Expand Down