github.com/openshift/installer@v1.4.17/pkg/asset/installconfig/ssh.go (about) 1 package installconfig 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "path/filepath" 8 "sort" 9 10 survey "github.com/AlecAivazis/survey/v2" 11 "github.com/AlecAivazis/survey/v2/core" 12 "github.com/pkg/errors" 13 14 "github.com/openshift/installer/pkg/asset" 15 "github.com/openshift/installer/pkg/validate" 16 ) 17 18 const ( 19 noSSHKey = "<none>" 20 ) 21 22 type sshPublicKey struct { 23 Key string 24 } 25 26 var _ asset.Asset = (*sshPublicKey)(nil) 27 28 // Dependencies returns no dependencies. 29 func (a *sshPublicKey) Dependencies() []asset.Asset { 30 return nil 31 } 32 33 func readSSHKey(path string) (string, error) { 34 keyAsBytes, err := os.ReadFile(path) 35 if err != nil { 36 return "", err 37 } 38 39 key := string(keyAsBytes) 40 41 err = validate.SSHPublicKey(key) 42 if err != nil { 43 return "", err 44 } 45 46 return key, nil 47 } 48 49 // Generate generates the SSH public key asset. 50 func (a *sshPublicKey) Generate(context.Context, asset.Parents) error { 51 pubKeys := map[string]string{ 52 noSSHKey: "", 53 } 54 home := os.Getenv("HOME") 55 if home != "" { 56 paths, err := filepath.Glob(filepath.Join(home, ".ssh", "*.pub")) 57 if err != nil { 58 return errors.Wrap(err, "failed to glob for public key files") 59 } 60 for _, path := range paths { 61 key, err := readSSHKey(path) 62 if err != nil { 63 continue 64 } 65 pubKeys[path] = key 66 } 67 } 68 69 if len(pubKeys) == 1 { 70 for _, value := range pubKeys { 71 a.Key = value 72 } 73 return nil 74 } 75 76 var paths []string 77 for path := range pubKeys { 78 paths = append(paths, path) 79 } 80 sort.Strings(paths) 81 82 var path string 83 if err := survey.AskOne( 84 &survey.Select{ 85 Message: "SSH Public Key", 86 Help: "The SSH public key used to access all nodes within the cluster. This is optional.", 87 Options: paths, 88 Default: noSSHKey, 89 }, 90 &path, 91 survey.WithValidator(func(ans interface{}) error { 92 choice := ans.(core.OptionAnswer).Value 93 i := sort.SearchStrings(paths, choice) 94 if i == len(paths) || paths[i] != choice { 95 return fmt.Errorf("invalid path %q", choice) 96 } 97 return nil 98 }), 99 ); err != nil { 100 return errors.Wrap(err, "failed UserInput") 101 } 102 103 a.Key = pubKeys[path] 104 return nil 105 } 106 107 // Name returns the human-friendly name of the asset. 108 func (a sshPublicKey) Name() string { 109 return "SSH Key" 110 }