Compare commits
3 Commits
Author | SHA1 | Date | |
---|---|---|---|
c4e980834d | |||
5e363df9b0 | |||
bdda2de936 |
@ -1,5 +1,12 @@
|
|||||||
LISTEN="0.0.0.0:8081"
|
LISTEN="0.0.0.0:8081"
|
||||||
LDAP_HOST="ldap://ldap.example.org"
|
LDAP_HOST="ldap://ldap.example.org"
|
||||||
LDAP_BASE_DN="dc=example,dc=org"
|
LDAP_BASE_DN="dc=example,dc=org"
|
||||||
|
|
||||||
|
# Credentials used for every op in ldap, so this account needs write access if you want to update ldap
|
||||||
LDAP_USER="cn=ldapuser,dc=example,dc=org"
|
LDAP_USER="cn=ldapuser,dc=example,dc=org"
|
||||||
LDAP_PASS='here_lies_the_password'
|
LDAP_PASS='here_lies_the_password'
|
||||||
|
|
||||||
|
# Https support
|
||||||
|
HTTPS=false
|
||||||
|
SSL_CERTIFICATE=/etc/ssl/certs/server.pem
|
||||||
|
SSL_PRIVATE_KEY=/etc/ssl/private/server.key
|
||||||
|
68
main.go
68
main.go
@ -10,6 +10,7 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"time"
|
"time"
|
||||||
"strings"
|
"strings"
|
||||||
|
"net/http"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
@ -19,7 +20,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
gVersion = "0.4"
|
gVersion = "0.5.1"
|
||||||
)
|
)
|
||||||
|
|
||||||
func marshalResultToText(res *ldap.SearchResult, delimiter string, showValueName, showDN bool) string {
|
func marshalResultToText(res *ldap.SearchResult, delimiter string, showValueName, showDN bool) string {
|
||||||
@ -54,9 +55,9 @@ func sendResponse(c *gin.Context, res *ldap.SearchResult, format string) {
|
|||||||
// 404 Not found
|
// 404 Not found
|
||||||
if len(res.Entries) == 0 {
|
if len(res.Entries) == 0 {
|
||||||
if strings.EqualFold(format, "json") {
|
if strings.EqualFold(format, "json") {
|
||||||
c.JSON(404, gin.H{"error": "No result"})
|
c.JSON(http.StatusNotFound, gin.H{"error": "No result"})
|
||||||
} else {
|
} else {
|
||||||
c.String(404, "No result")
|
c.String(http.StatusNotFound, "No result")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -69,27 +70,27 @@ func sendResponse(c *gin.Context, res *ldap.SearchResult, format string) {
|
|||||||
log.Errorf("Error marshalling result to json: %v", err)
|
log.Errorf("Error marshalling result to json: %v", err)
|
||||||
}
|
}
|
||||||
log.Debugf("%v\n", string(jsonRes))
|
log.Debugf("%v\n", string(jsonRes))
|
||||||
c.String(200, string(jsonRes))
|
c.String(http.StatusOK, string(jsonRes))
|
||||||
|
|
||||||
} else if strings.EqualFold(format, "text") {
|
} else if strings.EqualFold(format, "text") {
|
||||||
txtRes := marshalResultToText(res, "=", false, true)
|
txtRes := marshalResultToText(res, "=", false, true)
|
||||||
log.Debugf("%v\n", string(txtRes))
|
log.Debugf("%v\n", string(txtRes))
|
||||||
c.String(200, string(txtRes))
|
c.String(http.StatusOK, string(txtRes))
|
||||||
|
|
||||||
} else if strings.EqualFold(format, "ldif") {
|
} else if strings.EqualFold(format, "ldif") {
|
||||||
txtRes := marshalResultToText(res, ": ", false, true)
|
txtRes := marshalResultToText(res, ": ", false, true)
|
||||||
log.Debugf("%v\n", string(txtRes))
|
log.Debugf("%v\n", string(txtRes))
|
||||||
c.String(200, string(txtRes))
|
c.String(http.StatusOK, string(txtRes))
|
||||||
|
|
||||||
} else if strings.EqualFold(format, "textvalue") {
|
} else if strings.EqualFold(format, "textvalue") {
|
||||||
txtRes := marshalResultToText(res, "", true, true)
|
txtRes := marshalResultToText(res, "", true, true)
|
||||||
log.Debugf("%v\n", string(txtRes))
|
log.Debugf("%v\n", string(txtRes))
|
||||||
c.String(200, string(txtRes))
|
c.String(http.StatusOK, string(txtRes))
|
||||||
|
|
||||||
} else if strings.EqualFold(format, "textvalue-nodn") {
|
} else if strings.EqualFold(format, "textvalue-nodn") {
|
||||||
txtRes := marshalResultToText(res, "", true, false)
|
txtRes := marshalResultToText(res, "", true, false)
|
||||||
log.Debugf("%v\n", string(txtRes))
|
log.Debugf("%v\n", string(txtRes))
|
||||||
c.String(200, string(txtRes))
|
c.String(http.StatusOK, string(txtRes))
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -149,7 +150,7 @@ func basicAuth(c *gin.Context) {
|
|||||||
if hasAuth && user == "admin" && password == "admin" {
|
if hasAuth && user == "admin" && password == "admin" {
|
||||||
log.Infof("[%s]: User %s successfully authenticated", c.Request.RemoteAddr, user)
|
log.Infof("[%s]: User %s successfully authenticated", c.Request.RemoteAddr, user)
|
||||||
} else {
|
} else {
|
||||||
c.AbortWithStatus(401)
|
c.AbortWithStatus(http.StatusUnauthorized)
|
||||||
c.Writer.Header().Set("WWW-Authenticate", "Basic realm=Restricted")
|
c.Writer.Header().Set("WWW-Authenticate", "Basic realm=Restricted")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -158,7 +159,7 @@ func basicAuth(c *gin.Context) {
|
|||||||
|
|
||||||
func initRouter(r *gin.Engine, myldap *MyLdap) {
|
func initRouter(r *gin.Engine, myldap *MyLdap) {
|
||||||
r.GET("/ping", func(c *gin.Context) {
|
r.GET("/ping", func(c *gin.Context) {
|
||||||
c.JSON(200, gin.H{
|
c.JSON(http.StatusOK, gin.H{
|
||||||
"message": "pong",
|
"message": "pong",
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -178,7 +179,7 @@ func initRouter(r *gin.Engine, myldap *MyLdap) {
|
|||||||
// If OU does not exist, we'll get err='LDAP Result Code 32 "No Such Object"'
|
// If OU does not exist, we'll get err='LDAP Result Code 32 "No Such Object"'
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error searching %s in %s : %v", cn, ou, err)
|
log.Errorf("Error searching %s in %s : %v", cn, ou, err)
|
||||||
c.AbortWithError(500, err)
|
c.AbortWithError(http.StatusInternalServerError, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sendResponse(c, res, format)
|
sendResponse(c, res, format)
|
||||||
@ -195,7 +196,7 @@ func initRouter(r *gin.Engine, myldap *MyLdap) {
|
|||||||
|
|
||||||
modified, err := checkIfModifiedSince(c, myldap, ou, cn, class, "ALL")
|
modified, err := checkIfModifiedSince(c, myldap, ou, cn, class, "ALL")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.AbortWithError(http.StatusInternalServerError, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -203,12 +204,12 @@ func initRouter(r *gin.Engine, myldap *MyLdap) {
|
|||||||
res, err := doLdapSearch(myldap, ou, cn, class, "ALL")
|
res, err := doLdapSearch(myldap, ou, cn, class, "ALL")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error searching %s in %s : %v", cn, ou, err)
|
log.Errorf("Error searching %s in %s : %v", cn, ou, err)
|
||||||
c.AbortWithError(500, err)
|
c.AbortWithError(http.StatusInternalServerError, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sendResponse(c, res, format)
|
sendResponse(c, res, format)
|
||||||
} else {
|
} else {
|
||||||
c.String(304, "")
|
c.String(http.StatusNotModified, "")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
@ -225,7 +226,7 @@ func initRouter(r *gin.Engine, myldap *MyLdap) {
|
|||||||
res, err := doLdapSearch(myldap, ou, cn, class, attr)
|
res, err := doLdapSearch(myldap, ou, cn, class, attr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error searching %s in %s : %v", cn, ou, err)
|
log.Errorf("Error searching %s in %s : %v", cn, ou, err)
|
||||||
c.AbortWithError(500, err)
|
c.AbortWithError(http.StatusInternalServerError, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sendResponse(c, res, format)
|
sendResponse(c, res, format)
|
||||||
@ -243,7 +244,7 @@ func initRouter(r *gin.Engine, myldap *MyLdap) {
|
|||||||
|
|
||||||
modified, err := checkIfModifiedSince(c, myldap, ou, cn, class, attr)
|
modified, err := checkIfModifiedSince(c, myldap, ou, cn, class, attr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(500, err)
|
c.AbortWithError(http.StatusInternalServerError, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -251,12 +252,12 @@ func initRouter(r *gin.Engine, myldap *MyLdap) {
|
|||||||
res, err := doLdapSearch(myldap, ou, cn, class, attr)
|
res, err := doLdapSearch(myldap, ou, cn, class, attr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("Error searching %s in %s : %v", cn, ou, err)
|
log.Errorf("Error searching %s in %s : %v", cn, ou, err)
|
||||||
c.AbortWithError(500, err)
|
c.AbortWithError(http.StatusInternalServerError, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
sendResponse(c, res, format)
|
sendResponse(c, res, format)
|
||||||
} else {
|
} else {
|
||||||
c.String(304, "")
|
c.String(http.StatusNotModified, "")
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
})
|
})
|
||||||
@ -269,6 +270,9 @@ func main() {
|
|||||||
var ldapUser string
|
var ldapUser string
|
||||||
var ldapPass string
|
var ldapPass string
|
||||||
var ldapBaseDN string
|
var ldapBaseDN string
|
||||||
|
var tlsPrivKey string
|
||||||
|
var tlsCert string
|
||||||
|
var doTls bool
|
||||||
var debug bool
|
var debug bool
|
||||||
|
|
||||||
flag.StringVar(&confFile, "config", "", "Path to the config file (optional)")
|
flag.StringVar(&confFile, "config", "", "Path to the config file (optional)")
|
||||||
@ -277,6 +281,9 @@ func main() {
|
|||||||
flag.StringVar(&ldapUser, "ldap-user", "", "ldap username")
|
flag.StringVar(&ldapUser, "ldap-user", "", "ldap username")
|
||||||
flag.StringVar(&ldapPass, "ldap-pass", "", "ldap password")
|
flag.StringVar(&ldapPass, "ldap-pass", "", "ldap password")
|
||||||
flag.StringVar(&ldapBaseDN, "ldap-base-dn", "", "ldap base DN")
|
flag.StringVar(&ldapBaseDN, "ldap-base-dn", "", "ldap base DN")
|
||||||
|
flag.BoolVar(&doTls, "https", false, "Serve over TLS")
|
||||||
|
flag.StringVar(&tlsPrivKey, "ssl-private-key", "", "SSL Private key")
|
||||||
|
flag.StringVar(&tlsCert, "ssl-certificate", "", "SSL certificate (PEM format)")
|
||||||
flag.BoolVar(&debug, "debug", false, "Set log level to debug")
|
flag.BoolVar(&debug, "debug", false, "Set log level to debug")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
@ -328,6 +335,25 @@ func main() {
|
|||||||
log.Fatal("No ldap-base-dn defined!")
|
log.Fatal("No ldap-base-dn defined!")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if false == doTls {
|
||||||
|
doTls = viper.GetBool("HTTPS")
|
||||||
|
}
|
||||||
|
if doTls && len(tlsCert) == 0 {
|
||||||
|
l := viper.GetString("SSL_CERTIFICATE")
|
||||||
|
if len(l) > 0 {
|
||||||
|
tlsCert = l
|
||||||
|
} else {
|
||||||
|
log.Fatal("SSL certificate must be set to use https!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if doTls && len(tlsPrivKey) == 0 {
|
||||||
|
l := viper.GetString("SSL_PRIVATE_KEY")
|
||||||
|
if len(l) > 0 {
|
||||||
|
tlsPrivKey = l
|
||||||
|
} else {
|
||||||
|
log.Fatal("SSL private key must be set to use https!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.Println("Starting Go Ldap API v.", gVersion)
|
log.Println("Starting Go Ldap API v.", gVersion)
|
||||||
if debug {
|
if debug {
|
||||||
@ -340,7 +366,11 @@ func main() {
|
|||||||
|
|
||||||
initRouter(r, &ldap)
|
initRouter(r, &ldap)
|
||||||
|
|
||||||
r.Run(listen)
|
if doTls {
|
||||||
|
r.RunTLS(listen, tlsCert, tlsPrivKey)
|
||||||
|
} else {
|
||||||
|
r.Run(listen)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user