// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package cliconfig

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"

	"github.com/zclconf/go-cty/cty"
	ctyjson "github.com/zclconf/go-cty/cty/json"

	svchost "github.com/hashicorp/terraform-svchost"
	svcauth "github.com/hashicorp/terraform-svchost/auth"
	"github.com/hashicorp/terraform/internal/configs/hcl2shim"
	pluginDiscovery "github.com/hashicorp/terraform/internal/plugin/discovery"
	"github.com/hashicorp/terraform/internal/replacefile"
)

// credentialsConfigFile returns the path for the special configuration file
// that the credentials source will use when asked to save or forget credentials
// and when a "credentials helper" program is not active.
func credentialsConfigFile() (string, error) {
	configDir, err := ConfigDir()
	if err != nil {
		return "", err
	}
	return filepath.Join(configDir, "credentials.tfrc.json"), nil
}

// CredentialsSource creates and returns a service credentials source whose
// behavior depends on which "credentials" and "credentials_helper" blocks,
// if any, are present in the receiving config.
func (c *Config) CredentialsSource(helperPlugins pluginDiscovery.PluginMetaSet) (*CredentialsSource, error) {
	credentialsFilePath, err := credentialsConfigFile()
	if err != nil {
		// If we managed to load a Config object at all then we would already
		// have located this file, so this error is very unlikely.
		return nil, fmt.Errorf("can't locate credentials file: %s", err)
	}

	var helper svcauth.CredentialsSource
	var helperType string
	for givenType, givenConfig := range c.CredentialsHelpers {
		available := helperPlugins.WithName(givenType)
		if available.Count() == 0 {
			log.Printf("[ERROR] Unable to find credentials helper %q; ignoring", givenType)
			break
		}

		selected := available.Newest()

		helperSource := svcauth.HelperProgramCredentialsSource(selected.Path, givenConfig.Args...)
		helper = svcauth.CachingCredentialsSource(helperSource) // cached because external operation may be slow/expensive
		helperType = givenType

		// There should only be zero or one "credentials_helper" blocks. We
		// assume that the config was validated earlier and so we don't check
		// for extras here.
		break
	}

	return c.credentialsSource(helperType, helper, credentialsFilePath), nil
}

// EmptyCredentialsSourceForTests constructs a CredentialsSource with
// no credentials pre-loaded and which writes new credentials to a file
// at the given path.
//
// As the name suggests, this function is here only for testing and should not
// be used in normal application code.
func EmptyCredentialsSourceForTests(credentialsFilePath string) *CredentialsSource {
	cfg := &Config{}
	return cfg.credentialsSource("", nil, credentialsFilePath)
}

// credentialsSource is an internal factory for the credentials source which
// allows overriding the credentials file path, which allows setting it to
// a temporary file location when testing.
func (c *Config) credentialsSource(helperType string, helper svcauth.CredentialsSource, credentialsFilePath string) *CredentialsSource {
	configured := map[svchost.Hostname]cty.Value{}
	for userHost, creds := range c.Credentials {
		host, err := svchost.ForComparison(userHost)
		if err != nil {
			// We expect the config was already validated by the time we get
			// here, so we'll just ignore invalid hostnames.
			continue
		}

		// For now our CLI config continues to use HCL 1.0, so we'll shim it
		// over to HCL 2.0 types. In future we will hopefully migrate it to
		// HCL 2.0 instead, and so it'll be a cty.Value already.
		credsV := hcl2shim.HCL2ValueFromConfigValue(creds)
		configured[host] = credsV
	}

	writableLocal := readHostsInCredentialsFile(credentialsFilePath)
	unwritableLocal := map[svchost.Hostname]cty.Value{}
	for host, v := range configured {
		if _, exists := writableLocal[host]; !exists {
			unwritableLocal[host] = v
		}
	}

	return &CredentialsSource{
		configured:          configured,
		unwritable:          unwritableLocal,
		credentialsFilePath: credentialsFilePath,
		helper:              helper,
		helperType:          helperType,
	}
}

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

	ret := make(map[svchost.Hostname]string)
	for _, ev := range os.Environ() {
		eqIdx := strings.Index(ev, "=")
		if eqIdx < 0 {
			continue
		}
		name := ev[:eqIdx]
		value := ev[eqIdx+1:]
		if !strings.HasPrefix(name, prefix) {
			continue
		}
		rawHost := name[len(prefix):]

		// We accept double underscores in place of hyphens because hyphens are not valid
		// identifiers in most shells and are therefore hard to set.
		// This is unambiguous with replacing single underscores below because
		// hyphens are not allowed at the beginning or end of a label and therefore
		// odd numbers of underscores will not appear together in a valid variable name.
		rawHost = strings.ReplaceAll(rawHost, "__", "-")

		// We accept underscores in place of dots because dots are not valid
		// identifiers in most shells and are therefore hard to set.
		// Underscores are not valid in hostnames, so this is unambiguous for
		// valid hostnames.
		rawHost = strings.ReplaceAll(rawHost, "_", ".")

		// Because environment variables are often set indirectly by OS
		// libraries that might interfere with how they are encoded, we'll
		// be tolerant of them being given either directly as UTF-8 IDNs
		// or in Punycode form, normalizing to Punycode form here because
		// that is what the Terraform credentials helper protocol will
		// use in its requests.
		//
		// Using ForDisplay first here makes this more liberal than Terraform
		// itself would usually be in that it will tolerate pre-punycoded
		// hostnames that Terraform normally rejects in other contexts in order
		// to ensure stored hostnames are human-readable.
		dispHost := svchost.ForDisplay(rawHost)
		hostname, err := svchost.ForComparison(dispHost)
		if err != nil {
			// Ignore invalid hostnames
			continue
		}

		ret[hostname] = value
	}

	return ret
}

// 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"
func hostCredentialsFromEnv(host svchost.Hostname) svcauth.HostCredentials {
	token, ok := collectCredentialsFromEnv()[host]
	if !ok {
		return nil
	}
	return svcauth.HostCredentialsToken(token)
}

// CredentialsSource is an implementation of svcauth.CredentialsSource
// that can read and write the CLI configuration, and possibly also delegate
// to a credentials helper when configured.
type CredentialsSource struct {
	// configured describes the credentials explicitly configured in the CLI
	// config via "credentials" blocks. This map will also change to reflect
	// any writes to the special credentials.tfrc.json file.
	configured map[svchost.Hostname]cty.Value

	// unwritable describes any credentials explicitly configured in the
	// CLI config in any file other than credentials.tfrc.json. We cannot update
	// these automatically because only credentials.tfrc.json is subject to
	// editing by this credentials source.
	unwritable map[svchost.Hostname]cty.Value

	// credentialsFilePath is the full path to the credentials.tfrc.json file
	// that we'll update if any changes to credentials are requested and if
	// a credentials helper isn't available to use instead.
	//
	// (This is a field here rather than just calling credentialsConfigFile
	// directly just so that we can use temporary file location instead during
	// testing.)
	credentialsFilePath string

	// helper is the credentials source representing the configured credentials
	// helper, if any. When this is non-nil, it will be consulted for any
	// hostnames not explicitly represented in "configured". Any writes to
	// the credentials store will also be sent to a configured helper instead
	// of the credentials.tfrc.json file.
	helper svcauth.CredentialsSource

	// helperType is the name of the type of credentials helper that is
	// referenced in "helper", or the empty string if "helper" is nil.
	helperType string
}

// Assertion that credentialsSource implements CredentialsSource
var _ svcauth.CredentialsSource = (*CredentialsSource)(nil)

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

	// Then, any credentials block present in the CLI config
	v, ok := s.configured[host]
	if ok {
		return svcauth.HostCredentialsFromObject(v), nil
	}

	// And finally, the credentials helper
	if s.helper != nil {
		return s.helper.ForHost(host)
	}

	return nil, nil
}

func (s *CredentialsSource) StoreForHost(host svchost.Hostname, credentials svcauth.HostCredentialsWritable) error {
	return s.updateHostCredentials(host, credentials)
}

func (s *CredentialsSource) ForgetForHost(host svchost.Hostname) error {
	return s.updateHostCredentials(host, nil)
}

// HostCredentialsLocation returns a value indicating what type of storage is
// currently used for the credentials for the given hostname.
//
// The current location of credentials determines whether updates are possible
// at all and, if they are, where any updates will be written.
func (s *CredentialsSource) HostCredentialsLocation(host svchost.Hostname) CredentialsLocation {
	if _, unwritable := s.unwritable[host]; unwritable {
		return CredentialsInOtherFile
	}
	if _, exists := s.configured[host]; exists {
		return CredentialsInPrimaryFile
	}
	if s.helper != nil {
		return CredentialsViaHelper
	}
	return CredentialsNotAvailable
}

// CredentialsFilePath returns the full path to the local credentials
// configuration file, so that a caller can mention this path in order to
// be transparent about where credentials will be stored.
//
// This file will be used for writes only if HostCredentialsLocation for the
// relevant host returns CredentialsInPrimaryFile or CredentialsNotAvailable.
//
// The credentials file path is found relative to the current user's home
// directory, so this function will return an error in the unlikely event that
// we cannot determine a suitable home directory to resolve relative to.
func (s *CredentialsSource) CredentialsFilePath() (string, error) {
	return s.credentialsFilePath, nil
}

// CredentialsHelperType returns the name of the configured credentials helper
// type, or an empty string if no credentials helper is configured.
func (s *CredentialsSource) CredentialsHelperType() string {
	return s.helperType
}

func (s *CredentialsSource) updateHostCredentials(host svchost.Hostname, new svcauth.HostCredentialsWritable) error {
	switch loc := s.HostCredentialsLocation(host); loc {
	case CredentialsInOtherFile:
		return ErrUnwritableHostCredentials(host)
	case CredentialsInPrimaryFile, CredentialsNotAvailable:
		// If the host already has credentials stored locally then we'll update
		// them locally too, even if there's a credentials helper configured,
		// because the user might be intentionally retaining this particular
		// host locally for some reason, e.g. if the credentials helper is
		// talking to some shared remote service like HashiCorp Vault.
		return s.updateLocalHostCredentials(host, new)
	case CredentialsViaHelper:
		// Delegate entirely to the helper, then.
		if new == nil {
			return s.helper.ForgetForHost(host)
		}
		return s.helper.StoreForHost(host, new)
	default:
		// Should never happen because the above cases are exhaustive
		return fmt.Errorf("invalid credentials location %#v", loc)
	}
}

func (s *CredentialsSource) updateLocalHostCredentials(host svchost.Hostname, new svcauth.HostCredentialsWritable) error {
	// This function updates the local credentials file in particular,
	// regardless of whether a credentials helper is active. It should be
	// called only indirectly via updateHostCredentials.

	filename, err := s.CredentialsFilePath()
	if err != nil {
		return fmt.Errorf("unable to determine credentials file path: %s", err)
	}

	oldSrc, err := ioutil.ReadFile(filename)
	if err != nil && !os.IsNotExist(err) {
		return fmt.Errorf("cannot read %s: %s", filename, err)
	}

	var raw map[string]interface{}

	if len(oldSrc) > 0 {
		// When decoding we use a custom decoder so we can decode any numbers as
		// json.Number and thus avoid losing any accuracy in our round-trip.
		dec := json.NewDecoder(bytes.NewReader(oldSrc))
		dec.UseNumber()
		err = dec.Decode(&raw)
		if err != nil {
			return fmt.Errorf("cannot read %s: %s", filename, err)
		}
	} else {
		raw = make(map[string]interface{})
	}

	rawCredsI, ok := raw["credentials"]
	if !ok {
		rawCredsI = make(map[string]interface{})
		raw["credentials"] = rawCredsI
	}
	rawCredsMap, ok := rawCredsI.(map[string]interface{})
	if !ok {
		return fmt.Errorf("credentials file %s has invalid value for \"credentials\" property: must be a JSON object", filename)
	}

	// We use display-oriented hostnames in our file to mimick how a human user
	// would write it, so we need to search for and remove any key that
	// normalizes to our target hostname so we won't generate something invalid
	// when the existing entry is slightly different.
	for givenHost := range rawCredsMap {
		canonHost, err := svchost.ForComparison(givenHost)
		if err == nil && canonHost == host {
			delete(rawCredsMap, givenHost)
		}
	}

	// If we have a new object to store we'll write it in now. If the previous
	// object had the hostname written in a different way then this will
	// appear to change it into our canonical display form, with all the
	// letters in lowercase and other transforms from the Internationalized
	// Domain Names specification.
	if new != nil {
		toStore := new.ToStore()
		rawCredsMap[host.ForDisplay()] = ctyjson.SimpleJSONValue{
			Value: toStore,
		}
	}

	newSrc, err := json.MarshalIndent(raw, "", "  ")
	if err != nil {
		return fmt.Errorf("cannot serialize updated credentials file: %s", err)
	}

	// Now we'll write our new content over the top of the existing file.
	// Because we updated the data structure surgically here we should not
	// have disturbed the meaning of any other content in the file, but it
	// might have a different JSON layout than before.
	// We'll create a new file with a different name first and then rename
	// it over the old file in order to make the change as atomically as
	// the underlying OS/filesystem will allow.
	{
		dir, file := filepath.Split(filename)
		f, err := ioutil.TempFile(dir, file)
		if err != nil {
			return fmt.Errorf("cannot create temporary file to update credentials: %s", err)
		}
		tmpName := f.Name()
		moved := false
		defer func(f *os.File, name string) {
			// Remove the temporary file if it hasn't been moved yet. We're
			// ignoring errors here because there's nothing we can do about
			// them anyway.
			if !moved {
				os.Remove(name)
			}
		}(f, tmpName)

		// Write the credentials to the temporary file, then immediately close
		// it, whether or not the write succeeds.
		_, err = f.Write(newSrc)
		f.Close()
		if err != nil {
			return fmt.Errorf("cannot write to temporary file %s: %s", tmpName, err)
		}

		// Temporary file now replaces the original file, as atomically as
		// possible. (At the very least, we should not end up with a file
		// containing only a partial JSON object.)
		err = replacefile.AtomicRename(tmpName, filename)
		if err != nil {
			return fmt.Errorf("failed to replace %s with temporary file %s: %s", filename, tmpName, err)
		}

		// Credentials file should be readable only by its owner. (This may
		// not be effective on all platforms, but should at least work on
		// Unix-like targets and should be harmless elsewhere.)
		if err := os.Chmod(filename, 0600); err != nil {
			return fmt.Errorf("cannot set mode for credentials file %s: %s", filename, err)
		}

		moved = true
	}

	if new != nil {
		s.configured[host] = new.ToStore()
	} else {
		delete(s.configured, host)
	}

	return nil
}

// readHostsInCredentialsFile discovers which hosts have credentials configured
// in the credentials file specifically, as opposed to in any other CLI
// config file.
//
// If the credentials file isn't present or is unreadable for any reason then
// this returns an empty set, reflecting that effectively no credentials are
// stored there.
func readHostsInCredentialsFile(filename string) map[svchost.Hostname]struct{} {
	src, err := ioutil.ReadFile(filename)
	if err != nil {
		return nil
	}

	var raw map[string]interface{}
	err = json.Unmarshal(src, &raw)
	if err != nil {
		return nil
	}

	rawCredsI, ok := raw["credentials"]
	if !ok {
		return nil
	}
	rawCredsMap, ok := rawCredsI.(map[string]interface{})
	if !ok {
		return nil
	}

	ret := make(map[svchost.Hostname]struct{})
	for givenHost := range rawCredsMap {
		host, err := svchost.ForComparison(givenHost)
		if err != nil {
			// We expect the config was already validated by the time we get
			// here, so we'll just ignore invalid hostnames.
			continue
		}
		ret[host] = struct{}{}
	}
	return ret
}

// ErrUnwritableHostCredentials is an error type that is returned when a caller
// tries to write credentials for a host that has existing credentials configured
// in a file that we cannot automatically update.
type ErrUnwritableHostCredentials svchost.Hostname

func (err ErrUnwritableHostCredentials) Error() string {
	return fmt.Sprintf("cannot change credentials for %s: existing manually-configured credentials in a CLI config file", svchost.Hostname(err).ForDisplay())
}

// Hostname returns the host that could not be written.
func (err ErrUnwritableHostCredentials) Hostname() svchost.Hostname {
	return svchost.Hostname(err)
}

// CredentialsLocation describes a type of storage used for the credentials
// for a particular hostname.
type CredentialsLocation rune

const (
	// CredentialsNotAvailable means that we know that there are no credential
	// available for the host.
	//
	// Note that CredentialsViaHelper might also lead to no credentials being
	// available, depending on how the helper answers when we request credentials
	// from it.
	CredentialsNotAvailable CredentialsLocation = 0

	// CredentialsInPrimaryFile means that there is already a credentials object
	// for the host in the credentials.tfrc.json file.
	CredentialsInPrimaryFile CredentialsLocation = 'P'

	// CredentialsInOtherFile means that there is already a credentials object
	// for the host in a CLI config file other than credentials.tfrc.json.
	CredentialsInOtherFile CredentialsLocation = 'O'

	// CredentialsViaHelper indicates that no statically-configured credentials
	// are available for the host but a helper program is available that may
	// or may not have credentials for the host.
	CredentialsViaHelper CredentialsLocation = 'H'
)
