github.com/openshift/installer@v1.4.17/pkg/asset/password/password.go (about) 1 package password 2 3 import ( 4 "context" 5 "crypto/rand" 6 "math/big" 7 "os" 8 "path/filepath" 9 10 "golang.org/x/crypto/bcrypt" 11 12 "github.com/openshift/installer/pkg/asset" 13 ) 14 15 var ( 16 // kubeadminPasswordPath is the path where kubeadmin user password is stored. 17 kubeadminPasswordPath = filepath.Join("auth", "kubeadmin-password") 18 ) 19 20 // KubeadminPassword is the asset for the kubeadmin user password 21 type KubeadminPassword struct { 22 Password string 23 PasswordHash []byte 24 File *asset.File 25 } 26 27 var _ asset.WritableAsset = (*KubeadminPassword)(nil) 28 29 // Dependencies returns no dependencies. 30 func (a *KubeadminPassword) Dependencies() []asset.Asset { 31 return []asset.Asset{} 32 } 33 34 // Generate the kubeadmin password 35 func (a *KubeadminPassword) Generate(context.Context, asset.Parents) error { 36 err := a.generateRandomPasswordHash(23) 37 if err != nil { 38 return err 39 } 40 return nil 41 } 42 43 // generateRandomPasswordHash generates a hash of a random ASCII password 44 // 5char-5char-5char-5char 45 func (a *KubeadminPassword) generateRandomPasswordHash(length int) error { 46 const ( 47 lowerLetters = "abcdefghijkmnopqrstuvwxyz" 48 upperLetters = "ABCDEFGHIJKLMNPQRSTUVWXYZ" 49 digits = "23456789" 50 all = lowerLetters + upperLetters + digits 51 ) 52 var password string 53 for i := 0; i < length; i++ { 54 n, err := rand.Int(rand.Reader, big.NewInt(int64(len(all)))) 55 if err != nil { 56 return err 57 } 58 newchar := string(all[n.Int64()]) 59 if password == "" { 60 password = newchar 61 } 62 if i < length-1 { 63 n, err = rand.Int(rand.Reader, big.NewInt(int64(len(password)+1))) 64 if err != nil { 65 return err 66 } 67 j := n.Int64() 68 password = password[0:j] + newchar + password[j:] 69 } 70 } 71 pw := []rune(password) 72 for _, replace := range []int{5, 11, 17} { 73 pw[replace] = '-' 74 } 75 if a.Password == "" { 76 a.Password = string(pw) 77 } 78 bytes, err := bcrypt.GenerateFromPassword([]byte(a.Password), bcrypt.DefaultCost) 79 if err != nil { 80 return err 81 } 82 a.PasswordHash = bytes 83 84 a.File = &asset.File{ 85 Filename: kubeadminPasswordPath, 86 Data: []byte(a.Password), 87 } 88 89 return nil 90 } 91 92 // Name returns the human-friendly name of the asset. 93 func (a *KubeadminPassword) Name() string { 94 return "Kubeadmin Password" 95 } 96 97 // Files returns the password file. 98 func (a *KubeadminPassword) Files() []*asset.File { 99 if a.File != nil { 100 return []*asset.File{a.File} 101 } 102 return []*asset.File{} 103 } 104 105 // Load loads a predefined hash only, if one is supplied 106 func (a *KubeadminPassword) Load(f asset.FileFetcher) (found bool, err error) { 107 hashFilePath := filepath.Join("tls", "kubeadmin-password.hash") 108 hashFile, err := f.FetchByName(hashFilePath) 109 if err != nil { 110 if os.IsNotExist(err) { 111 return false, nil 112 } 113 return false, err 114 } 115 116 a.PasswordHash = hashFile.Data 117 // Assisted-service expects to always see a password file, so generate an 118 // empty one 119 a.File = &asset.File{ 120 Filename: kubeadminPasswordPath, 121 } 122 return true, nil 123 }