Эх сурвалжийг харах

Add cron folder and ldap_sync

Andrea Fazzi 6 жил өмнө
parent
commit
bd3de4fe36

+ 7 - 0
cron/ldap_sync/excludes.txt

@@ -0,0 +1,7 @@
+Utente Temporaneo
+Andrea FAZZI
+Giulia ZUDINI
+andrea.fazzi
+giulia.zudini
+utente.temporaneo
+

+ 27 - 0
cron/ldap_sync/mail.tpl

@@ -0,0 +1,27 @@
+Gentile prof./prof.ssa {{.Surname}},
+
+questa mail contiene le sue credenziali di accesso all'infrastruttura
+informatica del Liceo "Carducci-Dante" di Trieste.
+
+Nome utente: {{.GenerateUsername}}
+Password: {{.PlainPassword}}
+
+Cliccando sul seguente link sarà possibile modificare la propria
+password.
+
+https://password.carducci-dante.gov.it
+
+Per accedere al servizio di webmail, seguire il link riportato sotto:
+
+https://webmail.carducci-dante.gov.it
+
+Per accedere al servizio di cloud, seguire il link riportato sotto:
+
+https://cloud.carducci-dante.gov.it
+
+Per ulteriori informazioni sui servizi informatici dell'Istituto, si
+prega di consultare la "Guida ai servizi" depositata all'interno della
+cartella "Tutti i docenti/Guide e manuali".
+
+Cordiali saluti,
+Karmen @ Carducci-Dante

+ 325 - 0
cron/ldap_sync/main.go

@@ -0,0 +1,325 @@
+package main
+
+import (
+	"bufio"
+	"bytes"
+	"crypto/tls"
+	"fmt"
+	"log"
+	"os"
+
+	"github.com/sethvargo/go-password/password"
+
+	gomail "gopkg.in/gomail.v2"
+	ldap "gopkg.in/ldap.v2"
+
+	"text/template"
+
+	tpl_util "gogs.carducci-dante.gov.it/andrea.fazzi/karmen/util/template"
+	karmen_client "gogs.carducci-dante.gov.it/karmen/client"
+	"gogs.carducci-dante.gov.it/karmen/core/orm"
+	karmen_ldap "gogs.carducci-dante.gov.it/karmen/ldap"
+)
+
+const (
+	Remove = iota + 1
+	Add
+	Update
+)
+
+type Action struct {
+	Id   int
+	Type int
+}
+
+var actDict = map[int]string{
+	1: "REMOVE",
+	2: "ADD",
+	3: "UPDATE",
+}
+
+func diff(dst []string, src []string, excludes []string) map[string]*Action {
+	actions := make(map[string]*Action)
+
+	for id, el := range dst {
+		if !excluded(excludes, el) {
+			actions[el] = &Action{id, Remove}
+		}
+	}
+
+	for id, el := range src {
+		_, ok := actions[el]
+		if !ok {
+			actions[el] = &Action{id, Add}
+			continue
+		}
+		actions[el] = &Action{id, Update}
+	}
+
+	return actions
+}
+
+func entriesToSliceFunc(elements []*ldap.Entry, fn func(*ldap.Entry) string) (result []string) {
+	for _, el := range elements {
+		result = append(result, fn(el))
+	}
+	return result
+}
+
+func teachersToSliceFunc(elements []*orm.Teacher, fn func(*orm.Teacher) string) (result []string) {
+	for _, el := range elements {
+		result = append(result, fn(el))
+	}
+	return result
+}
+
+func excluded(excludes []string, name string) bool {
+	for _, excluded := range excludes {
+		if name == excluded {
+			return true
+		}
+	}
+	return false
+}
+
+func filterTeachers(teachers []*orm.Teacher, excludes []string) []*orm.Teacher {
+	fTeachers := teachers[:0]
+	for _, t := range teachers {
+		if t.Name != "Senza nome" && !excluded(excludes, t.CompleteName()) {
+			fTeachers = append(fTeachers, t)
+		}
+	}
+	return fTeachers
+}
+
+func sendMail(teacher *orm.Teacher, tpl *template.Template, dryRun bool) error {
+	var buf bytes.Buffer
+
+	err := tpl.Execute(&buf, teacher)
+	if err != nil {
+		return err
+	}
+
+	log.Printf("Send mail to %s", teacher.AltEmail)
+
+	if !dryRun {
+		m := gomail.NewMessage()
+		m.SetHeader("From", "karmen@carducci-dante.gov.it")
+		m.SetHeader("To", teacher.AltEmail)
+		//m.SetHeader("To", "segreteria.automatica@carducci-dante.gov.it")
+		m.SetHeader("Subject", "Credenziali servizi informatici del Liceo \"Carducci-Dante\" di Trieste")
+		m.SetBody("text/plain", buf.String())
+
+		d := gomail.NewDialer("mail.carducci-dante.gov.it", 25, "karmen", `Kq&&mZ3s5Bdg>"*V~"X+`)
+		d.TLSConfig = &tls.Config{InsecureSkipVerify: true}
+
+		if err := d.DialAndSend(m); err != nil {
+			return err
+		}
+	}
+	return nil
+}
+
+func syncTeachers(ldapClient *karmen_ldap.Client, karmenClient *karmen_client.Client, ldapTeachers []*ldap.Entry, teachers []*orm.Teacher, excludes []string, mailTpl *template.Template) error {
+	actions := diff(
+		entriesToSliceFunc(ldapTeachers, func(entry *ldap.Entry) string { return entry.DN }),
+		teachersToSliceFunc(teachers, func(t *orm.Teacher) string { return ldapClient.TeacherDN(t) }),
+		excludes,
+	)
+
+	for el, act := range actions {
+		switch act.Type {
+		case Remove:
+			err := ldapClient.DeleteByDN(el)
+			if err != nil {
+				return err
+			}
+		case Add:
+			teacher := teachers[act.Id]
+			log.Printf("ADD teacher %s", teacher.CompleteName())
+			password, err := password.Generate(8, 2, 0, false, true)
+			if err != nil {
+				return err
+			}
+			teacher.PlainPassword = password
+			err = ldapClient.AddTeacher(teacher)
+			if err != nil {
+				panic(err)
+			}
+
+			if !teacher.MailSent {
+				log.Printf("Sending credentials to %s, pw is %s", teacher.AltEmail, teacher.PlainPassword)
+				err = sendMail(teacher, mailTpl, false)
+				if err != nil {
+					return err
+				}
+				teacher.MailSent = true
+				err = karmenClient.UpdateTeacher(teacher)
+				if err != nil {
+					return err
+				}
+			}
+
+			// case Update:
+			// 	// teacher := teachers[act.Id]
+			// 	// log.Printf("UPDATE teacher %s", teacher.CompleteName())
+			// 	// err = ldapClient.UpdateTeacher(teacher)
+			// 	// if err != nil {
+			// 	// 	panic(err)
+			// 	// }
+
+		}
+	}
+	return nil
+}
+
+func syncMailingList(ldapClient *karmen_ldap.Client, teachers []*orm.Teacher, excludes []string, groupDN string) error {
+	entries, err := ldapClient.GroupMembers(groupDN)
+	if err != nil {
+		return err
+	}
+
+	actions := diff(
+		entries[0].Attributes[0].Values,
+		teachersToSliceFunc(teachers, func(t *orm.Teacher) string { return ldapClient.TeacherDN(t) }),
+		excludes,
+	)
+
+	for el, act := range actions {
+		switch act.Type {
+		case Remove:
+			log.Printf("REMOVE teacher %s from %s", el, groupDN)
+			ldapClient.RemoveTeacherFromGroupByMemberValue(el, groupDN)
+		case Add:
+			log.Printf("ADD teacher %s to %s", el, groupDN)
+			teacher := teachers[act.Id]
+			err = ldapClient.AddTeacherToGroup(teacher, groupDN)
+			if err != nil {
+				panic(err)
+			}
+		}
+	}
+	return nil
+}
+
+func syncTeachersGroup(ldapClient *karmen_ldap.Client, teachers []*orm.Teacher, excludes []string, groupDN string) error {
+	entries, err := ldapClient.GroupMembers(groupDN)
+	if err != nil {
+		return err
+	}
+
+	actions := diff(
+		entries[0].Attributes[0].Values,
+		teachersToSliceFunc(teachers, func(t *orm.Teacher) string { return t.GenerateUsername() }),
+		excludes,
+	)
+
+	for el, act := range actions {
+		switch act.Type {
+		case Remove:
+			log.Printf("REMOVE teacher %s from %s", el, groupDN)
+			ldapClient.RemoveTeacherFromGroupByMemberValue(el, groupDN)
+		case Add:
+			log.Printf("ADD teacher %s to %s", el, groupDN)
+			teacher := teachers[act.Id]
+			err = ldapClient.AddTeacherToGroup(teacher, groupDN)
+			if err != nil {
+				panic(err)
+			}
+
+		}
+	}
+	return nil
+}
+
+func main() {
+	log.Printf("Connecting to karmen at %s...", "https://karmen.andreafazzi.eu")
+	karmenClient, err := karmen_client.Dial("https://karmen.andreafazzi.eu", "admin", "aolieVooju")
+	if err != nil {
+		panic(err)
+	}
+
+	teachers, err := karmenClient.GetTeachers()
+	if err != nil {
+		panic(err)
+	}
+
+	departments, err := karmenClient.GetDepartments()
+	if err != nil {
+		panic(err)
+	}
+
+	conf := &karmen_ldap.Config{
+		Domain:         "carducci-dante.gov.it",
+		AdminCN:        "admin",
+		AdminPassword:  "CDlinux2016",
+		TeachersDN:     "ou=Docenti,ou=Persone",
+		GroupsDN:       "ou=Gruppi",
+		PeopleDN:       "ou=Persone",
+		MailDirPath:    "/var/mail/carducci-dante.gov.it",
+		MailQuota:      "10240",
+		FirstUIDNumber: "5000",
+		MailGIDNumber:  "5000",
+	}
+
+	log.Printf("Connecting to LDAP at %s...", "ldap.carducci-dante.gov.it:389")
+	ldapClient, err := karmen_ldap.NewClient("ldap.carducci-dante.gov.it:389", conf)
+	if err != nil {
+		panic(err)
+	}
+
+	log.Println("Getting LDAP registered teachers...")
+	ldapTeachers, err := ldapClient.Teachers()
+	if err != nil {
+		panic(err)
+	}
+
+	excludes := make([]string, 0)
+	log.Print("Read excludes...")
+	f, err := os.Open("./excludes.txt")
+	defer f.Close()
+	if err != nil {
+		log.Println(err)
+	} else {
+		scanner := bufio.NewScanner(f)
+		for scanner.Scan() {
+			excludes = append(excludes, scanner.Text())
+		}
+
+		if err := scanner.Err(); err != nil {
+			panic(err)
+		}
+	}
+
+	tpl, err := tpl_util.LoadTextTemplate("mail.tpl")
+	if err != nil {
+		panic(err)
+	}
+
+	fTeachers := filterTeachers(teachers, excludes)
+
+	err = syncTeachers(ldapClient, karmenClient, ldapTeachers, fTeachers, excludes, tpl)
+	if err != nil {
+		panic(err)
+	}
+
+	for _, department := range departments {
+		group := fmt.Sprintf("cn=%s,ou=Mailing Lists", department.Name)
+		err = syncMailingList(ldapClient, filterTeachers(department.Teachers, excludes), excludes, group)
+		if err != nil {
+			panic(err)
+		}
+		group = fmt.Sprintf("cn=%s,ou=Dipartimenti", department.Name)
+		err = syncTeachersGroup(ldapClient, filterTeachers(department.Teachers, excludes), excludes, group)
+		if err != nil {
+			panic(err)
+		}
+
+	}
+
+	err = syncTeachersGroup(ldapClient, fTeachers, excludes, "cn=Docenti")
+	if err != nil {
+		panic(err)
+	}
+
+}