// Key method for ssh.ClientKeyring interface func (k *SimpleKeychain) Key(i int) (ssh.PublicKey, error) { if i < 0 || i >= len(k.keys) { return nil, nil } switch key := k.keys[i].(type) { case *rsa.PrivateKey: return ssh.NewRSAPublicKey(&key.PublicKey), nil case *dsa.PrivateKey: return ssh.NewDSAPublicKey(&key.PublicKey), nil } panic("unknown key type") }
func (s *stepCreateSSHKey) Run(state multistep.StateBag) multistep.StepAction { client := state.Get("client").(*DigitalOceanClient) ui := state.Get("ui").(packer.Ui) ui.Say("Creating temporary ssh key for droplet...") priv, err := rsa.GenerateKey(rand.Reader, 2014) // ASN.1 DER encoded form priv_der := x509.MarshalPKCS1PrivateKey(priv) priv_blk := pem.Block{ Type: "RSA PRIVATE KEY", Headers: nil, Bytes: priv_der, } // Set the private key in the statebag for later state.Put("privateKey", string(pem.EncodeToMemory(&priv_blk))) // Marshal the public key into SSH compatible format pub := ssh.NewRSAPublicKey(&priv.PublicKey) pub_sshformat := string(ssh.MarshalAuthorizedKey(pub)) // The name of the public key on DO name := fmt.Sprintf("packer-%s", hex.EncodeToString(identifier.NewUUID().Raw())) // Create the key! keyId, err := client.CreateKey(name, pub_sshformat) if err != nil { err := fmt.Errorf("Error creating temporary SSH key: %s", err) state.Put("error", err) ui.Error(err.Error()) return multistep.ActionHalt } // We use this to check cleanup s.keyId = keyId log.Printf("temporary ssh key name: %s", name) // Remember some state for the future state.Put("ssh_key_id", keyId) return multistep.ActionContinue }