Skip to content
Snippets Groups Projects
Commit 8ad1bd3d authored by Theo's avatar Theo :troll:
Browse files

Test and fix bugs from refactor, stable now

parent f003565e
No related branches found
No related tags found
No related merge requests found
useradm
useradm.py
full_commands.py
......@@ -9,20 +9,10 @@ import (
"gitlab.c3sl.ufpr.br/tss24/useradm/utils"
)
const (
MAIL_ALIAS_FILE = "/etc/aliases" // aliases db path for query
DEF_PERMISSION = "0700" // default user dir permission
BLK_PERMISSION = "0000" // user dir permission if blocked
HTML_BASE_PERM = "0755" // set public_html to this on creation
MAX_VARIANCE = 200 // tries made to create login automatically
MIN_UID = 1000
MAX_UID = 6000
)
var CreateCmd = &cobra.Command{
Use: "create",
Short: "Create new user",
RunE: createUserFunc,
RunE: createUserCmd,
}
func init() {
......@@ -49,7 +39,7 @@ func init() {
CreateCmd.Flags().BoolP("confirm", "y", false, "Skip confirmation prompt")
}
func createUserFunc(cmd *cobra.Command, args []string) error {
func createUserCmd(cmd *cobra.Command, args []string) error {
l, err := model.ConnLDAP()
if err != nil {
return err
......@@ -76,6 +66,11 @@ func createUserFunc(cmd *cobra.Command, args []string) error {
return err
}
err = utils.ClearCache()
if err != nil {
fmt.Printf("Failed to reload cache, changes might take a while\nError: %v", err)
}
fmt.Println("User created!")
fmt.Printf("\nUser Login: %v", usr.UID)
fmt.Printf("\nUser Password: %v\n\n", usr.Password)
......@@ -90,22 +85,22 @@ func createNewUserModel(cmd *cobra.Command, l *ldap.Conn) (model.User, bool, err
var u model.User
var opts model.Opts
users, err := model.GetAllUsersLDAP(l)
err := opts.RetrieveOpts(cmd)
if err != nil {
return u, false, err
}
groups, err := model.GetAllGroupsLDAP(l)
if err != nil {
if err := validateInputs(opts); err != nil {
return u, false, err
}
err = opts.RetrieveOpts(cmd)
users, err := model.GetAllUsersLDAP(l)
if err != nil {
return u, false, err
}
if err := validateInputs(opts); err != nil {
groups, err := model.GetAllGroupsLDAP(l)
if err != nil {
return u, false, err
}
......@@ -117,21 +112,6 @@ func createNewUserModel(cmd *cobra.Command, l *ldap.Conn) (model.User, bool, err
return u, false, fmt.Errorf("GRR is required for \"ini\" login type")
}
opts.Homedir, err = utils.GenDirPath("/home", opts.GID, opts.UID, opts.Homedir)
if err != nil {
return u, false, err
}
opts.Nobkp, err = utils.GenDirPath("/nobackup", opts.GID, opts.UID, opts.Nobkp)
if err != nil {
return u, false, err
}
opts.Webdir, err = utils.GenDirPath("/home/html/inf", "", opts.UID, opts.Webdir)
if err != nil {
return u, false, err
}
u = model.User{
UID: opts.UID,
GID: opts.GID,
......@@ -156,6 +136,27 @@ func createNewUserModel(cmd *cobra.Command, l *ldap.Conn) (model.User, bool, err
}
}
if opts.Homedir == "" {
u.Homedir, err = utils.GenDirPath("/home", u.GID, u.UID, u.Homedir)
if err != nil {
return u, false, err
}
}
if opts.Nobkp == "" {
u.Nobackup, err = utils.GenDirPath("/nobackup", u.GID, u.UID, u.Nobackup)
if err != nil {
return u, false, err
}
}
if opts.Webdir == "" {
u.Webdir, err = utils.GenDirPath("/home/html/inf", "", u.UID, u.Webdir)
if err != nil {
return u, false, err
}
}
// get a new UIDNumber
err = u.GetNewUIDNumber(l)
if err != nil {
......
package user
// FIXME: mudanças não são mostradas kkkkkk
import (
"fmt"
"os"
......@@ -25,16 +26,17 @@ type cfg struct {
var ModCmd = &cobra.Command{
Use: "mod [username]",
Short: "Modify user information",
Long: "Opens a file for editing the users config. Uses $EDITOR variable",
Long: `Opens a file for editing the users config.
Uses $EDITOR variable, if it is not set, use vim`,
Args: cobra.ExactArgs(1),
RunE: modifyUserFunc,
RunE: modUserCmd,
}
func init() {
ModCmd.Flags().BoolP("confirm", "y", false, "Skip confirmation prompt")
}
func modifyUserFunc(cmd *cobra.Command, args []string) error {
func modUserCmd(cmd *cobra.Command, args []string) error {
var opts model.Opts
l, err := model.ConnLDAP()
......@@ -216,7 +218,7 @@ func promptUserYaml(state cfg) (cfg, error) {
// abrir o editor
editor := os.Getenv("EDITOR")
if editor == "" {
editor = "nano"
editor = "vim"
}
comd := exec.Command(editor, tmpFile.Name())
......
......@@ -4,33 +4,24 @@ import (
"fmt"
"log"
"path/filepath"
"strconv"
"time"
"github.com/spf13/cobra"
"gitlab.c3sl.ufpr.br/tss24/useradm/model"
"gitlab.c3sl.ufpr.br/tss24/useradm/utils"
)
var (
ANO = strconv.Itoa(time.Now().Year())
NO_BKP_TRASH = "/nobackup/contas_removidas/" + ANO
HOME_TRASH = "/home/contas_removidas/" + ANO
WEB_TRASH = "/home/contas_removidas/html/" + ANO
)
var RemoveCmd = &cobra.Command{
Use: "remove [username]",
Short: "Delete a user",
Args: cobra.ExactArgs(1),
RunE: removeUserFunc,
RunE: removeUserCmd,
}
func init() {
RemoveCmd.Flags().BoolP("confirm", "y", false, "Skip confirmation prompt")
}
func removeUserFunc(cmd *cobra.Command, args []string) error {
func removeUserCmd(cmd *cobra.Command, args []string) error {
var opts model.Opts
success := false
......@@ -54,16 +45,16 @@ func removeUserFunc(cmd *cobra.Command, args []string) error {
defer func() {
if !success {
log.Println("Found error, rolling back dirs...")
_ = utils.MoveAndChown(filepath.Join(NO_BKP_TRASH,
_ = utils.MoveAndChown(filepath.Join(model.NO_BKP_TRASH,
filepath.Base(u.Nobackup)), u.Nobackup, u.UID, u.GID)
_ = utils.MoveAndChown(filepath.Join(HOME_TRASH,
_ = utils.MoveAndChown(filepath.Join(model.HOME_TRASH,
filepath.Base(u.Homedir)), u.Homedir, u.UID, u.GID)
_ = utils.MoveAndChown(filepath.Join(WEB_TRASH,
_ = utils.MoveAndChown(filepath.Join(model.WEB_TRASH,
filepath.Base(u.Webdir)), u.Webdir, u.UID, u.GID)
}
}()
fmt.Printf("Found %v\n\n", u.ToString())
fmt.Printf("Found %v\n\n", u.FullToString())
utils.ConfirmationPrompt(opts.Confirm, "removal")
......
......@@ -12,14 +12,14 @@ var ResetCmd = &cobra.Command{
Use: "reset [username]",
Short: "Reset the password of a user",
Args: cobra.ExactArgs(1),
RunE: resetPass,
RunE: resetPassCmd,
}
func init() {
ResetCmd.Flags().StringP("passwd", "p", "", "User's new password")
}
func resetPass(cmd *cobra.Command, args []string) error {
func resetPassCmd(cmd *cobra.Command, args []string) error {
pass, err := cmd.Flags().GetString("passwd")
if err != nil {
return err
......@@ -35,17 +35,12 @@ func resetPass(cmd *cobra.Command, args []string) error {
pass = utils.GenPassword()
}
users, err := model.GetAllUsersLDAP(l)
login := args[0]
_, err = model.Locate(l, login)
if err != nil {
return err
}
login := args[0]
res := model.Search(users, false, true, login, "", "", "", "", "")
if len(res) != 1 {
return fmt.Errorf("More than one user found")
}
utils.ConfirmationPrompt(false, "password reset")
err = model.ModKRBPassword(login, pass)
if err != nil {
......
......@@ -56,8 +56,9 @@ func tempCreate(cmd *cobra.Command, args []string) error {
}
for i := 1; i <= opts.Number; i++ {
if model.LoginExists(users, opts.UID+strconv.Itoa(i)) {
return fmt.Errorf("User found with login %v%v, won't overwrite", opts.UID, i)
login := opts.UID + strconv.Itoa(i)
if model.LoginExists(users, login) {
return fmt.Errorf("User found with login %v, won't overwrite", login)
}
}
......@@ -113,6 +114,8 @@ func tempCreate(cmd *cobra.Command, args []string) error {
}
}
_ = utils.ClearCache()
success = true
return nil
}
......@@ -137,7 +140,7 @@ func createTempUser(base model.User, num int) error {
base.UID = base.UID + numstring
// gen dn
base.DN = "uid=" + base.UID + ",ou=usuarios,dc=c3local"
base.SetDN(base.UID)
// no webdir for temps
......@@ -168,27 +171,7 @@ func createTempUser(base model.User, num int) error {
fmt.Printf("Pronto para criar:\n%v\n\n", base.FullToString())
utils.ConfirmationPrompt(false, "creation")
// TODO: change for base.Create()
// create ldap
err = base.AddToLDAP(l)
if err != nil {
return err
}
// create kerberos
err = model.CreateKRBPrincipal(base.UID)
if err != nil {
return err
}
// change pass
err = model.ModKRBPassword(base.UID, base.Password)
if err != nil {
return err
}
// create dirs
err = base.CreateDirs()
err = base.Create(l)
if err != nil {
return err
}
......
package model
import (
"bytes"
"fmt"
"os/exec"
"regexp"
)
// creates a KerberosPrincipal for the user
......@@ -19,16 +21,34 @@ func CreateKRBPrincipal(login string) error {
}
// command that changes the password >:D
// the command kadmin.local returns 0 if the password change
// fails, bruh. so we have to check differently.
// FIXME: maybe do the validation with regex?
// the command kadmin.local returns 0 if the password
// change fails, bruh. so we have to check differently.
// in case you find another error message, please include it here :)
func ModKRBPassword(login, password string) error {
cmd := exec.Command("kadmin.local", "-q",
fmt.Sprintf("cpw -pw %s %s", password, login))
output, _ := cmd.CombinedOutput()
if len(output) > 105 {
return fmt.Errorf("Error found changing password, output: \n%v", string(output[:]))
var output bytes.Buffer
cmd.Stdout = &output
cmd.Stderr = &output
err := cmd.Run()
outStr := output.String()
// made like this so it is easy to add more :]
failPatt := []string{
"does not contain enough character",
"is too short",
}
for _, pattern := range failPatt {
if match, _ := regexp.MatchString(pattern, outStr); match {
return fmt.Errorf("Failed to change Kerberos password: \n%s", outStr)
}
}
if err != nil {
return fmt.Errorf("Command execution failed: %v\nOutput:\n%s", err, outStr)
}
return nil
......
......@@ -39,6 +39,7 @@ func ConnLDAP() (*ldap.Conn, error) {
return l, nil
}
// reads the password file in urquell
func getPasswordLDAP(path string) (string, error) {
passwd, err := os.ReadFile(path)
if err != nil {
......@@ -86,7 +87,7 @@ func DelFromLDAP(UID string) error {
// search for all groups the user is a member of
searchReq := ldap.NewSearchRequest(
"ou=grupos,dc=c3local,dc=com",
"ou=grupos,dc=c3local",
ldap.ScopeWholeSubtree,
ldap.NeverDerefAliases, 0, 0, false,
"(memberUid="+UID+")", // Filter by UID membership
......@@ -108,7 +109,7 @@ func DelFromLDAP(UID string) error {
}
// removing user entry
userDN := "uid=" + UID + "ou=usuarios,dc=c3local"
userDN := "uid=" + UID + ",ou=usuarios,dc=c3local"
delReq := ldap.NewDelRequest(userDN, nil)
if err := l.Del(delReq); err != nil &&
!ldap.IsErrorWithCode(err, ldap.LDAPResultNoSuchObject) {
......
......@@ -28,11 +28,11 @@ func (lt LoginType) String() string {
// converts to Ltype
func (lt *LoginType) Parse(s string) {
switch strings.ToLower(s) {
case "initials":
case "initials", "ini":
*lt = Initials
case "firstname":
case "firstname", "first":
*lt = FirstName
case "lastname":
case "lastname", "last":
*lt = LastName
default:
*lt = LoginTypeUnknown
......
......@@ -90,6 +90,7 @@ func (u *User) Create(l *ldap.Conn) error {
defer func() {
if !success {
fmt.Printf("Error found, deleting user...\n")
_ = DelKRBPrincipal(u.UID)
_ = DelFromLDAP(u.UID)
}
......@@ -150,7 +151,7 @@ func Locate(l *ldap.Conn, login string) (User, error) {
}
if !LoginExists(users, login) {
return u, fmt.Errorf("Failed to find login in LDAP database: %v", err)
return u, fmt.Errorf("No such user!")
}
filter := Search(users, false, true, login, "", "", "", "", "")
......@@ -165,7 +166,7 @@ search made: "useradm user show -l %v -e"`, login)
// DN formatting
func (u *User) SetDN(UID string) {
u.DN = "uid=" + UID + "ou=usuarios,dc=c3local"
u.DN = "uid=" + UID + ",ou=usuarios,dc=c3local"
}
// finds next available uidNumber (MEX from uid group)
......
......@@ -14,7 +14,6 @@ import (
const (
MAIL_ALIAS_FILE = "/etc/aliases"
PASSWD_PATH = "/etc/ldapscripts/ldapscripts.passwd"
)
// generic function for filtering data types, in this case the model User
......@@ -78,7 +77,7 @@ func GenDirPath(base, group, login, input string) (string, error) {
p := filepath.Join(base, group, login)
if PathExists(p) {
return p, fmt.Errorf("Path already exists")
return p, fmt.Errorf("Path %v already exists: %v, %v, %v, %v", p, base, group, login, input)
}
return p, nil
......@@ -123,7 +122,7 @@ func MoveAndChown(orig, dest, owner, group string) error {
destPath := filepath.Join(dest, filepath.Base(orig))
if _, err := os.Stat(destPath); err == nil {
return fmt.Errorf("Directory %v already exists, can't move\n", destPath)
return fmt.Errorf("Destiny directiory %v already exists, won't overwrite!\n", destPath)
}
// move directory
......@@ -156,7 +155,7 @@ func ConfirmationPrompt(confirm bool, operation string) {
}
}
// LDAP has a cache...
// LDAP has a cache, so this should reload it
func ClearCache() error {
cmd := exec.Command("nscd", "-i", "passwd")
......@@ -181,6 +180,7 @@ func IsValidDate(arr []string) bool {
mth, err2 := strconv.Atoi(arr[1])
year, err3 := strconv.Atoi(arr[2])
// can't convert --> something's wrong lol
if err1 != nil || err2 != nil || err3 != nil {
return false
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment