Merge pull request #643 from pulumi/LateDecrypt
Decrypt configuration nearer to its use.
This commit is contained in:
commit
94645c313a
|
@ -177,8 +177,13 @@ func (b *localBackend) GetLogs(stackName tokens.QName, query operations.LogQuery
|
||||||
contract.Assert(snap != nil)
|
contract.Assert(snap != nil)
|
||||||
contract.Assert(target != nil)
|
contract.Assert(target != nil)
|
||||||
|
|
||||||
|
config, err := target.Config.Decrypt(target.Decrypter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
components := operations.NewResourceTree(snap.Resources)
|
components := operations.NewResourceTree(snap.Resources)
|
||||||
ops := components.OperationsProvider(target.Config)
|
ops := components.OperationsProvider(config)
|
||||||
logs, err := ops.GetLogs(query)
|
logs, err := ops.GetLogs(query)
|
||||||
if logs == nil {
|
if logs == nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
@ -39,17 +39,7 @@ func (p localStackProvider) GetTarget(name tokens.QName) (*deploy.Target, error)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
decryptedConfig := make(map[tokens.ModuleMember]string)
|
return &deploy.Target{Name: name, Config: config, Decrypter: p.decrypter}, nil
|
||||||
|
|
||||||
for k, v := range config {
|
|
||||||
decrypted, err := v.Value(p.decrypter)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "could not decrypt configuration value")
|
|
||||||
}
|
|
||||||
decryptedConfig[k] = decrypted
|
|
||||||
}
|
|
||||||
|
|
||||||
return &deploy.Target{Name: name, Config: decryptedConfig}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p localStackProvider) GetSnapshot(name tokens.QName) (*deploy.Snapshot, error) {
|
func (p localStackProvider) GetSnapshot(name tokens.QName) (*deploy.Snapshot, error) {
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/pulumi/pulumi/pkg/diag/colors"
|
"github.com/pulumi/pulumi/pkg/diag/colors"
|
||||||
"github.com/pulumi/pulumi/pkg/resource"
|
"github.com/pulumi/pulumi/pkg/resource"
|
||||||
|
"github.com/pulumi/pulumi/pkg/resource/config"
|
||||||
"github.com/pulumi/pulumi/pkg/resource/deploy"
|
"github.com/pulumi/pulumi/pkg/resource/deploy"
|
||||||
"github.com/pulumi/pulumi/pkg/resource/plugin"
|
"github.com/pulumi/pulumi/pkg/resource/plugin"
|
||||||
"github.com/pulumi/pulumi/pkg/tokens"
|
"github.com/pulumi/pulumi/pkg/tokens"
|
||||||
|
@ -185,16 +186,18 @@ func printPrelude(b *bytes.Buffer, result *planResult, planning bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func printConfig(b *bytes.Buffer, config map[tokens.ModuleMember]string) {
|
func printConfig(b *bytes.Buffer, cfg config.Map) {
|
||||||
b.WriteString(fmt.Sprintf("%vConfiguration:%v\n", colors.SpecUnimportant, colors.Reset))
|
b.WriteString(fmt.Sprintf("%vConfiguration:%v\n", colors.SpecUnimportant, colors.Reset))
|
||||||
if config != nil {
|
if cfg != nil {
|
||||||
var keys []string
|
var keys []string
|
||||||
for key := range config {
|
for key := range cfg {
|
||||||
keys = append(keys, string(key))
|
keys = append(keys, string(key))
|
||||||
}
|
}
|
||||||
sort.Strings(keys)
|
sort.Strings(keys)
|
||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
b.WriteString(fmt.Sprintf(" %v: %v\n", key, config[tokens.ModuleMember(key)]))
|
v, err := cfg[tokens.ModuleMember(key)].Value(config.NewBlindingDecrypter())
|
||||||
|
contract.Assert(err == nil)
|
||||||
|
b.WriteString(fmt.Sprintf(" %v: %v\n", key, v))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ type Crypter interface {
|
||||||
// be used when you want to display configuration information to a user but don't want to prompt for a password
|
// be used when you want to display configuration information to a user but don't want to prompt for a password
|
||||||
// so secrets will not be decrypted.
|
// so secrets will not be decrypted.
|
||||||
func NewBlindingDecrypter() Decrypter {
|
func NewBlindingDecrypter() Decrypter {
|
||||||
return &blindingDecrypter{}
|
return blindingDecrypter{}
|
||||||
}
|
}
|
||||||
|
|
||||||
type blindingDecrypter struct{}
|
type blindingDecrypter struct{}
|
||||||
|
|
|
@ -12,6 +12,19 @@ import (
|
||||||
// Map is a bag of config stored in the settings file.
|
// Map is a bag of config stored in the settings file.
|
||||||
type Map map[tokens.ModuleMember]Value
|
type Map map[tokens.ModuleMember]Value
|
||||||
|
|
||||||
|
// Decrypt returns the configuration as a map from module member to decrypted value.
|
||||||
|
func (m Map) Decrypt(decrypter Decrypter) (map[tokens.ModuleMember]string, error) {
|
||||||
|
r := map[tokens.ModuleMember]string{}
|
||||||
|
for k, c := range m {
|
||||||
|
v, err := c.Value(decrypter)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
r[k] = v
|
||||||
|
}
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
// HasSecureValue returns true if the config map contains a secure (encrypted) value.
|
// HasSecureValue returns true if the config map contains a secure (encrypted) value.
|
||||||
func (m Map) HasSecureValue() bool {
|
func (m Map) HasSecureValue() bool {
|
||||||
for _, v := range m {
|
for _, v := range m {
|
||||||
|
|
|
@ -63,7 +63,7 @@ func (p *Plan) Start(opts Options) (*PlanIterator, error) {
|
||||||
func (p *Plan) configure() error {
|
func (p *Plan) configure() error {
|
||||||
var pkgs []string
|
var pkgs []string
|
||||||
pkgconfigs := make(map[tokens.Package]map[tokens.ModuleMember]string)
|
pkgconfigs := make(map[tokens.Package]map[tokens.ModuleMember]string)
|
||||||
for k, v := range p.target.Config {
|
for k, c := range p.target.Config {
|
||||||
pkg := k.Package()
|
pkg := k.Package()
|
||||||
pkgs = append(pkgs, string(pkg))
|
pkgs = append(pkgs, string(pkg))
|
||||||
pkgconfig, has := pkgconfigs[pkg]
|
pkgconfig, has := pkgconfigs[pkg]
|
||||||
|
@ -71,6 +71,10 @@ func (p *Plan) configure() error {
|
||||||
pkgconfig = make(map[tokens.ModuleMember]string)
|
pkgconfig = make(map[tokens.ModuleMember]string)
|
||||||
pkgconfigs[pkg] = pkgconfig
|
pkgconfigs[pkg] = pkgconfig
|
||||||
}
|
}
|
||||||
|
v, err := c.Value(p.target.Decrypter)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
pkgconfig[k] = v
|
pkgconfig[k] = v
|
||||||
}
|
}
|
||||||
sort.Strings(pkgs)
|
sort.Strings(pkgs)
|
||||||
|
|
|
@ -150,16 +150,24 @@ func (iter *evalSourceIterator) forkRun(opts Options) {
|
||||||
go func() {
|
go func() {
|
||||||
// Next, launch the language plugin.
|
// Next, launch the language plugin.
|
||||||
// IDEA: cache these so we reuse the same language plugin instance; if we do this, monitors must be per-run.
|
// IDEA: cache these so we reuse the same language plugin instance; if we do this, monitors must be per-run.
|
||||||
rt := iter.src.runinfo.Pkg.Runtime
|
run := func() error {
|
||||||
langhost, err := iter.src.plugctx.Host.LanguageRuntime(rt, iter.mon.Address())
|
rt := iter.src.runinfo.Pkg.Runtime
|
||||||
if err != nil {
|
langhost, err := iter.src.plugctx.Host.LanguageRuntime(rt, iter.mon.Address())
|
||||||
err = errors.Wrapf(err, "failed to launch language host for '%v'", rt)
|
if err != nil {
|
||||||
} else if langhost == nil {
|
return errors.Wrapf(err, "failed to launch language host for '%v'", rt)
|
||||||
err = errors.Errorf("could not load language plugin for '%v' from $PATH", rt)
|
} else if langhost == nil {
|
||||||
} else {
|
return errors.Errorf("could not load language plugin for '%v' from $PATH", rt)
|
||||||
|
}
|
||||||
|
|
||||||
// Make sure to clean up before exiting.
|
// Make sure to clean up before exiting.
|
||||||
defer contract.IgnoreClose(langhost)
|
defer contract.IgnoreClose(langhost)
|
||||||
|
|
||||||
|
// Decrypt the configuration.
|
||||||
|
config, err := iter.src.runinfo.Target.Config.Decrypt(iter.src.runinfo.Target.Decrypter)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Now run the actual program.
|
// Now run the actual program.
|
||||||
var progerr string
|
var progerr string
|
||||||
progerr, err = langhost.Run(plugin.RunInfo{
|
progerr, err = langhost.Run(plugin.RunInfo{
|
||||||
|
@ -168,7 +176,7 @@ func (iter *evalSourceIterator) forkRun(opts Options) {
|
||||||
Pwd: iter.src.runinfo.Pwd,
|
Pwd: iter.src.runinfo.Pwd,
|
||||||
Program: iter.src.runinfo.Program,
|
Program: iter.src.runinfo.Program,
|
||||||
Args: iter.src.runinfo.Args,
|
Args: iter.src.runinfo.Args,
|
||||||
Config: iter.src.runinfo.Target.Config,
|
Config: config,
|
||||||
DryRun: iter.src.dryRun,
|
DryRun: iter.src.dryRun,
|
||||||
Parallel: opts.Parallel,
|
Parallel: opts.Parallel,
|
||||||
})
|
})
|
||||||
|
@ -176,10 +184,11 @@ func (iter *evalSourceIterator) forkRun(opts Options) {
|
||||||
// If the program had an unhandled error; propagate it to the caller.
|
// If the program had an unhandled error; propagate it to the caller.
|
||||||
err = errors.Errorf("an unhandled error occurred: %v", progerr)
|
err = errors.Errorf("an unhandled error occurred: %v", progerr)
|
||||||
}
|
}
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Communicate the error, if it exists, or nil if the program exited cleanly.
|
// Communicate the error, if it exists, or nil if the program exited cleanly.
|
||||||
iter.finChan <- err
|
iter.finChan <- run()
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,11 +3,13 @@
|
||||||
package deploy
|
package deploy
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/pulumi/pulumi/pkg/resource/config"
|
||||||
"github.com/pulumi/pulumi/pkg/tokens"
|
"github.com/pulumi/pulumi/pkg/tokens"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Target represents information about a deployment target.
|
// Target represents information about a deployment target.
|
||||||
type Target struct {
|
type Target struct {
|
||||||
Name tokens.QName // the target stack name.
|
Name tokens.QName // the target stack name.
|
||||||
Config map[tokens.ModuleMember]string // optional configuration key/values.
|
Config config.Map // optional configuration key/value pairs.
|
||||||
|
Decrypter config.Decrypter // decrypter for secret configuration values.
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue