forked from Deuxfleurs/bottin
Fixes
This commit is contained in:
parent
0bd2aeef06
commit
8e4537d2ef
5 changed files with 21 additions and 11 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -1 +1,2 @@
|
||||||
gobottin
|
gobottin
|
||||||
|
config.json
|
||||||
|
|
|
@ -71,7 +71,7 @@ A rule is a string composed of five fields separated by `:`. The fields are the
|
||||||
|
|
||||||
1. The name of the user that must be bound (logged in) for the rule to apply. May contain wildcards such as `*` (see the format used by Go's `path.Match`). The special name `ANONYMOUS` applies to clients before they bind to an LDAP entity.
|
1. The name of the user that must be bound (logged in) for the rule to apply. May contain wildcards such as `*` (see the format used by Go's `path.Match`). The special name `ANONYMOUS` applies to clients before they bind to an LDAP entity.
|
||||||
2. The groups that the user must be a part of, separated by spaces. Wildcards may also be used. If several groups (or wildcard group patterns) are specified, for each pattern the user must be part of a group that matches it.
|
2. The groups that the user must be a part of, separated by spaces. Wildcards may also be used. If several groups (or wildcard group patterns) are specified, for each pattern the user must be part of a group that matches it.
|
||||||
3. The action, a subset of `read`, `add`, `delete`, `modify` separated by spaces.
|
3. The action, a subset of `bind`, `read`, `add`, `delete`, `modify` separated by spaces.
|
||||||
4. The target entity of the action as a pattern that may contain wildcards. The special word `SELF` is replaced by the entity name of the bound user before trying to match.
|
4. The target entity of the action as a pattern that may contain wildcards. The special word `SELF` is replaced by the entity name of the bound user before trying to match.
|
||||||
5. The allowed attributes for a read, add or modify operation. This is specified as a list of patterns to include and exclude attributes, separated by spaces. A pattern that starts by `!` is an exclude pattern, otherwise it is an include pattern. To read/write an attribute, it has to match at least one include pattern and not match any exclude pattern. Delete operations do not check for any attribute, thus as soon as `delete` is included in the allowed actions, the right to delete entities is granted.
|
5. The allowed attributes for a read, add or modify operation. This is specified as a list of patterns to include and exclude attributes, separated by spaces. A pattern that starts by `!` is an exclude pattern, otherwise it is an include pattern. To read/write an attribute, it has to match at least one include pattern and not match any exclude pattern. Delete operations do not check for any attribute, thus as soon as `delete` is included in the allowed actions, the right to delete entities is granted.
|
||||||
|
|
||||||
|
|
15
main.go
15
main.go
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
// @FIXME: Panics if invalid keys are in consul (consulToDN in util.go)
|
// @FIXME: Auto populate entryuuid creatorsname createtimestamp modifiersname modifytimestamp (uuid: github.com/google/uuid, timestamps: 20060102150405Z)
|
||||||
|
// @FIXME: Use memberof and not memberOf
|
||||||
// @FIXME: Implement missing search filters (in applyFilter)
|
// @FIXME: Implement missing search filters (in applyFilter)
|
||||||
// @FIXME: Add an initial prefix to the consul key value
|
// @FIXME: Add an initial prefix to the consul key value
|
||||||
|
|
||||||
|
@ -112,6 +113,8 @@ func readConfig() Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
ldap.Logger = log.New(os.Stdout, "[ldapserver] ", log.LstdFlags)
|
ldap.Logger = log.New(os.Stdout, "[ldapserver] ", log.LstdFlags)
|
||||||
|
|
||||||
config := readConfig()
|
config := readConfig()
|
||||||
|
@ -739,7 +742,10 @@ func (server *Server) handleDeleteInternal(state *State, r *message.DelRequest)
|
||||||
return ldap.LDAPResultNoSuchObject, fmt.Errorf("Not found: %s", dn)
|
return ldap.LDAPResultNoSuchObject, fmt.Errorf("Not found: %s", dn)
|
||||||
}
|
}
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
itemDN, _ := consulToDN(item.Key)
|
itemDN, _, err := consulToDN(item.Key)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if itemDN != dn {
|
if itemDN != dn {
|
||||||
return ldap.LDAPResultNotAllowedOnNonLeaf, fmt.Errorf(
|
return ldap.LDAPResultNotAllowedOnNonLeaf, fmt.Errorf(
|
||||||
"Cannot delete %d as it has children", dn)
|
"Cannot delete %d as it has children", dn)
|
||||||
|
@ -833,7 +839,10 @@ func (server *Server) handleModifyInternal(state *State, r *message.ModifyReques
|
||||||
|
|
||||||
prevEntry := Entry{}
|
prevEntry := Entry{}
|
||||||
for _, item := range items {
|
for _, item := range items {
|
||||||
itemDN, attr := consulToDN(item.Key)
|
itemDN, attr, err := consulToDN(item.Key)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if itemDN != dn {
|
if itemDN != dn {
|
||||||
panic("itemDN != dn in handleModifyInternal")
|
panic("itemDN != dn in handleModifyInternal")
|
||||||
}
|
}
|
||||||
|
|
14
util.go
14
util.go
|
@ -3,7 +3,6 @@ package main
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
consul "github.com/hashicorp/consul/api"
|
consul "github.com/hashicorp/consul/api"
|
||||||
|
@ -24,7 +23,7 @@ func dnToConsul(dn string) (string, error) {
|
||||||
return strings.Join(rdns, "/"), nil
|
return strings.Join(rdns, "/"), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func consulToDN(key string) (string, string) {
|
func consulToDN(key string) (string, string, error) {
|
||||||
path := strings.Split(key, "/")
|
path := strings.Split(key, "/")
|
||||||
dn := ""
|
dn := ""
|
||||||
for _, cpath := range path {
|
for _, cpath := range path {
|
||||||
|
@ -33,16 +32,14 @@ func consulToDN(key string) (string, string) {
|
||||||
}
|
}
|
||||||
kv := strings.Split(cpath, "=")
|
kv := strings.Split(cpath, "=")
|
||||||
if len(kv) == 2 && kv[0] == "attribute" {
|
if len(kv) == 2 && kv[0] == "attribute" {
|
||||||
return dn, kv[1]
|
return dn, kv[1], nil
|
||||||
}
|
}
|
||||||
if dn != "" {
|
if dn != "" {
|
||||||
dn = "," + dn
|
dn = "," + dn
|
||||||
}
|
}
|
||||||
dn = cpath + dn
|
dn = cpath + dn
|
||||||
}
|
}
|
||||||
// TODO don't panic, handle this
|
return "", "", fmt.Errorf("Consul key %s does not end with attribute=something", key)
|
||||||
log.Panicf("Consul key %s does not end with attribute=something", key)
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseValue(value []byte) ([]string, error) {
|
func parseValue(value []byte) ([]string, error) {
|
||||||
|
@ -65,7 +62,10 @@ func parseConsulResult(data []*consul.KVPair) (map[string]Entry, error) {
|
||||||
aggregator := map[string]Entry{}
|
aggregator := map[string]Entry{}
|
||||||
|
|
||||||
for _, kv := range data {
|
for _, kv := range data {
|
||||||
dn, attr := consulToDN(kv.Key)
|
dn, attr, err := consulToDN(kv.Key)
|
||||||
|
if err != nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if _, exists := aggregator[dn]; !exists {
|
if _, exists := aggregator[dn]; !exists {
|
||||||
aggregator[dn] = Entry{}
|
aggregator[dn] = Entry{}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue