packer-cn/builder/googlecompute/step_create_windows_password.go
Megan Marsh a0edaf6c46 Going to revert this change for now, becuase of potential issues that arise from calling Prepare() twice
Revert "use statebag instead of SetSharedState for winRM password"

This reverts commit b35acbd8798a1baa645f0d181731a9cd9318a61c.
2018-09-10 16:48:42 -07:00

125 lines
3.3 KiB
Go

package googlecompute
import (
"context"
"crypto/rand"
"crypto/rsa"
"crypto/x509"
"encoding/base64"
"encoding/binary"
"encoding/pem"
"errors"
"fmt"
"os"
"time"
commonhelper "github.com/hashicorp/packer/helper/common"
"github.com/hashicorp/packer/helper/multistep"
"github.com/hashicorp/packer/packer"
)
// StepCreateWindowsPassword represents a Packer build step that sets the windows password on a Windows GCE instance.
type StepCreateWindowsPassword struct {
Debug bool
DebugKeyPath string
}
// Run executes the Packer build step that sets the windows password on a Windows GCE instance.
func (s *StepCreateWindowsPassword) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
ui := state.Get("ui").(packer.Ui)
d := state.Get("driver").(Driver)
c := state.Get("config").(*Config)
name := state.Get("instance_name").(string)
if c.Comm.WinRMPassword != "" {
state.Put("winrm_password", c.Comm.WinRMPassword)
packer.LogSecretFilter.Set(c.Comm.WinRMPassword)
return multistep.ActionContinue
}
create, ok := state.GetOk("create_windows_password")
if !ok || !create.(bool) {
return multistep.ActionContinue
}
ui.Say("Creating windows user for instance...")
priv, err := rsa.GenerateKey(rand.Reader, 2048)
if err != nil {
err := fmt.Errorf("Error creating temporary key: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
buf := make([]byte, 4)
binary.BigEndian.PutUint32(buf, uint32(priv.E))
data := WindowsPasswordConfig{
key: priv,
UserName: c.Comm.WinRMUser,
Modulus: base64.StdEncoding.EncodeToString(priv.N.Bytes()),
Exponent: base64.StdEncoding.EncodeToString(buf[1:]),
Email: c.Account.ClientEmail,
ExpireOn: time.Now().Add(time.Minute * 5),
}
if s.Debug {
priv_blk := pem.Block{
Type: "RSA PRIVATE KEY",
Headers: nil,
Bytes: x509.MarshalPKCS1PrivateKey(priv),
}
ui.Message(fmt.Sprintf("Saving key for debug purposes: %s", s.DebugKeyPath))
f, err := os.Create(s.DebugKeyPath)
if err != nil {
state.Put("error", fmt.Errorf("Error saving debug key: %s", err))
return multistep.ActionHalt
}
// Write out the key
err = pem.Encode(f, &priv_blk)
f.Close()
if err != nil {
state.Put("error", fmt.Errorf("Error saving debug key: %s", err))
return multistep.ActionHalt
}
}
errCh, err := d.CreateOrResetWindowsPassword(name, c.Zone, &data)
if err == nil {
ui.Message("Waiting for windows password to complete...")
select {
case err = <-errCh:
case <-time.After(c.stateTimeout):
err = errors.New("time out while waiting for the password to be created")
}
}
if err != nil {
err := fmt.Errorf("Error creating windows password: %s", err)
state.Put("error", err)
ui.Error(err.Error())
return multistep.ActionHalt
}
ui.Message("Created password.")
if s.Debug {
ui.Message(fmt.Sprintf(
"Password (since debug is enabled): %s", data.password))
}
state.Put("winrm_password", data.password)
commonhelper.SetSharedState("winrm_password", data.password, c.PackerConfig.PackerBuildName)
packer.LogSecretFilter.Set(data.password)
return multistep.ActionContinue
}
// Nothing to clean up. The windows password is only created on the single instance.
func (s *StepCreateWindowsPassword) Cleanup(state multistep.StateBag) {}