forked from Deuxfleurs/bottin
Rebrand to Bottin (with Superboum's benediction)
This commit is contained in:
parent
e1f5c31402
commit
7962e7b262
7 changed files with 55 additions and 55 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -1,3 +1,3 @@
|
||||||
gobottin
|
bottin
|
||||||
gobottin.static
|
bottin.static
|
||||||
config.json
|
config.json
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
FROM scratch
|
FROM scratch
|
||||||
|
|
||||||
ADD gobottin.static /gobottin
|
ADD bottin.static /bottin
|
||||||
|
|
||||||
ENTRYPOINT ["/gobottin"]
|
ENTRYPOINT ["/bottin"]
|
||||||
|
|
20
Makefile
20
Makefile
|
@ -1,15 +1,15 @@
|
||||||
all: gobottin
|
all: bottin
|
||||||
|
|
||||||
gobottin: main.go ssha.go util.go acl.go read.go write.go
|
bottin: main.go ssha.go util.go acl.go read.go write.go
|
||||||
go get -d -v
|
go get -d -v
|
||||||
go build -v
|
go build -v -o bottin
|
||||||
|
|
||||||
gobottin.static: main.go ssha.go util.go acl.go read.go write.go
|
bottin.static: main.go ssha.go util.go acl.go read.go write.go
|
||||||
go get -d -v
|
go get -d -v
|
||||||
CGO_ENABLED=0 GOOS=linux go build -a -v -o gobottin.static
|
CGO_ENABLED=0 GOOS=linux go build -a -v -o bottin.static
|
||||||
|
|
||||||
docker: gobottin.static
|
docker: bottin.static
|
||||||
docker build -t lxpz/gobottin_amd64:$(TAG) .
|
docker build -t lxpz/bottin_amd64:$(TAG) .
|
||||||
docker push lxpz/gobottin_amd64:$(TAG)
|
docker push lxpz/bottin_amd64:$(TAG)
|
||||||
docker tag lxpz/gobottin_amd64:$(TAG) lxpz/gobottin_amd64:latest
|
docker tag lxpz/bottin_amd64:$(TAG) lxpz/bottin_amd64:latest
|
||||||
docker push lxpz/gobottin_amd64:latest
|
docker push lxpz/bottin_amd64:latest
|
||||||
|
|
40
README.md
40
README.md
|
@ -1,4 +1,4 @@
|
||||||
`gobottin` is a LDAP server that uses Consul's key-value store as a storage backend,
|
Bottin is a LDAP server that uses Consul's key-value store as a storage backend,
|
||||||
in order to provide a redundant (high-availability) LDAP server on a Nomad+Consul cluster.
|
in order to provide a redundant (high-availability) LDAP server on a Nomad+Consul cluster.
|
||||||
It is a reimplementation of [superboum's Bottin](https://github.com/superboum/bottin)
|
It is a reimplementation of [superboum's Bottin](https://github.com/superboum/bottin)
|
||||||
using the Go programming language.
|
using the Go programming language.
|
||||||
|
@ -10,18 +10,18 @@ Features:
|
||||||
- Access control through an ACL (hardcoded in the configuration file)
|
- Access control through an ACL (hardcoded in the configuration file)
|
||||||
|
|
||||||
|
|
||||||
Building `gobottin` can be done simply by running `go build` in this folder.
|
Building Bottin can be done simply by running `go build` in this folder.
|
||||||
|
|
||||||
`gobottin` takes a single command line argument, `-config <filename>`, which is the
|
Bottin takes a single command line argument, `-config <filename>`, which is the
|
||||||
path to its config file (defaults to `./config.json`).
|
path to its config file (defaults to `./config.json`).
|
||||||
The configuration file is a JSON file whose contents is described in the following section.
|
The configuration file is a JSON file whose contents is described in the following section.
|
||||||
|
|
||||||
`gobottin` is licensed under the terms of the GPLv3.
|
Bottin is licensed under the terms of the GPLv3.
|
||||||
|
|
||||||
|
|
||||||
# Server initialization
|
# Server initialization
|
||||||
|
|
||||||
When `gobottin` is launched on an empty database,
|
When Bottin is launched on an empty database,
|
||||||
it creates a special admin entity with the name `cn=admin,your_suffix`.
|
it creates a special admin entity with the name `cn=admin,your_suffix`.
|
||||||
It will have a randomly generated password that is printed out by the server.
|
It will have a randomly generated password that is printed out by the server.
|
||||||
Check your logs to retrieve the password.
|
Check your logs to retrieve the password.
|
||||||
|
@ -31,39 +31,39 @@ so unless you don't want to use it, make sure to keep rules that allow to
|
||||||
bind to the admin entity and that allows the admin entity to do everything.
|
bind to the admin entity and that allows the admin entity to do everything.
|
||||||
|
|
||||||
|
|
||||||
# Configuration of `gobottin`
|
# Configuration of Bottin
|
||||||
|
|
||||||
## The LDAP suffix
|
## The LDAP suffix
|
||||||
|
|
||||||
`gobottin` only handles LDAP entries under a given path, which is typically of
|
Bottin only handles LDAP entries under a given path, which is typically of
|
||||||
the form `dn=sld,dn=tld`, where `sld.tld` is your domain name. Specify this
|
the form `dn=sld,dn=tld`, where `sld.tld` is your domain name. Specify this
|
||||||
suffix in the `suffix` key of the json config file.
|
suffix in the `suffix` key of the json config file.
|
||||||
|
|
||||||
## Connection to the Consul server
|
## Connection to the Consul server
|
||||||
|
|
||||||
By default, `gobottin` connects to the Consul server on localhost.
|
By default, Bottin connects to the Consul server on localhost.
|
||||||
Change this by specifying the `consul_host` key in the json config file.
|
Change this by specifying the `consul_host` key in the json config file.
|
||||||
|
|
||||||
## Bind addresses
|
## Bind addresses
|
||||||
|
|
||||||
### Insecure port
|
### Insecure port
|
||||||
|
|
||||||
By default, `gobottin` listens on all interfaces on port 389 for standard
|
By default, Bottin listens on all interfaces on port 389 for standard
|
||||||
non-TLS connections. Change the value of the `bind` key in the json config
|
non-TLS connections. Change the value of the `bind` key in the json config
|
||||||
file to change this behaviour (default value: `0.0.0.0:389`). An empty string
|
file to change this behaviour (default value: `0.0.0.0:389`). An empty string
|
||||||
will disable this port and `gobottin` will not listen for non-TLS connections.
|
will disable this port and Bottin will not listen for non-TLS connections.
|
||||||
|
|
||||||
### Secure port
|
### Secure port
|
||||||
|
|
||||||
If a TLS configuration is provided (see next section), `gobottin` also listens
|
If a TLS configuration is provided (see next section), Bottin also listens
|
||||||
on all interfaces on port 636 for TLS connections. Change the value of the
|
on all interfaces on port 636 for TLS connections. Change the value of the
|
||||||
`bind_secure` key in the json config file to change this behaviour (default
|
`bind_secure` key in the json config file to change this behaviour (default
|
||||||
value: `0.0.0.0:636`). An empty string will disable this port and `gobottin`
|
value: `0.0.0.0:636`). An empty string will disable this port and Bottin
|
||||||
will not listen for TLS connections.
|
will not listen for TLS connections.
|
||||||
|
|
||||||
## TLS
|
## TLS
|
||||||
|
|
||||||
`gobottin` supports TLS connections using either fully secure connections or
|
Bottin supports TLS connections using either fully secure connections or
|
||||||
using the STARTLS functionnality of the LDAP protocol to upgrade from an
|
using the STARTLS functionnality of the LDAP protocol to upgrade from an
|
||||||
insecure connection. To use it, specify the following three keys in the json
|
insecure connection. To use it, specify the following three keys in the json
|
||||||
config file:
|
config file:
|
||||||
|
@ -80,7 +80,7 @@ is set (non-empty) and no valid TLS configuration is provided.
|
||||||
|
|
||||||
## Access control list
|
## Access control list
|
||||||
|
|
||||||
`gobottin` supports a flexible syntax to specify access rights to items in the database.
|
Bottin supports a flexible syntax to specify access rights to items in the database.
|
||||||
The ACL is specified as a list of rules. A request will be allowed if there exists a rule that allows it. Otherwise an insufficient permission error will be returned.
|
The ACL is specified as a list of rules. A request will be allowed if there exists a rule that allows it. Otherwise an insufficient permission error will be returned.
|
||||||
|
|
||||||
The list of ACL rules are specified in the `acl` key of the json config file, as a list of strings whose structure is defined in the next paragraph.
|
The list of ACL rules are specified in the `acl` key of the json config file, as a list of strings whose structure is defined in the next paragraph.
|
||||||
|
@ -98,20 +98,20 @@ A rule is a string composed of five fields separated by `:`. The fields are the
|
||||||
|
|
||||||
### Rule examples
|
### Rule examples
|
||||||
|
|
||||||
- Anybody (before binding) can bind to an entity under `ou=users,dc=gobottin,dc=eu`:
|
- Anybody (before binding) can bind to an entity under `ou=users,dc=bottin,dc=eu`:
|
||||||
`ANONYMOUS::bind:*,ou=users,dc=gobottin,dc=eu:`
|
`ANONYMOUS::bind:*,ou=users,dc=bottin,dc=eu:`
|
||||||
|
|
||||||
- Anybody (before binding) can bind to the specific admin entity:
|
- Anybody (before binding) can bind to the specific admin entity:
|
||||||
`ANONYMOUS::bind:cn=admin,dc=gobottin,dc=eu:`
|
`ANONYMOUS::bind:cn=admin,dc=bottin,dc=eu:`
|
||||||
|
|
||||||
- Anybody who is logged in can read anything that is not a userpassword attribute:
|
- Anybody who is logged in can read anything that is not a userpassword attribute:
|
||||||
`*,dc=gobottin,dc=eu::read:*:* !userpassword`
|
`*,dc=bottin,dc=eu::read:*:* !userpassword`
|
||||||
|
|
||||||
- Anybody can read and modify anything from their own entry:
|
- Anybody can read and modify anything from their own entry:
|
||||||
`*::read modify:SELF:*`
|
`*::read modify:SELF:*`
|
||||||
|
|
||||||
- The admin can read, add, modify, delete anything:
|
- The admin can read, add, modify, delete anything:
|
||||||
`cn=admin,dc=gobottin,dc=eu::read add modify delete:*:*`
|
`cn=admin,dc=bottin,dc=eu::read add modify delete:*:*`
|
||||||
|
|
||||||
- Members of the admin group can read, add, modify, delete anything:
|
- Members of the admin group can read, add, modify, delete anything:
|
||||||
`*:cn=admin,ou=groups,dc=gobottin,dc=eu:read add modify delete:*:*`
|
`*:cn=admin,ou=groups,dc=bottin,dc=eu:read add modify delete:*:*`
|
||||||
|
|
|
@ -12,7 +12,7 @@ job "directory" {
|
||||||
task "server" {
|
task "server" {
|
||||||
driver = "docker"
|
driver = "docker"
|
||||||
config {
|
config {
|
||||||
image = "lxpz/gobottin_amd64:12"
|
image = "lxpz/bottin_amd64:12"
|
||||||
readonly_rootfs = true
|
readonly_rootfs = true
|
||||||
port_map {
|
port_map {
|
||||||
ldap_port = 389
|
ldap_port = 389
|
||||||
|
@ -23,7 +23,7 @@ job "directory" {
|
||||||
}
|
}
|
||||||
|
|
||||||
artifact {
|
artifact {
|
||||||
source = "http://127.0.0.1:8500/v1/kv/configuration/directory/gobottin/config.json?raw"
|
source = "http://127.0.0.1:8500/v1/kv/configuration/directory/bottin/config.json?raw"
|
||||||
destination = "secrets/config.json"
|
destination = "secrets/config.json"
|
||||||
mode = "file"
|
mode = "file"
|
||||||
}
|
}
|
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
"suffix": "dc=gobottin,dc=eu",
|
"suffix": "dc=bottin,dc=eu",
|
||||||
"bind": "127.0.0.1:1389",
|
"bind": "127.0.0.1:1389",
|
||||||
"acl": [
|
"acl": [
|
||||||
"ANONYMOUS::bind:*,ou=users,dc=gobottin,dc=eu:",
|
"ANONYMOUS::bind:*,ou=users,dc=bottin,dc=eu:",
|
||||||
"ANONYMOUS::bind:cn=admin,dc=gobottin,dc=eu:",
|
"ANONYMOUS::bind:cn=admin,dc=bottin,dc=eu:",
|
||||||
"*,dc=gobottin,dc=eu::read:*:* !userpassword",
|
"*,dc=bottin,dc=eu::read:*:* !userpassword",
|
||||||
"*::read modify:SELF:*",
|
"*::read modify:SELF:*",
|
||||||
"cn=admin,dc=gobottin,dc=eu::read add modify delete:*:*",
|
"cn=admin,dc=bottin,dc=eu::read add modify delete:*:*",
|
||||||
"*:cn=admin,ou=groups,dc=gobottin,dc=eu:read add modify delete:*:*"
|
"*:cn=admin,ou=groups,dc=bottin,dc=eu:read add modify delete:*:*"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
26
main.go
26
main.go
|
@ -140,13 +140,13 @@ func main() {
|
||||||
}
|
}
|
||||||
kv := consul_client.KV()
|
kv := consul_client.KV()
|
||||||
|
|
||||||
// Create gobottin server
|
// Create bottin server
|
||||||
gobottin := Server{
|
bottin := Server{
|
||||||
logger: log.New(os.Stdout, "[gobottin] ", log.LstdFlags),
|
logger: log.New(os.Stdout, "[bottin] ", log.LstdFlags),
|
||||||
config: config,
|
config: config,
|
||||||
kv: kv,
|
kv: kv,
|
||||||
}
|
}
|
||||||
err = gobottin.init()
|
err = bottin.init()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
@ -154,15 +154,15 @@ func main() {
|
||||||
// Create routes
|
// Create routes
|
||||||
routes := ldap.NewRouteMux()
|
routes := ldap.NewRouteMux()
|
||||||
|
|
||||||
routes.Bind(gobottin.handleBind)
|
routes.Bind(bottin.handleBind)
|
||||||
routes.Search(gobottin.handleSearch)
|
routes.Search(bottin.handleSearch)
|
||||||
routes.Add(gobottin.handleAdd)
|
routes.Add(bottin.handleAdd)
|
||||||
routes.Compare(gobottin.handleCompare)
|
routes.Compare(bottin.handleCompare)
|
||||||
routes.Delete(gobottin.handleDelete)
|
routes.Delete(bottin.handleDelete)
|
||||||
routes.Modify(gobottin.handleModify)
|
routes.Modify(bottin.handleModify)
|
||||||
|
|
||||||
if config.TLSConfig != nil {
|
if config.TLSConfig != nil {
|
||||||
routes.Extended(gobottin.handleStartTLS).
|
routes.Extended(bottin.handleStartTLS).
|
||||||
RequestName(ldap.NoticeOfStartTLS).Label("StartTLS")
|
RequestName(ldap.NoticeOfStartTLS).Label("StartTLS")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ func main() {
|
||||||
if config.Bind != "" {
|
if config.Bind != "" {
|
||||||
ldapServer = ldap.NewServer()
|
ldapServer = ldap.NewServer()
|
||||||
ldapServer.Handle(routes)
|
ldapServer.Handle(routes)
|
||||||
ldapServer.NewUserState = gobottin.newUserState
|
ldapServer.NewUserState = bottin.newUserState
|
||||||
go func() {
|
go func() {
|
||||||
err := ldapServer.ListenAndServe(config.Bind)
|
err := ldapServer.ListenAndServe(config.Bind)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -187,7 +187,7 @@ func main() {
|
||||||
if config.TLSConfig != nil {
|
if config.TLSConfig != nil {
|
||||||
ldapServerSecure := ldap.NewServer()
|
ldapServerSecure := ldap.NewServer()
|
||||||
ldapServerSecure.Handle(routes)
|
ldapServerSecure.Handle(routes)
|
||||||
ldapServerSecure.NewUserState = gobottin.newUserState
|
ldapServerSecure.NewUserState = bottin.newUserState
|
||||||
secureConn := func(s *ldap.Server) {
|
secureConn := func(s *ldap.Server) {
|
||||||
s.Listener = tls.NewListener(s.Listener, config.TLSConfig)
|
s.Listener = tls.NewListener(s.Listener, config.TLSConfig)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue