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) {}