forked from Deuxfleurs/bottin
Externalize config
This commit is contained in:
parent
611d182907
commit
c1f0247586
3 changed files with 120 additions and 34 deletions
16
README.md
Normal file
16
README.md
Normal file
|
@ -0,0 +1,16 @@
|
|||
## ACL examples
|
||||
|
||||
```
|
||||
// Anybody (before binding) can bind to an entity under ou=users,dc=gobottin,dc=eu
|
||||
"ANONYMOUS::bind:*,ou=users,dc=gobottin,dc=eu:",
|
||||
// Anybody (before binding) can bind to the specific admin entity
|
||||
"ANONYMOUS::bind:cn=admin,dc=gobottin,dc=eu:",
|
||||
// Anybody who is logged in can read anything that is not a userpassword attribute
|
||||
"*,dc=gobottin,dc=eu::read:*:* !userpassword",
|
||||
// Anybody can read and modify anything from their own entry
|
||||
"*::read modify:SELF:*",
|
||||
// The admin can read, add, modify, delete anything
|
||||
"cn=admin,dc=gobottin,dc=eu::read add modify delete:*:*",
|
||||
// Members of the admin group can read, add, modify, delete anything
|
||||
"*:cn=admin,ou=groups,dc=gobottin,dc=eu:read add modify delete:*:*"
|
||||
```
|
13
config.json
Normal file
13
config.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"suffix": "dc=gobottin,dc=eu",
|
||||
"bind_address": "127.0.0.1:10389",
|
||||
"acl": [
|
||||
"ANONYMOUS::bind:*,ou=users,dc=gobottin,dc=eu:",
|
||||
"ANONYMOUS::bind:cn=admin,dc=gobottin,dc=eu:",
|
||||
"*,dc=gobottin,dc=eu::read:*:* !userpassword",
|
||||
"*::read modify:SELF:*",
|
||||
"cn=admin,dc=gobottin,dc=eu::read add modify delete:*:*",
|
||||
"*:cn=admin,ou=groups,dc=gobottin,dc=eu:read add modify delete:*:*"
|
||||
]
|
||||
}
|
||||
|
125
main.go
125
main.go
|
@ -1,14 +1,15 @@
|
|||
package main
|
||||
|
||||
// @FIXME: Implement a real permission system: limit read/write scope/attributes, possibly based on group membership
|
||||
// @FIXME: Implement missing search filters (in applyFilter)
|
||||
// @FIXME: Add an initial prefix to the consul key value
|
||||
// @FIXME: Add TLS connections
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
|
@ -21,9 +22,24 @@ import (
|
|||
message "github.com/vjeantet/goldap/message"
|
||||
)
|
||||
|
||||
type ConfigFile struct {
|
||||
Suffix string `json:"suffix"`
|
||||
BindAddress string `json:"bind_address"`
|
||||
ConsulHost string `json:"consul_host"`
|
||||
Acl []string `json:"acl"`
|
||||
SSLCertFile string `json:"ssl_cert_file"`
|
||||
SSLKeyFile string `json:"ssl_key_file"`
|
||||
SSLServerName string `json:"ssl_server_name"`
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Suffix string
|
||||
Acl ACL
|
||||
Suffix string
|
||||
BindAddress string
|
||||
ConsulHost string
|
||||
|
||||
Acl ACL
|
||||
|
||||
TlsConfig *tls.Config
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
|
@ -37,42 +53,77 @@ type State struct {
|
|||
|
||||
type Entry map[string][]string
|
||||
|
||||
var configFlag = flag.String("config", "./config.json", "Configuration file path")
|
||||
|
||||
func readConfig() Config {
|
||||
config_file := ConfigFile{
|
||||
BindAddress: "0.0.0.0:389",
|
||||
}
|
||||
|
||||
bytes, err := ioutil.ReadFile(*configFlag)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
err = json.Unmarshal(bytes, &config_file)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
acl, err := ParseACL(config_file.Acl)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
ret := Config{
|
||||
Suffix: config_file.Suffix,
|
||||
BindAddress: config_file.BindAddress,
|
||||
ConsulHost: config_file.ConsulHost,
|
||||
Acl: acl,
|
||||
}
|
||||
|
||||
if config_file.SSLCertFile != "" && config_file.SSLKeyFile != "" && config_file.SSLServerName != "" {
|
||||
cert_txt, err := ioutil.ReadFile(config_file.SSLCertFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
key_txt, err := ioutil.ReadFile(config_file.SSLKeyFile)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
cert, err := tls.X509KeyPair(cert_txt, key_txt)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ret.TlsConfig = &tls.Config{
|
||||
MinVersion: tls.VersionSSL30,
|
||||
MaxVersion: tls.VersionTLS12,
|
||||
Certificates: []tls.Certificate{cert},
|
||||
ServerName: config_file.SSLServerName,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func main() {
|
||||
//ldap logger
|
||||
ldap.Logger = log.New(os.Stdout, "[server] ", log.LstdFlags)
|
||||
|
||||
config := readConfig()
|
||||
|
||||
// Connect to Consul
|
||||
client, err := consul.NewClient(consul.DefaultConfig())
|
||||
consul_config := consul.DefaultConfig()
|
||||
if config.ConsulHost != "" {
|
||||
consul_config.Address = config.ConsulHost
|
||||
}
|
||||
consul_client, err := consul.NewClient(consul_config)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
kv := client.KV()
|
||||
|
||||
aclStr := []string{
|
||||
// Anybody (before binding) can bind to an entity under ou=users,dc=gobottin,dc=eu
|
||||
"ANONYMOUS::bind:*,ou=users,dc=gobottin,dc=eu:",
|
||||
// Anybody (before binding) can bind to the specific admin entity
|
||||
"ANONYMOUS::bind:cn=admin,dc=gobottin,dc=eu:",
|
||||
// Anybody who is logged in can read anything that is not a userpassword attribute
|
||||
"*,dc=gobottin,dc=eu::read:*:* !userpassword",
|
||||
// Anybody can read and modify anything from their own entry
|
||||
"*::read modify:SELF:*",
|
||||
// The admin can read, add, modify, delete anything
|
||||
"cn=admin,dc=gobottin,dc=eu::read add modify delete:*:*",
|
||||
// Members of the admin group can read, add, modify, delete anything
|
||||
"*:cn=admin,ou=groups,dc=gobottin,dc=eu:read add modify delete:*:*",
|
||||
}
|
||||
acl, err := ParseACL(aclStr)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// TODO read config from somewhere
|
||||
config := Config{
|
||||
Suffix: "dc=gobottin,dc=eu",
|
||||
Acl: acl,
|
||||
}
|
||||
kv := consul_client.KV()
|
||||
|
||||
// Create gobottin server
|
||||
gobottin := Server{config: config, kv: kv}
|
||||
err = gobottin.init()
|
||||
if err != nil {
|
||||
|
@ -99,8 +150,14 @@ func main() {
|
|||
routes.Modify(gobottin.handleModify)
|
||||
ldapserver.Handle(routes)
|
||||
|
||||
// listen on 10389
|
||||
go ldapserver.ListenAndServe("127.0.0.1:10389")
|
||||
if config.TlsConfig != nil {
|
||||
secureConn := func(s *ldap.Server) {
|
||||
s.Listener = tls.NewListener(s.Listener, config.TlsConfig)
|
||||
}
|
||||
go ldapserver.ListenAndServe(config.BindAddress, secureConn)
|
||||
} else {
|
||||
go ldapserver.ListenAndServe(config.BindAddress)
|
||||
}
|
||||
|
||||
// When CTRL+C, SIGINT and SIGTERM signal occurs
|
||||
// Then stop server gracefully
|
||||
|
|
Loading…
Reference in a new issue