Dump Azure configuration values.

Dump the top level variables in the config object. Any values with
'secret' or 'password' in the name are masked.
pull/3511/head
Christopher Boumenot 10 years ago committed by Chris Bednarski
parent d2921a11ab
commit a91156b134

@ -17,7 +17,7 @@ import (
"github.com/mitchellh/packer/builder/azure/common/lin"
"github.com/mitchellh/multistep"
"github.com/mitchellh/packer/common"
packerCommon "github.com/mitchellh/packer/common"
"github.com/mitchellh/packer/helper/communicator"
"github.com/mitchellh/packer/packer"
)
@ -53,6 +53,9 @@ func (b *Builder) Prepare(raws ...interface{}) ([]string, error) {
func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packer.Artifact, error) {
ui.Say("Preparing builder ...")
log.Print(":: Configuration")
packerAzureCommon.DumpConfig(b.config, func(s string) { log.Print(s) })
b.stateBag.Put("hook", hook)
b.stateBag.Put(constants.Ui, ui)
@ -93,7 +96,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
Host: lin.SSHHost,
SSHConfig: lin.SSHConfig(b.config.UserName),
},
&common.StepProvision{},
&packerCommon.StepProvision{},
NewStepGetOSDisk(azureClient, ui),
NewStepPowerOffCompute(azureClient, ui),
NewStepCaptureImage(azureClient, ui),
@ -122,7 +125,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
}, nil
},
},
&common.StepProvision{},
&packerCommon.StepProvision{},
NewStepGetOSDisk(azureClient, ui),
NewStepPowerOffCompute(azureClient, ui),
NewStepCaptureImage(azureClient, ui),
@ -179,7 +182,7 @@ func (b *Builder) createRunner(steps *[]multistep.Step, ui packer.Ui) multistep.
if b.config.PackerDebug {
return &multistep.DebugRunner{
Steps: *steps,
PauseFn: common.MultistepDebugFn(ui),
PauseFn: packerCommon.MultistepDebugFn(ui),
}
}

@ -0,0 +1,69 @@
package common
import (
"fmt"
"github.com/mitchellh/reflectwalk"
"reflect"
"strings"
)
type walker struct {
depth int
say func(string)
}
func newDumpConfig(say func(string)) *walker {
return &walker{
depth: 0,
say: say,
}
}
func (s *walker) Enter(l reflectwalk.Location) error {
s.depth += 1
return nil
}
func (s *walker) Exit(l reflectwalk.Location) error {
s.depth -= 1
return nil
}
func (s *walker) Struct(v reflect.Value) error {
return nil
}
func (s *walker) StructField(f reflect.StructField, v reflect.Value) error {
if !s.shouldDump(v) {
return nil
}
switch v.Kind() {
case reflect.String:
s.say(fmt.Sprintf("%s=%s", f.Name, s.formatValue(f.Name, v.String())))
}
return nil
}
func (s *walker) shouldDump(v reflect.Value) bool {
return s.depth == 2 && v.IsValid() && v.CanInterface()
}
func (s *walker) formatValue(name, value string) string {
if s.isMaskable(name) {
return strings.Repeat("*", len(value))
}
return value
}
func (s *walker) isMaskable(name string) bool {
up := strings.ToUpper(name)
return strings.Contains(up, "SECRET") || strings.Contains(up, "PASSWORD")
}
func DumpConfig(config interface{}, say func(string)) {
walker := newDumpConfig(say)
reflectwalk.Walk(config, walker)
}

@ -0,0 +1,127 @@
package common
import "testing"
func TestShouldDumpPublicValues(t *testing.T) {
type S struct {
MyString string
myString string
}
data := &S{
MyString: "value1",
}
dumps := make([]string, 0, 2)
DumpConfig(data, func(s string) { dumps = append(dumps, s) })
if len(dumps) != 1 {
t.Fatalf("Expected len(dumps) to be 1, but got %d", len(dumps))
}
if dumps[0] != "MyString=value1" {
t.Errorf("Expected dumps[0] to be 'MyString=value1', but got %s", dumps[0])
}
}
func TestShouldOnlyDumpStrings(t *testing.T) {
type S struct {
MyString string
MyInt int
MyFloat32 float32
MyStringPointer *string
}
s := "value1"
data := &S{
MyString: s,
MyInt: 1,
MyFloat32: 2.0,
MyStringPointer: &s,
}
dumps := make([]string, 0, 4)
DumpConfig(data, func(s string) { dumps = append(dumps, s) })
if len(dumps) != 1 {
t.Fatalf("Expected len(dumps) to be 1, but got %d", len(dumps))
}
if dumps[0] != "MyString=value1" {
t.Errorf("Expected dumps[0] to be 'MyString=value1', but got %s", dumps[0])
}
}
func TestDumpShouldMaskSensitiveFieldValues(t *testing.T) {
type S struct {
MyString string
MySecret string
MySecretValue string
MyPassword string
MyPasswordValue string
}
data := &S{
MyString: "my-string",
MySecret: "s3cr3t",
MySecretValue: "s3cr3t-value",
MyPassword: "p@ssw0rd",
MyPasswordValue: "p@ssw0rd-value",
}
dumps := make([]string, 0, 5)
DumpConfig(data, func(s string) { dumps = append(dumps, s) })
if len(dumps) != 5 {
t.Fatalf("Expected len(dumps) to be 5, but got %d", len(dumps))
}
if dumps[0] != "MyString=my-string" {
t.Errorf("Expected dumps[0] to be 'MyString=my-string', but got %s", dumps[0])
}
if dumps[1] != "MySecret=******" {
t.Errorf("Expected dumps[1] to be 'MySecret=******', but got %s", dumps[1])
}
if dumps[2] != "MySecretValue=************" {
t.Errorf("Expected dumps[2] to be 'MySecret=************', but got %s", dumps[2])
}
if dumps[3] != "MyPassword=********" {
t.Errorf("Expected dumps[3] to be 'MyPassword=******** but got %s", dumps[3])
}
if dumps[4] != "MyPasswordValue=**************" {
t.Errorf("Expected dumps[4] to be 'MyPasswordValue=**************' but got %s", dumps[4])
}
}
func TestDumpConfigShouldDumpTopLevelValuesOnly(t *testing.T) {
type N struct {
NestedString string
}
type S struct {
Nested1 N
MyString string
Nested2 N
}
data := &S{
Nested1: N{
NestedString: "nested-string1",
},
MyString: "my-string",
Nested2: N{
NestedString: "nested-string2",
},
}
dumps := make([]string, 0, 1)
DumpConfig(data, func(s string) { dumps = append(dumps, s) })
if len(dumps) != 1 {
t.Fatalf("Expected len(dumps) to be 1, but got %d", len(dumps))
}
if dumps[0] != "MyString=my-string" {
t.Errorf("Expected dumps[0] to be 'MyString=my-string', but got %s", dumps[0])
}
}
Loading…
Cancel
Save