quinta-feira, 4 de setembro de 2008

Interface para manipulação de grupos no LDAP

A seguir está uma simples, rápida e não muito elegante interface para manipulação de grupos de usuários no LDAP (Lightweight Directory Access Protocol) que usa o programa cpu por baixo dos panos. A implementação é em Chicken Scheme.

Com esta ferramenta são possíveis as seguintes operações:

  • Listar grupos aos quais um dado usuário pertence

  • Listar usuários que fazem parte de um dado grupo

  • Adicionar usuário a grupo


Exemplos:


$ ldap-groups.scm -h
Uso: ldap-groups.scm -h | -a <user> <group> | -l <group> | -g <user>

-a : adiciona <user> ao grupo <group> (cria <group> se nao existir)
-l : lista os usuarios do grupo <group>
-g : lista os grupos a que pertence o usuario <user>

Listando os usuários do grupo admin:


$ ldap-groups.scm -l admin
mario
joao

Listando os grupos a que pertenço:


$ ldap-groups.scm -g mario
sgpc
admin

Adicionando o meu usuário ao grupo printer:


$ ldap-groups.scm -a mario printer

O código está abaixo:

(use posix srfi-13)

(define (system-output . command)
(let ((cmd (string-intersperse (map ->string command))))
(read-all (open-input-pipe (sprintf "~A 2>&1" cmd)))))

(define *groups-data* #f)

(define (set-groups-data!)
(set! *groups-data*
;; lista de listas (("grupo" "user1" "user2" ... "usern"))
(let ((data (with-input-from-string
(cadr (string-split-fields
"Group Entries\n"
(system-output "cpu cat")
infix:))
read-lines)))
(map (lambda (line)
(let ((ldata (string-split line ":")))
(cons (car ldata) ;; nome do grupo
(let ((users (cdddr ldata))) ;; usuarios
(if (null? users)
'()
(map
string-trim-both
(string-split (car users) ",")))))))
data))))

(define (get-groups user)
(let ((user-groups '()))
(for-each (lambda (group/users)
(when (member user (cdr group/users))
(set! user-groups
(cons (car group/users) user-groups))))
*groups-data*)
user-groups))

(define (group-exists? group)
(not (not (alist-ref group *groups-data* equal?))))

(define (get-users group)
(alist-ref group *groups-data* equal?))

(define (add-user-to-group! user group)
(unless (group-exists? group)
(let ((cmd (conc "cpu groupadd " group)))
(print cmd)
(system-output cmd)))
(let ((cmd (conc "cpu usermod " user " -G "
(string-intersperse
(cons group (get-groups user)) ","))))
(print cmd)
(system-output cmd)))

(define (usage #!optional exit-code)
(print #<#EOF
Uso: #(program-name) -h | -a <user> <group> | -l <group> | -g <user>

-a : adiciona <user> ao grupo <group> (cria <group> se nao existir)
-l : lista os usuarios do grupo <group>
-g : lista os grupos a que pertence o usuario <user>
EOF
)
(when exit-code
(exit exit-code)))

(let ((args (command-line-arguments)))
(when (null? args)
(usage 1))
(set-groups-data!)
(cond ((member (car args) '("-h" "--help" "-help"))
(usage))
((member "-a" args)
(add-user-to-group! (cadr args) (caddr args)))
((member "-l" args)
(map print (or (get-users (cadr args)) '())))
((member "-g" args)
(map print (or (get-groups (cadr args)) '())))
(else (usage 1))))