fleet/cmd/fleetctl/user.go

125 lines
3.1 KiB
Go

package main
import (
"bytes"
"fmt"
"os"
"github.com/fleetdm/fleet/server/kolide"
"github.com/pkg/errors"
"github.com/urfave/cli"
"golang.org/x/crypto/ssh/terminal"
)
const (
adminFlagName = "admin"
usernameFlagName = "username"
passwordFlagName = "password"
emailFlagName = "email"
ssoFlagName = "sso"
)
func userCommand() cli.Command {
return cli.Command{
Name: "user",
Usage: "Manage Fleet users",
Subcommands: []cli.Command{
createUserCommand(),
},
}
}
func createUserCommand() cli.Command {
return cli.Command{
Name: "create",
Usage: "Create a new user",
UsageText: `This command will create a new user in Fleet. By default, the user will authenticate with a password and will not have admin privileges.
If a password is required and not provided by flag, the command will prompt for password input through stdin.`,
Flags: []cli.Flag{
cli.StringFlag{
Name: usernameFlagName,
Usage: "Username for new user (required)",
Required: true,
},
cli.StringFlag{
Name: emailFlagName,
Usage: "Email for new user (required)",
Required: true,
},
cli.StringFlag{
Name: passwordFlagName,
Usage: "Password for new user",
},
cli.BoolFlag{
Name: adminFlagName,
Usage: "Grant admin privileges to created user (default false)",
},
cli.BoolFlag{
Name: ssoFlagName,
Usage: "Enable user login via SSO (default false)",
},
configFlag(),
contextFlag(),
yamlFlag(),
},
Action: func(c *cli.Context) error {
fleet, err := clientFromCLI(c)
if err != nil {
return err
}
username := c.String(usernameFlagName)
password := c.String(passwordFlagName)
email := c.String(emailFlagName)
admin := c.Bool(adminFlagName)
sso := c.Bool(ssoFlagName)
if sso && len(password) > 0 {
return fmt.Errorf("Password may not be provided for SSO users.")
}
if !sso && len(password) == 0 {
fmt.Print("Enter password for user: ")
passBytes, err := terminal.ReadPassword(int(os.Stdin.Fd()))
fmt.Println()
if err != nil {
return errors.Wrap(err, "Failed to read password")
}
if len(passBytes) == 0 {
return fmt.Errorf("Password may not be empty.")
}
fmt.Print("Enter password for user (confirm): ")
confBytes, err := terminal.ReadPassword(int(os.Stdin.Fd()))
fmt.Println()
if err != nil {
return errors.Wrap(err, "Failed to read confirmation")
}
if !bytes.Equal(passBytes, confBytes) {
return fmt.Errorf("Confirmation does not match")
}
password = string(passBytes)
}
// Only set the password reset flag if SSO is not enabled. Otherwise
// the user will be stuck in a bad state and not be able to log in.
force_reset := !sso
err = fleet.CreateUser(kolide.UserPayload{
Username: &username,
Password: &password,
Email: &email,
Admin: &admin,
SSOEnabled: &sso,
AdminForcedPasswordReset: &force_reset,
})
if err != nil {
return errors.Wrap(err, "Failed to create user")
}
return nil
},
}
}