github.com/StackPointCloud/packer@v0.10.2-0.20180716202532-b28098e0f79b/builder/googlecompute/step_create_ssh_key.go (about) 1 package googlecompute 2 3 import ( 4 "context" 5 "crypto/rand" 6 "crypto/rsa" 7 "crypto/x509" 8 "encoding/pem" 9 "fmt" 10 "io/ioutil" 11 "os" 12 13 "github.com/hashicorp/packer/helper/multistep" 14 "github.com/hashicorp/packer/packer" 15 "golang.org/x/crypto/ssh" 16 ) 17 18 // StepCreateSSHKey represents a Packer build step that generates SSH key pairs. 19 type StepCreateSSHKey struct { 20 Debug bool 21 DebugKeyPath string 22 PrivateKeyFile string 23 } 24 25 // Run executes the Packer build step that generates SSH key pairs. 26 // The key pairs are added to the multistep state as "ssh_private_key" and 27 // "ssh_public_key". 28 func (s *StepCreateSSHKey) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { 29 ui := state.Get("ui").(packer.Ui) 30 31 if s.PrivateKeyFile != "" { 32 ui.Say("Using existing SSH private key") 33 privateKeyBytes, err := ioutil.ReadFile(s.PrivateKeyFile) 34 if err != nil { 35 state.Put("error", fmt.Errorf( 36 "Error loading configured private key file: %s", err)) 37 return multistep.ActionHalt 38 } 39 40 state.Put("ssh_private_key", string(privateKeyBytes)) 41 state.Put("ssh_public_key", "") 42 43 return multistep.ActionContinue 44 } 45 46 ui.Say("Creating temporary SSH key for instance...") 47 priv, err := rsa.GenerateKey(rand.Reader, 2048) 48 if err != nil { 49 err := fmt.Errorf("Error creating temporary ssh key: %s", err) 50 state.Put("error", err) 51 ui.Error(err.Error()) 52 return multistep.ActionHalt 53 } 54 55 priv_blk := pem.Block{ 56 Type: "RSA PRIVATE KEY", 57 Headers: nil, 58 Bytes: x509.MarshalPKCS1PrivateKey(priv), 59 } 60 61 pub, err := ssh.NewPublicKey(&priv.PublicKey) 62 if err != nil { 63 err := fmt.Errorf("Error creating temporary ssh key: %s", err) 64 state.Put("error", err) 65 ui.Error(err.Error()) 66 return multistep.ActionHalt 67 } 68 state.Put("ssh_private_key", string(pem.EncodeToMemory(&priv_blk))) 69 state.Put("ssh_public_key", string(ssh.MarshalAuthorizedKey(pub))) 70 71 if s.Debug { 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 return multistep.ActionContinue 88 } 89 90 // Nothing to clean up. SSH keys are associated with a single GCE instance. 91 func (s *StepCreateSSHKey) Cleanup(state multistep.StateBag) {}