main: configure credentials from the CLI config file
This commit is contained in:
parent
47c45788bc
commit
35a058fb3d
47
commands.go
47
commands.go
|
@ -4,10 +4,11 @@ import (
|
|||
"os"
|
||||
"os/signal"
|
||||
|
||||
"github.com/hashicorp/terraform/command"
|
||||
pluginDiscovery "github.com/hashicorp/terraform/plugin/discovery"
|
||||
"github.com/hashicorp/terraform/svchost"
|
||||
"github.com/hashicorp/terraform/svchost/auth"
|
||||
"github.com/hashicorp/terraform/svchost/disco"
|
||||
|
||||
"github.com/hashicorp/terraform/command"
|
||||
"github.com/mitchellh/cli"
|
||||
)
|
||||
|
||||
|
@ -34,7 +35,7 @@ func initCommands(config *Config) {
|
|||
inAutomation = true
|
||||
}
|
||||
|
||||
credsSrc := auth.NoCredentials // TODO: Actually expose credentials here
|
||||
credsSrc := credentialsSource(config)
|
||||
services := disco.NewDisco()
|
||||
services.SetCredentialsSource(credsSrc)
|
||||
|
||||
|
@ -342,3 +343,43 @@ func makeShutdownCh() <-chan struct{} {
|
|||
|
||||
return resultCh
|
||||
}
|
||||
|
||||
func credentialsSource(config *Config) auth.CredentialsSource {
|
||||
creds := auth.NoCredentials
|
||||
if len(config.Credentials) > 0 {
|
||||
staticTable := map[svchost.Hostname]map[string]interface{}{}
|
||||
for userHost, creds := range config.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
|
||||
}
|
||||
staticTable[host] = creds
|
||||
}
|
||||
creds = auth.StaticCredentialsSource(staticTable)
|
||||
}
|
||||
|
||||
for helperType, helperConfig := range config.CredentialsHelpers {
|
||||
available := pluginDiscovery.FindPlugins("credentials", globalPluginDirs())
|
||||
available = available.WithName(helperType)
|
||||
if available.Count() == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
selected := available.Newest()
|
||||
|
||||
helperSource := auth.HelperProgramCredentialsSource(selected.Path, helperConfig.Args...)
|
||||
creds = auth.Credentials{
|
||||
creds,
|
||||
auth.CachingCredentialsSource(helperSource), // cached because external operation may be slow/expensive
|
||||
}
|
||||
|
||||
// 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 creds
|
||||
}
|
||||
|
|
|
@ -27,6 +27,15 @@ type Config struct {
|
|||
// If set, enables local caching of plugins in this directory to
|
||||
// avoid repeatedly re-downloading over the Internet.
|
||||
PluginCacheDir string `hcl:"plugin_cache_dir"`
|
||||
|
||||
Credentials map[string]map[string]interface{} `hcl:"credentials"`
|
||||
CredentialsHelpers map[string]*ConfigCredentialsHelper `hcl:"credentials_helper"`
|
||||
}
|
||||
|
||||
// ConfigCredentialsHelper is the structure of the "credentials_helper"
|
||||
// nested block within the CLI configuration.
|
||||
type ConfigCredentialsHelper struct {
|
||||
Args []string `hcl:"args"`
|
||||
}
|
||||
|
||||
// BuiltinConfig is the built-in defaults for the configuration. These
|
||||
|
|
|
@ -5,6 +5,8 @@ import (
|
|||
"path/filepath"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
)
|
||||
|
||||
// This is the directory where our test fixtures are.
|
||||
|
@ -52,6 +54,34 @@ func TestLoadConfig_env(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestLoadConfig_credentials(t *testing.T) {
|
||||
got, err := LoadConfig(filepath.Join(fixtureDir, "credentials"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
want := &Config{
|
||||
Credentials: map[string]map[string]interface{}{
|
||||
"example.com": map[string]interface{}{
|
||||
"token": "foo the bar baz",
|
||||
},
|
||||
"example.net": map[string]interface{}{
|
||||
"username": "foo",
|
||||
"password": "baz",
|
||||
},
|
||||
},
|
||||
CredentialsHelpers: map[string]*ConfigCredentialsHelper{
|
||||
"foo": &ConfigCredentialsHelper{
|
||||
Args: []string{"bar", "baz"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("wrong result\ngot: %swant: %s", spew.Sdump(got), spew.Sdump(want))
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfig_Merge(t *testing.T) {
|
||||
c1 := &Config{
|
||||
Providers: map[string]string{
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
|
||||
credentials "example.com" {
|
||||
token = "foo the bar baz"
|
||||
}
|
||||
|
||||
credentials "example.net" {
|
||||
# Username and password are not currently supported, but we want to tolerate
|
||||
# unknown keys in case future versions add new keys when both old and new
|
||||
# versions of Terraform are installed on a system, sharing the same
|
||||
# CLI config.
|
||||
username = "foo"
|
||||
password = "baz"
|
||||
}
|
||||
|
||||
credentials_helper "foo" {
|
||||
args = ["bar", "baz"]
|
||||
}
|
Loading…
Reference in New Issue