aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Auvolat <alex@adnab.me>2021-03-09 19:00:45 +0100
committerAlex Auvolat <alex@adnab.me>2021-03-09 19:00:45 +0100
commit99d8955ab3b5e24552d1f2b621744d07013f58ac (patch)
tree5820b5b594aeea4d4bb366055efef62046221119
parent1a20a64eff34336789c0e3b41db1de727e3fe998 (diff)
downloadbottin-99d8955ab3b5e24552d1f2b621744d07013f58ac.tar.gz
bottin-99d8955ab3b5e24552d1f2b621744d07013f58ac.zip
Refactor & add case normalization logic to putAttributes
-rw-r--r--main.go2
-rw-r--r--read.go3
-rw-r--r--util.go92
-rw-r--r--write.go36
4 files changed, 87 insertions, 46 deletions
diff --git a/main.go b/main.go
index 3d5ba57..13d3da6 100644
--- a/main.go
+++ b/main.go
@@ -74,8 +74,6 @@ type State struct {
login Login
}
-type Entry map[string][]string
-
var configFlag = flag.String("config", "./config.json", "Configuration file path")
var resyncFlag = flag.Bool("resync", false, "Check and re-synchronize memberOf values before launch")
diff --git a/read.go b/read.go
index b36b966..7887c93 100644
--- a/read.go
+++ b/read.go
@@ -17,11 +17,14 @@ func (server *Server) getAttribute(dn string, attr string) ([]string, error) {
return nil, err
}
+ // List all attributes of the object, this is needed because the attribute we are
+ // looking for can exist with different cases than the one specified here
pairs, _, err := server.kv.List(path+"/attribute=", &server.readOpts)
if err != nil {
return nil, err
}
+ // Collect values for the attribute, case-insensitively
values := []string{}
for _, pair := range pairs {
if strings.EqualFold(pair.Key, path+"/attribute="+attr) {
diff --git a/util.go b/util.go
index 30d7a67..cbb6b0f 100644
--- a/util.go
+++ b/util.go
@@ -11,6 +11,13 @@ import (
log "github.com/sirupsen/logrus"
)
+// DNs ----
+
+type dnComponent struct {
+ Type string
+ Value string
+}
+
func dnToConsul(dn string) (string, error) {
if strings.Contains(dn, "/") {
return "", fmt.Errorf("DN %s contains a /", dn)
@@ -45,6 +52,48 @@ func consulToDN(key string) (string, string, error) {
return "", "", fmt.Errorf("Consul key %s does not end with attribute=something", key)
}
+func parseDN(dn string) ([]dnComponent, error) {
+ rdns := strings.Split(dn, ",")
+
+ ret := []dnComponent{}
+
+ for _, rdn := range rdns {
+ splits := strings.Split(rdn, "=")
+ if len(splits) != 2 {
+ return nil, fmt.Errorf("Wrong DN component: %s (expected type=value)", rdn)
+ }
+ ret = append(ret, dnComponent{
+ Type: strings.ToLower(strings.TrimSpace(splits[0])),
+ Value: strings.ToLower(strings.TrimSpace(splits[1])),
+ })
+ }
+ return ret, nil
+}
+
+func unparseDN(path []dnComponent) string {
+ ret := ""
+ for _, c := range path {
+ if ret != "" {
+ ret = ret + ","
+ }
+ ret = ret + c.Type + "=" + c.Value
+ }
+ return ret
+}
+
+func canonicalDN(dn string) (string, error) {
+ path, err := parseDN(dn)
+ if err != nil {
+ return "", err
+ }
+
+ return unparseDN(path), nil
+}
+
+// Values
+
+type Entry map[string][]string
+
func parseValue(value []byte) ([]string, error) {
val := []string{}
err := json.Unmarshal(value, &val)
@@ -82,49 +131,6 @@ func parseConsulResult(data []*consul.KVPair) (map[string]Entry, error) {
return aggregator, nil
}
-type DNComponent struct {
- Type string
- Value string
-}
-
-func parseDN(dn string) ([]DNComponent, error) {
- rdns := strings.Split(dn, ",")
-
- ret := []DNComponent{}
-
- for _, rdn := range rdns {
- splits := strings.Split(rdn, "=")
- if len(splits) != 2 {
- return nil, fmt.Errorf("Wrong DN component: %s (expected type=value)", rdn)
- }
- ret = append(ret, DNComponent{
- Type: strings.ToLower(strings.TrimSpace(splits[0])),
- Value: strings.ToLower(strings.TrimSpace(splits[1])),
- })
- }
- return ret, nil
-}
-
-func unparseDN(path []DNComponent) string {
- ret := ""
- for _, c := range path {
- if ret != "" {
- ret = ret + ","
- }
- ret = ret + c.Type + "=" + c.Value
- }
- return ret
-}
-
-func canonicalDN(dn string) (string, error) {
- path, err := parseDN(dn)
- if err != nil {
- return "", err
- }
-
- return unparseDN(path), nil
-}
-
func checkRestrictedAttr(attr string) error {
RESTRICTED_ATTRS := []string{
ATTR_MEMBEROF,
diff --git a/write.go b/write.go
index e4c7de1..482f971 100644
--- a/write.go
+++ b/write.go
@@ -19,7 +19,31 @@ func (server *Server) putAttributes(dn string, attrs Entry) error {
return err
}
- for k, valuesNC := range attrs {
+ // Normalize attribute names: if we have several times the same attr
+ // but with different cases, put that in the same attr
+ normalized := make(Entry)
+ for k, values := range attrs {
+ found := false
+ for k2 := range normalized {
+ if strings.EqualFold(k, k2) {
+ normalized[k2] = append(normalized[k2], values...)
+ found = true
+ break
+ }
+ }
+ if !found {
+ normalized[k] = values
+ }
+ }
+
+ // Retreieve previously existing attributes, which we will use to delete
+ // entries with the wrong case
+ previous_pairs, _, err := server.kv.List(prefix + "/attribute=", &server.readOpts)
+ if err != nil {
+ return err
+ }
+
+ for k, valuesNC := range normalized {
path := prefix + "/attribute=" + k
// Trim spaces and remove empty values
@@ -31,6 +55,16 @@ func (server *Server) putAttributes(dn string, attrs Entry) error {
}
}
+ // If previously existing pairs with the wrong case exist, delete them
+ for _, prev_pair := range previous_pairs {
+ if strings.EqualFold(prev_pair.Key, path) && prev_pair.Key != path {
+ _, err := server.kv.Delete(prev_pair.Key, nil)
+ if err != nil {
+ return err
+ }
+ }
+ }
+
// If we have zero values, delete associated k/v pair
// Otherwise, write new values
if len(values) == 0 {