From 9a6e24aea0c0229b9b30dcf0136228bda34e4690 Mon Sep 17 00:00:00 2001 From: Alex Auvolat Date: Mon, 10 Feb 2020 15:26:02 +0100 Subject: [PATCH] Containerize --- .gitignore | 1 + Dockerfile | 7 ++++ Makefile | 22 +++++++++--- README.md | 6 +++- admin.go | 42 +++++++++++----------- main.go | 76 +++++++++++++++++++-------------------- templates/admin_ldap.html | 2 +- 7 files changed, 89 insertions(+), 67 deletions(-) create mode 100644 Dockerfile diff --git a/.gitignore b/.gitignore index 508fb34..c84fa98 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ guichet +guichet.static config.json diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..05efce0 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,7 @@ +FROM scratch + +ADD static /static +ADD guichet.static /guichet +ADD templates /templates + +ENTRYPOINT ["/guichet"] diff --git a/Makefile b/Makefile index ed43d56..26734d2 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,19 @@ -all: guichet +BIN=guichet +SRC=main.go ssha.go profile.go admin.go +DOCKER=lxpz/guichet_amd64 -guichet: main.go ssha.go profile.go admin.go - go get -v - go build -v +all: $(BIN) + +$(BIN): $(SRC) + go get -d -v + go build -v -o $(BIN) + +$(BIN).static: $(SRC) + go get -d -v + CGO_ENABLED=0 GOOS=linux go build -a -v -o $(BIN).static + +docker: $(BIN).static + docker build -t $(DOCKER):$(TAG) . + docker push $(DOCKER):$(TAG) + docker tag $(DOCKER):$(TAG) $(DOCKER):latest + docker push $(DOCKER):latest diff --git a/README.md b/README.md index 1431c2f..8c77153 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,6 @@ Exemple de config.json pour Deuxfleurs: ``` { "http_bind_addr": ":9991", - "session_key": "V1BAbmn9VW/wL0EZ6Q8xwhkVq/QVwmwPOtliUlfc0iI=", "ldap_server_addr": "ldap://bottin2.service.2.cluster.deuxfleurs.fr:389", "base_dn": "dc=deuxfleurs,dc=fr", @@ -14,7 +13,12 @@ Exemple de config.json pour Deuxfleurs: "group_base_dn": "ou=groups,dc=deuxfleurs,dc=fr", "group_name_attr": "cn", + "admin_account": "cn=admin,dc=deuxfleurs,dc=fr", "group_can_admin": "cn=admin,ou=groups,dc=deuxfleurs,dc=fr", "group_can_invite": "cn=asso_deuxfleurs,ou=groups,dc=deuxfleurs,dc=fr" } ``` + +``` +docker run --net host -v $PWD/config.json:/config.json -i lxpz/guichet_amd64:latest +``` diff --git a/admin.go b/admin.go index daf0267..fa230bc 100644 --- a/admin.go +++ b/admin.go @@ -78,7 +78,7 @@ func handleAdminUsers(w http.ResponseWriter, r *http.Request) { data := &AdminUsersTplData{ Login: login, UserNameAttr: config.UserNameAttr, - UserBaseDN: config.UserBaseDN, + UserBaseDN: config.UserBaseDN, Users: EntryList(sr.Entries), } sort.Sort(data.Users) @@ -117,7 +117,7 @@ func handleAdminGroups(w http.ResponseWriter, r *http.Request) { data := &AdminGroupsTplData{ Login: login, GroupNameAttr: config.GroupNameAttr, - GroupBaseDN: config.GroupBaseDN, + GroupBaseDN: config.GroupBaseDN, Groups: EntryList(sr.Entries), } sort.Sort(data.Groups) @@ -128,11 +128,11 @@ func handleAdminGroups(w http.ResponseWriter, r *http.Request) { type AdminLDAPTplData struct { DN string - Path []PathItem - Children []Child + Path []PathItem + Children []Child CanAddChild bool - Props map[string]*PropValues - CanDelete bool + Props map[string]*PropValues + CanDelete bool HasMembers bool Members []EntryName @@ -161,9 +161,9 @@ type PathItem struct { } type PropValues struct { - Name string - Values []string - Editable bool + Name string + Values []string + Editable bool Deletable bool } @@ -299,7 +299,7 @@ func handleAdminLDAP(w http.ResponseWriter, r *http.Request) { if err != nil { dError = err.Error() } else { - http.Redirect(w, r, "/admin/ldap/" + strings.Join(dn_split[1:], ","), http.StatusFound) + http.Redirect(w, r, "/admin/ldap/"+strings.Join(dn_split[1:], ","), http.StatusFound) return } } @@ -344,16 +344,16 @@ func handleAdminLDAP(w http.ResponseWriter, r *http.Request) { } } deletable := true - for _, restricted := range []string{ "displayname", "objectclass", "structuralobjectclass" } { + for _, restricted := range []string{"displayname", "objectclass", "structuralobjectclass"} { if strings.EqualFold(attr.Name, restricted) { deletable = false break } } props[name_lower] = &PropValues{ - Name: attr.Name, - Values: attr.Values, - Editable: editable, + Name: attr.Name, + Values: attr.Values, + Editable: editable, Deletable: deletable, } } @@ -468,11 +468,11 @@ func handleAdminLDAP(w http.ResponseWriter, r *http.Request) { templateAdminLDAP.Execute(w, &AdminLDAPTplData{ DN: dn, - Path: path, - Children: children, - Props: props, + Path: path, + Children: children, + Props: props, CanAddChild: dn_last_attr == "ou" || isOrganization, - CanDelete: dn != config.BaseDN && len(children) == 0, + CanDelete: dn != config.BaseDN && len(children) == 0, HasMembers: len(members) > 0 || hasMembers, Members: members, @@ -486,14 +486,14 @@ func handleAdminLDAP(w http.ResponseWriter, r *http.Request) { type CreateData struct { SuperDN string - Path []PathItem + Path []PathItem IdType string IdValue string DisplayName string StructuralObjectClass string ObjectClass string - IsTemplated bool + IsTemplated bool Error string } @@ -548,7 +548,7 @@ func handleAdminCreate(w http.ResponseWriter, r *http.Request) { // Handle data data := &CreateData{ SuperDN: super_dn, - Path: path, + Path: path, } if template == "user" { data.IdType = config.UserNameAttr diff --git a/main.go b/main.go index 677e7b2..d8848de 100644 --- a/main.go +++ b/main.go @@ -3,7 +3,6 @@ package main import ( "crypto/rand" "crypto/tls" - "encoding/base64" "encoding/json" "flag" "fmt" @@ -21,7 +20,6 @@ import ( type ConfigFile struct { HttpBindAddr string `json:"http_bind_addr"` - SessionKey string `json:"session_key"` LdapServerAddr string `json:"ldap_server_addr"` LdapTLS bool `json:"ldap_tls"` @@ -31,7 +29,7 @@ type ConfigFile struct { GroupBaseDN string `json:"group_base_dn"` GroupNameAttr string `json:"group_name_attr"` - AdminAccount string `json:"admin_account"` + AdminAccount string `json:"admin_account"` GroupCanInvite string `json:"group_can_invite"` GroupCanAdmin string `json:"group_can_admin"` } @@ -45,15 +43,8 @@ const SESSION_NAME = "guichet_session" var store sessions.Store = nil func readConfig() ConfigFile { - key_bytes := make([]byte, 32) - n, err := rand.Read(key_bytes) - if err != nil || n != 32 { - log.Fatal(err) - } - config_file := ConfigFile{ HttpBindAddr: ":9991", - SessionKey: base64.StdEncoding.EncodeToString(key_bytes), LdapServerAddr: "ldap://127.0.0.1:389", LdapTLS: false, BaseDN: "dc=example,dc=com", @@ -66,7 +57,7 @@ func readConfig() ConfigFile { GroupCanAdmin: "gid=admin,ou=groups,dc=example,dc=com", } - _, err = os.Stat(*configFlag) + _, err := os.Stat(*configFlag) if os.IsNotExist(err) { // Generate default config file log.Printf("Generating default config file as %s", *configFlag) @@ -106,7 +97,13 @@ func main() { config_file := readConfig() config = &config_file - store = sessions.NewFilesystemStore("", []byte(config.SessionKey)) + + session_key := make([]byte, 32) + n, err := rand.Read(session_key) + if err != nil || n != 32 { + log.Fatal(err) + } + store = sessions.NewCookieStore(session_key) r := mux.NewRouter() r.HandleFunc("/", handleHome) @@ -123,7 +120,7 @@ func main() { r.Handle("/static/{file:.*}", http.StripPrefix("/static/", staticfiles)) log.Printf("Starting HTTP server on %s", config.HttpBindAddr) - err := http.ListenAndServe(config.HttpBindAddr, logRequest(r)) + err = http.ListenAndServe(config.HttpBindAddr, logRequest(r)) if err != nil { log.Fatal("Cannot start http server: ", err) } @@ -149,28 +146,28 @@ func logRequest(handler http.Handler) http.Handler { } func checkLogin(w http.ResponseWriter, r *http.Request) *LoginStatus { + var login_info *LoginInfo + session, err := store.Get(r, SESSION_NAME) - if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return nil + if err == nil { + username, ok := session.Values["login_username"] + password, ok2 := session.Values["login_password"] + user_dn, ok3 := session.Values["login_dn"] + + if ok && ok2 && ok3 { + login_info = &LoginInfo{ + DN: user_dn.(string), + Username: username.(string), + Password: password.(string), + } + } } - username, ok := session.Values["login_username"] - password, ok2 := session.Values["login_password"] - user_dn, ok3 := session.Values["login_dn"] - - var login_info *LoginInfo - if !(ok && ok2 && ok3) { + if login_info == nil { login_info = handleLogin(w, r) if login_info == nil { return nil } - } else { - login_info = &LoginInfo{ - DN: user_dn.(string), - Username: username.(string), - Password: password.(string), - } } l := ldapOpen(w) @@ -193,8 +190,8 @@ func checkLogin(w http.ResponseWriter, r *http.Request) *LoginStatus { } loginStatus := &LoginStatus{ - Info: login_info, - conn: l, + Info: login_info, + conn: l, } requestKind := "(objectClass=organizationalPerson)" @@ -245,11 +242,11 @@ func ldapOpen(w http.ResponseWriter) *ldap.Conn { // Page handlers ---- type HomePageData struct { - Login *LoginStatus + Login *LoginStatus WelcomeName string - CanAdmin bool - CanInvite bool - BaseDN string + CanAdmin bool + CanInvite bool + BaseDN string } func handleHome(w http.ResponseWriter, r *http.Request) { @@ -272,10 +269,10 @@ func handleHome(w http.ResponseWriter, r *http.Request) { } data := &HomePageData{ - Login: login, - CanAdmin: can_admin, - CanInvite: can_invite, - BaseDN: config.BaseDN, + Login: login, + CanAdmin: can_admin, + CanInvite: can_invite, + BaseDN: config.BaseDN, WelcomeName: login.UserEntry.GetAttributeValue("givenname"), } if data.WelcomeName == "" { @@ -346,8 +343,7 @@ func handleLogin(w http.ResponseWriter, r *http.Request) *LoginInfo { // Successfully logged in, save it to session session, err := store.Get(r, SESSION_NAME) if err != nil { - http.Error(w, err.Error(), http.StatusInternalServerError) - return nil + session, _ = store.New(r, SESSION_NAME) } session.Values["login_username"] = username diff --git a/templates/admin_ldap.html b/templates/admin_ldap.html index 06d568c..188652b 100644 --- a/templates/admin_ldap.html +++ b/templates/admin_ldap.html @@ -146,7 +146,7 @@
Ajouter au groupe :
- +