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"
|
||||||
"os/signal"
|
"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/auth"
|
||||||
"github.com/hashicorp/terraform/svchost/disco"
|
"github.com/hashicorp/terraform/svchost/disco"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/command"
|
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -34,7 +35,7 @@ func initCommands(config *Config) {
|
||||||
inAutomation = true
|
inAutomation = true
|
||||||
}
|
}
|
||||||
|
|
||||||
credsSrc := auth.NoCredentials // TODO: Actually expose credentials here
|
credsSrc := credentialsSource(config)
|
||||||
services := disco.NewDisco()
|
services := disco.NewDisco()
|
||||||
services.SetCredentialsSource(credsSrc)
|
services.SetCredentialsSource(credsSrc)
|
||||||
|
|
||||||
|
@ -342,3 +343,43 @@ func makeShutdownCh() <-chan struct{} {
|
||||||
|
|
||||||
return resultCh
|
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
|
// If set, enables local caching of plugins in this directory to
|
||||||
// avoid repeatedly re-downloading over the Internet.
|
// avoid repeatedly re-downloading over the Internet.
|
||||||
PluginCacheDir string `hcl:"plugin_cache_dir"`
|
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
|
// BuiltinConfig is the built-in defaults for the configuration. These
|
||||||
|
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
)
|
)
|
||||||
|
|
||||||
// This is the directory where our test fixtures are.
|
// 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) {
|
func TestConfig_Merge(t *testing.T) {
|
||||||
c1 := &Config{
|
c1 := &Config{
|
||||||
Providers: map[string]string{
|
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