github.phpd.cn/hashicorp/packer@v1.3.2/builder/amazon/common/step_key_pair.go (about) 1 package common 2 3 import ( 4 "context" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "runtime" 9 10 "github.com/aws/aws-sdk-go/service/ec2" 11 "github.com/hashicorp/packer/helper/communicator" 12 "github.com/hashicorp/packer/helper/multistep" 13 "github.com/hashicorp/packer/packer" 14 ) 15 16 type StepKeyPair struct { 17 Debug bool 18 Comm *communicator.Config 19 DebugKeyPath string 20 21 doCleanup bool 22 } 23 24 func (s *StepKeyPair) Run(_ context.Context, state multistep.StateBag) multistep.StepAction { 25 ui := state.Get("ui").(packer.Ui) 26 27 if s.Comm.SSHPrivateKeyFile != "" { 28 ui.Say("Using existing SSH private key") 29 privateKeyBytes, err := ioutil.ReadFile(s.Comm.SSHPrivateKeyFile) 30 if err != nil { 31 state.Put("error", fmt.Errorf( 32 "Error loading configured private key file: %s", err)) 33 return multistep.ActionHalt 34 } 35 36 s.Comm.SSHPrivateKey = privateKeyBytes 37 38 return multistep.ActionContinue 39 } 40 41 if s.Comm.SSHAgentAuth && s.Comm.SSHKeyPairName == "" { 42 ui.Say("Using SSH Agent with key pair in Source AMI") 43 return multistep.ActionContinue 44 } 45 46 if s.Comm.SSHAgentAuth && s.Comm.SSHKeyPairName != "" { 47 ui.Say(fmt.Sprintf("Using SSH Agent for existing key pair %s", s.Comm.SSHKeyPairName)) 48 return multistep.ActionContinue 49 } 50 51 if s.Comm.SSHTemporaryKeyPairName == "" { 52 ui.Say("Not using temporary keypair") 53 s.Comm.SSHKeyPairName = "" 54 return multistep.ActionContinue 55 } 56 57 ec2conn := state.Get("ec2").(*ec2.EC2) 58 59 ui.Say(fmt.Sprintf("Creating temporary keypair: %s", s.Comm.SSHTemporaryKeyPairName)) 60 keyResp, err := ec2conn.CreateKeyPair(&ec2.CreateKeyPairInput{ 61 KeyName: &s.Comm.SSHTemporaryKeyPairName}) 62 if err != nil { 63 state.Put("error", fmt.Errorf("Error creating temporary keypair: %s", err)) 64 return multistep.ActionHalt 65 } 66 67 s.doCleanup = true 68 69 // Set some data for use in future steps 70 s.Comm.SSHKeyPairName = s.Comm.SSHTemporaryKeyPairName 71 s.Comm.SSHPrivateKey = []byte(*keyResp.KeyMaterial) 72 73 // If we're in debug mode, output the private key to the working 74 // directory. 75 if s.Debug { 76 ui.Message(fmt.Sprintf("Saving key for debug purposes: %s", s.DebugKeyPath)) 77 f, err := os.Create(s.DebugKeyPath) 78 if err != nil { 79 state.Put("error", fmt.Errorf("Error saving debug key: %s", err)) 80 return multistep.ActionHalt 81 } 82 defer f.Close() 83 84 // Write the key out 85 if _, err := f.Write([]byte(*keyResp.KeyMaterial)); err != nil { 86 state.Put("error", fmt.Errorf("Error saving debug key: %s", err)) 87 return multistep.ActionHalt 88 } 89 90 // Chmod it so that it is SSH ready 91 if runtime.GOOS != "windows" { 92 if err := f.Chmod(0600); err != nil { 93 state.Put("error", fmt.Errorf("Error setting permissions of debug key: %s", err)) 94 return multistep.ActionHalt 95 } 96 } 97 } 98 99 return multistep.ActionContinue 100 } 101 102 func (s *StepKeyPair) Cleanup(state multistep.StateBag) { 103 if !s.doCleanup { 104 return 105 } 106 107 ec2conn := state.Get("ec2").(*ec2.EC2) 108 ui := state.Get("ui").(packer.Ui) 109 110 // Remove the keypair 111 ui.Say("Deleting temporary keypair...") 112 _, err := ec2conn.DeleteKeyPair(&ec2.DeleteKeyPairInput{KeyName: &s.Comm.SSHTemporaryKeyPairName}) 113 if err != nil { 114 ui.Error(fmt.Sprintf( 115 "Error cleaning up keypair. Please delete the key manually: %s", s.Comm.SSHTemporaryKeyPairName)) 116 } 117 118 // Also remove the physical key if we're debugging. 119 if s.Debug { 120 if err := os.Remove(s.DebugKeyPath); err != nil { 121 ui.Error(fmt.Sprintf( 122 "Error removing debug key '%s': %s", s.DebugKeyPath, err)) 123 } 124 } 125 }