github.com/amanya/packer@v0.12.1-0.20161117214323-902ac5ab2eb6/builder/googlecompute/step_create_windows_password.go (about)

     1  package googlecompute
     2  
     3  import (
     4  	"crypto/rand"
     5  	"crypto/rsa"
     6  	"crypto/x509"
     7  	"encoding/base64"
     8  	"encoding/binary"
     9  	"encoding/pem"
    10  	"errors"
    11  	"fmt"
    12  	"os"
    13  	"time"
    14  
    15  	"github.com/mitchellh/multistep"
    16  	"github.com/mitchellh/packer/packer"
    17  )
    18  
    19  // StepCreateWindowsPassword represents a Packer build step that sets the windows password on a Windows GCE instance.
    20  type StepCreateWindowsPassword struct {
    21  	Debug        bool
    22  	DebugKeyPath string
    23  }
    24  
    25  // Run executes the Packer build step that sets the windows password on a Windows GCE instance.
    26  func (s *StepCreateWindowsPassword) Run(state multistep.StateBag) multistep.StepAction {
    27  	ui := state.Get("ui").(packer.Ui)
    28  	d := state.Get("driver").(Driver)
    29  	c := state.Get("config").(*Config)
    30  	name := state.Get("instance_name").(string)
    31  
    32  	if c.Comm.WinRMPassword != "" {
    33  		state.Put("winrm_password", c.Comm.WinRMPassword)
    34  		return multistep.ActionContinue
    35  	}
    36  
    37  	create, ok := state.GetOk("create_windows_password")
    38  
    39  	if !ok || !create.(bool) {
    40  		return multistep.ActionContinue
    41  
    42  	}
    43  	ui.Say("Creating windows user for instance...")
    44  	priv, err := rsa.GenerateKey(rand.Reader, 2048)
    45  	if err != nil {
    46  		err := fmt.Errorf("Error creating temporary key: %s", err)
    47  		state.Put("error", err)
    48  		ui.Error(err.Error())
    49  		return multistep.ActionHalt
    50  	}
    51  
    52  	buf := make([]byte, 4)
    53  	binary.BigEndian.PutUint32(buf, uint32(priv.E))
    54  
    55  	data := WindowsPasswordConfig{
    56  		key:      priv,
    57  		UserName: c.Comm.WinRMUser,
    58  		Modulus:  base64.StdEncoding.EncodeToString(priv.N.Bytes()),
    59  		Exponent: base64.StdEncoding.EncodeToString(buf[1:]),
    60  		Email:    c.Account.ClientEmail,
    61  		ExpireOn: time.Now().Add(time.Minute * 5),
    62  	}
    63  
    64  	if s.Debug {
    65  
    66  		priv_blk := pem.Block{
    67  			Type:    "RSA PRIVATE KEY",
    68  			Headers: nil,
    69  			Bytes:   x509.MarshalPKCS1PrivateKey(priv),
    70  		}
    71  
    72  		ui.Message(fmt.Sprintf("Saving key for debug purposes: %s", s.DebugKeyPath))
    73  		f, err := os.Create(s.DebugKeyPath)
    74  		if err != nil {
    75  			state.Put("error", fmt.Errorf("Error saving debug key: %s", err))
    76  			return multistep.ActionHalt
    77  		}
    78  
    79  		// Write out the key
    80  		err = pem.Encode(f, &priv_blk)
    81  		f.Close()
    82  		if err != nil {
    83  			state.Put("error", fmt.Errorf("Error saving debug key: %s", err))
    84  			return multistep.ActionHalt
    85  		}
    86  	}
    87  
    88  	errCh, err := d.CreateOrResetWindowsPassword(name, c.Zone, &data)
    89  
    90  	if err == nil {
    91  		ui.Message("Waiting for windows password to complete...")
    92  		select {
    93  		case err = <-errCh:
    94  		case <-time.After(c.stateTimeout):
    95  			err = errors.New("time out while waiting for the password to be created")
    96  		}
    97  	}
    98  
    99  	if err != nil {
   100  		err := fmt.Errorf("Error creating windows password: %s", err)
   101  		state.Put("error", err)
   102  		ui.Error(err.Error())
   103  		return multistep.ActionHalt
   104  	}
   105  
   106  	ui.Message("Created password.")
   107  
   108  	if s.Debug {
   109  		ui.Message(fmt.Sprintf(
   110  			"Password (since debug is enabled): %s", data.password))
   111  	}
   112  
   113  	state.Put("winrm_password", data.password)
   114  
   115  	return multistep.ActionContinue
   116  }
   117  
   118  // Nothing to clean up. The windows password is only created on the single instance.
   119  func (s *StepCreateWindowsPassword) Cleanup(state multistep.StateBag) {}