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