diff --git a/cmd/user.go b/cmd/user.go index c285e4c..bbf1acd 100644 --- a/cmd/user.go +++ b/cmd/user.go @@ -8,6 +8,8 @@ import ( "github.com/spf13/cobra" "github.com/spf13/viper" ldap "gopkg.in/ldap.v2" + + cli "git.metaunix.net/metaunix.net/muldap/lib/cli" ) var ( @@ -42,8 +44,16 @@ func init() { viper.BindPFlag("user.base_ou", userDeleteCmd.Flags().Lookup("base_ou")) viper.BindPFlag("user.uid_attr", userDeleteCmd.Flags().Lookup("uid_attribute")) + // define user delete subcommand flags + userPwCmd.Flags().StringP("base_ou", "o", "", "LDAP OU where your user entries are stored") + userPwCmd.Flags().StringP("uid_attribute", "a", "uid", "LDAP DN attribute for users") + userPwCmd.Flags().StringVarP(&flagUserUsername, "username", "u", "", "Username of user to delete") + // bind config file values to user delete flags + viper.BindPFlag("user.base_ou", userPwCmd.Flags().Lookup("base_ou")) + viper.BindPFlag("user.uid_attr", userPwCmd.Flags().Lookup("uid_attribute")) + // register add command and subcommands - userCmd.AddCommand(userAddCmd, userDeleteCmd) + userCmd.AddCommand(userAddCmd, userDeleteCmd, userPwCmd) rootCmd.AddCommand(userCmd) } @@ -53,7 +63,7 @@ var userCmd = &cobra.Command{ Short: "Manage LDAP user resources", Long: `Perform various LDAP operations on user resources.`, Run: func(cmd *cobra.Command, args []string) { - fmt.Println("Metaunix.net LDAP tool, user command. Available subcommands are: add, delete") + fmt.Println("Metaunix.net LDAP tool, user command. Available subcommands are: add, delete, pw") }, } @@ -139,3 +149,43 @@ var userDeleteCmd = &cobra.Command{ } }, } + +// define user password subcommand +var userPwCmd = &cobra.Command{ + Use: "pw", + Short: "Set an LDAP user's password", + Long: "Prompts you for a password to use to set an LDAP user's password", + Run: func(cmd *cobra.Command, args []string) { + // create new LDAP connection + l, err := ldap.Dial("tcp", fmt.Sprintf("%s:%d", viper.GetString("host"), viper.GetInt("port"))) + if err != nil { + log.Fatal(err) + } + defer l.Close() + + // bind as the admin user + err = l.Bind(viper.GetString("bind_dn"), viper.GetString("bind_pw")) + if err != nil { + log.Fatal(err) + } + + // get password from user + userPw, pwErr := cli.GetUserInput("New user password", true) + + if pwErr != nil { + log.Fatal(pwErr) + } + + // set up user DN + userDn := fmt.Sprintf("%s=%s,%s", viper.GetString("user.uid_attr"), flagUserUsername, viper.GetString("user.base_ou")) + + // create new password modify request + passwordModifyRequest := ldap.NewPasswordModifyRequest(userDn, "", userPw) + + // perform password change operation + _, err = l.PasswordModify(passwordModifyRequest) + if err != nil { + log.Fatalf("Password could not be changed: %s", err.Error()) + } + }, +} diff --git a/lib/cli/cli.go b/lib/cli/cli.go new file mode 100644 index 0000000..7883c8c --- /dev/null +++ b/lib/cli/cli.go @@ -0,0 +1,35 @@ +package lib + +import ( + "bufio" + "errors" + "fmt" + "os" + "strings" +) + +// prompt user for input +func GetUserInput(consoleMsg string, confirm bool) (string, error) { + reader := bufio.NewReader(os.Stdin) + fmt.Print(fmt.Sprintf("%s: ", consoleMsg)) + input, err := reader.ReadString('\n') + + if err != nil { + return "", err + } + + if confirm { + fmt.Print("Confirm: ") + confirm_input, confirm_err := reader.ReadString('\n') + + if confirm_err != nil { + return "", confirm_err + } + + if input != confirm_input { + return "", errors.New("The passwords provided do not match!") + } + } + + return strings.TrimSpace(input), nil +}