github.phpd.cn/hashicorp/packer@v1.3.2/builder/scaleway/step_create_ssh_key.go (about) 1 package scaleway 2 3 import ( 4 "context" 5 "crypto/rand" 6 "crypto/rsa" 7 "crypto/x509" 8 "encoding/pem" 9 "fmt" 10 "io/ioutil" 11 "log" 12 "os" 13 "runtime" 14 15 "github.com/hashicorp/packer/helper/multistep" 16 "github.com/hashicorp/packer/packer" 17 "golang.org/x/crypto/ssh" 18 ) 19 20 type stepCreateSSHKey struct { 21 Debug bool 22 DebugKeyPath string 23 } 24 25 func (s *stepCreateSSHKey) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { 26 ui := state.Get("ui").(packer.Ui) 27 config := state.Get("config").(*Config) 28 29 if config.Comm.SSHPrivateKeyFile != "" { 30 ui.Say("Using existing SSH private key") 31 privateKeyBytes, err := ioutil.ReadFile(config.Comm.SSHPrivateKeyFile) 32 if err != nil { 33 state.Put("error", fmt.Errorf( 34 "Error loading configured private key file: %s", err)) 35 return multistep.ActionHalt 36 } 37 38 config.Comm.SSHPrivateKey = privateKeyBytes 39 config.Comm.SSHPublicKey = nil 40 41 return multistep.ActionContinue 42 } 43 44 ui.Say("Creating temporary ssh key for server...") 45 46 priv, err := rsa.GenerateKey(rand.Reader, 4096) 47 if err != nil { 48 err := fmt.Errorf("Error creating temporary SSH key: %s", err) 49 state.Put("error", err) 50 ui.Error(err.Error()) 51 return multistep.ActionHalt 52 } 53 54 // ASN.1 DER encoded form 55 priv_der := x509.MarshalPKCS1PrivateKey(priv) 56 priv_blk := pem.Block{ 57 Type: "RSA PRIVATE KEY", 58 Headers: nil, 59 Bytes: priv_der, 60 } 61 62 pub, err := ssh.NewPublicKey(&priv.PublicKey) 63 if err != nil { 64 err := fmt.Errorf("Error creating temporary SSH key: %s", err) 65 state.Put("error", err) 66 ui.Error(err.Error()) 67 return multistep.ActionHalt 68 } 69 70 log.Printf("temporary ssh key created") 71 72 // Remember some state for the future 73 config.Comm.SSHPrivateKey = pem.EncodeToMemory(&priv_blk) 74 config.Comm.SSHPublicKey = ssh.MarshalAuthorizedKey(pub) 75 76 // If we're in debug mode, output the private key to the working directory. 77 if s.Debug { 78 ui.Message(fmt.Sprintf("Saving key for debug purposes: %s", s.DebugKeyPath)) 79 f, err := os.Create(s.DebugKeyPath) 80 if err != nil { 81 state.Put("error", fmt.Errorf("Error saving debug key: %s", err)) 82 return multistep.ActionHalt 83 } 84 defer f.Close() 85 86 // Write the key out 87 if _, err := f.Write(pem.EncodeToMemory(&priv_blk)); err != nil { 88 state.Put("error", fmt.Errorf("Error saving debug key: %s", err)) 89 return multistep.ActionHalt 90 } 91 92 // Chmod it so that it is SSH ready 93 if runtime.GOOS != "windows" { 94 if err := f.Chmod(0600); err != nil { 95 state.Put("error", fmt.Errorf("Error setting permissions of debug key: %s", err)) 96 return multistep.ActionHalt 97 } 98 } 99 } 100 101 return multistep.ActionContinue 102 } 103 104 func (s *stepCreateSSHKey) Cleanup(state multistep.StateBag) { 105 // SSH key is passed via tag. Nothing to do here. 106 return 107 }