Nuestro burocrata preferido: Sam Lowry https://lowry.sindominio.net
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

146 lines
4.5 KiB

package main
import (
"bufio"
"log"
"os"
"sort"
"strings"
"time"
"git.sindominio.net/sindominio/lowry/db"
"git.sindominio.net/sindominio/lowry/gitea"
"git.sindominio.net/sindominio/lowry/ldap"
"git.sindominio.net/sindominio/lowry/mail"
"git.sindominio.net/sindominio/lowry/server"
"github.com/namsral/flag"
)
var (
inviteExpireDuration = time.Hour * 24 * 30 // 30 days
collectiveExpireDuration = time.Hour * 24 * 90 // 90 days
accountExpireDuration = time.Hour * 24 * 90 // 90 days
accountBlockDuration = time.Hour * 24 * 6 * 30 // ~ 6 months
accountDeleteDuration = time.Hour * 24 * 365 // ~ 1 year
)
func main() {
var (
ldapaddr = flag.String("ldapaddr", "localhost:389", "LDAP server address and port")
domain = flag.String("domain", "", "LDAP domain components")
ldappass = flag.String("ldappass", "", "Password of the LDAP `admin' user")
homepath = flag.String("homepath", "/home/", "Path to the user homes")
smtpaddr = flag.String("smtpaddr", "localhost:25", "The address of the smtp server to send email")
email = flag.String("email", "", "The email address to send notifications from")
emailpass = flag.String("emailpass", "", "The password of the email address")
httpaddr = flag.String("httpaddr", ":8080", "Web server address and port")
dbpath = flag.String("dbpath", "bolt.db", "The path to store the lowry status database")
ro = flag.Bool("ro", false, "Read-Only mode")
noLockUsers = flag.Bool("noLockUsers", false, "Don't lock users (mostly useful for development)")
giteaURL = flag.String("giteaURL", "", "Gitea server address")
token = flag.String("token", "", "Gitea admin token")
cloneAddr = flag.String("cloneAddr", "", "Template repo address to copy")
webhookRepoSecret = flag.String("webhookRepoSecret", "", "Webhook secret of the created repo")
webhookRepoURL = flag.String("webhookRepoURL", "", "Webhook url of the created repo")
webhookURL = flag.String("webhookURL", "", "Webhook URL to send user keys")
webhookSecret = flag.String("webhookSecret", "", "Webhook Secret to send user keys")
)
flag.String(flag.DefaultConfigFlagname, "/etc/lowry.conf", "Path to configuration file")
flag.Parse()
m := mail.Init(*email, *emailpass, *smtpaddr, *domain)
l := ldap.Ldap{
Addr: *ldapaddr,
Domain: *domain,
Pass: *ldappass,
HomePath: *homepath,
RO: *ro,
}
err := l.Init()
if err != nil {
log.Fatal(err)
}
g := gitea.Init(*giteaURL, *token, *cloneAddr, *webhookRepoURL, *webhookRepoSecret, *webhookURL, *webhookSecret)
if !*noLockUsers {
go updateUsers(l)
}
ldb, err := db.Init(*dbpath)
if err != nil {
log.Fatal(err)
}
defer ldb.Close()
go cleanInvites(ldb)
log.Fatal(server.Serve(*httpaddr, &l, m, ldb, g))
}
func updateUsers(l ldap.Ldap) {
for {
users, err := l.ListUsers()
if err != nil {
log.Printf("Error listing users for locking: %v", err)
time.Sleep(time.Minute * 61)
continue
}
for _, u := range users {
if u.Shell == "/bin/false" && u.Role == ldap.Sindominante {
err := l.ChangeShell(u.Name, "/bin/bash")
if err != nil {
log.Println("An error ocurred changing shell of '", u.Name, "': ", err)
}
}
newLocked := ldap.Unknown
sinceLastLogin := time.Now().Sub(u.LastLogin)
if u.Locked != ldap.Deleted && sinceLastLogin > accountDeleteDuration {
newLocked = ldap.Deleted
} else if u.Locked != ldap.Blocked && sinceLastLogin > accountBlockDuration && sinceLastLogin < accountDeleteDuration {
newLocked = ldap.Blocked
} else {
continue
}
err = l.ChangeLocked(u.Name, newLocked)
if err != nil {
log.Printf("Error changing locked to %s for user %s: %v", newLocked.String(), u.Name, err)
}
if u.Role == ldap.Sindominante {
err = l.ChangeRole(u.Name, ldap.Amiga)
if err != nil {
log.Printf("Error changing role for blocked user %s: %v", u.Name, err)
}
}
}
time.Sleep(time.Minute * 61)
}
}
func cleanInvites(ldb *db.DB) {
for {
ldb.ExpireInvites(inviteExpireDuration)
ldb.ExpireAccounts(accountExpireDuration)
ldb.ExpireCollectives(collectiveExpireDuration)
time.Sleep(time.Minute * 60)
}
}
func readUserList(listPath string) []string {
f, err := os.Open(listPath)
if err != nil {
log.Fatal(err)
}
defer f.Close()
list := []string{}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
user := strings.TrimSpace(scanner.Text())
list = append(list, user)
}
sort.Strings(list)
return list
}