diff --git a/cmd/create/idp/htpasswd.go b/cmd/create/idp/htpasswd.go index bb07117bdd..64d615b727 100644 --- a/cmd/create/idp/htpasswd.go +++ b/cmd/create/idp/htpasswd.go @@ -185,20 +185,24 @@ func getUserList(cmd *cobra.Command, r *rosa.Runtime) (userList map[string]strin func GetUserDetails(cmd *cobra.Command, r *rosa.Runtime, usernameKey, passwordKey, defaultUsername, defaultPassword string) (string, string) { - return GetIdpUserNameFromPrompt(cmd, r, usernameKey, defaultUsername), + return GetIdpUserNameFromPrompt(cmd, r, usernameKey, defaultUsername, false), GetIdpPasswordFromPrompt(cmd, r, passwordKey, defaultPassword) } func GetIdpUserNameFromPrompt(cmd *cobra.Command, r *rosa.Runtime, - usernameKey, defaultUsername string) string { + usernameKey, defaultUsername string, acceptClusterAdmin bool) string { + validators := []interactive.Validator{ + UsernameValidator, + } + if !acceptClusterAdmin { + validators = append(validators, clusterAdminValidator) + } username, err := interactive.GetString(interactive.Input{ - Question: "Username", - Help: cmd.Flags().Lookup(usernameKey).Usage, - Default: defaultUsername, - Required: true, - Validators: []interactive.Validator{ - UsernameValidator, - }, + Question: "Username", + Help: cmd.Flags().Lookup(usernameKey).Usage, + Default: defaultUsername, + Required: true, + Validators: validators, }) if err != nil { exitHTPasswdCreate("Expected a valid username: %s", r.ClusterKey, err, r) @@ -244,10 +248,6 @@ func exitHTPasswdCreate(format, clusterKey string, err error, r *rosa.Runtime) { func UsernameValidator(val interface{}) error { if username, ok := val.(string); ok { - if username == ClusterAdminUsername { - return fmt.Errorf("username '%s' is not allowed. It is preserved for cluster admin creation. "+ - "Run `rosa create admin -c ` to create user '%s'", username, username) - } if strings.ContainsAny(username, "/:%") { return fmt.Errorf("invalid username '%s': "+ "username must not contain /, :, or %%", username) @@ -257,6 +257,17 @@ func UsernameValidator(val interface{}) error { return fmt.Errorf("can only validate strings, got '%v'", val) } +func clusterAdminValidator(val interface{}) error { + if username, ok := val.(string); ok { + if username == ClusterAdminUsername { + return fmt.Errorf("username '%s' is not allowed. It is preserved for cluster admin creation. "+ + "Run `rosa create admin -c ` to create user '%s'", username, username) + } + return nil + } + return fmt.Errorf("can only validate strings, got '%v'", val) +} + func parseHtpasswordFile(usersList *map[string]string, filePath string) error { //A standard wellformed htpasswd file has rows of colon separated usernames and passwords diff --git a/cmd/create/idp/htpasswd_test.go b/cmd/create/idp/htpasswd_test.go index 72670e02ad..70926c6c5f 100644 --- a/cmd/create/idp/htpasswd_test.go +++ b/cmd/create/idp/htpasswd_test.go @@ -85,6 +85,22 @@ var _ = Describe("IDP Tests", func() { ) }) + Describe("Username Validators Tests", func() { + It("username with `:` cannot pass clusterAdminValidator", func() { + username := "my:admin" + err := UsernameValidator(username) + Expect(err).To(HaveOccurred()) + err = clusterAdminValidator(username) + Expect(err).NotTo(HaveOccurred()) + }) + It("username `cluster-admin` cannot pass clusterAdminValidator", func() { + username := "cluster-admin" + err := UsernameValidator(username) + Expect(err).NotTo(HaveOccurred()) + err = clusterAdminValidator(username) + Expect(err).To(HaveOccurred()) + }) + }) }) func CreateTmpFile(content string) (*os.File, error) {