forked from Deuxfleurs/bottin
Refactor & add case normalization logic to putAttributes
This commit is contained in:
parent
1a20a64eff
commit
99d8955ab3
4 changed files with 87 additions and 46 deletions
2
main.go
2
main.go
|
@ -74,8 +74,6 @@ type State struct {
|
||||||
login Login
|
login Login
|
||||||
}
|
}
|
||||||
|
|
||||||
type Entry map[string][]string
|
|
||||||
|
|
||||||
var configFlag = flag.String("config", "./config.json", "Configuration file path")
|
var configFlag = flag.String("config", "./config.json", "Configuration file path")
|
||||||
var resyncFlag = flag.Bool("resync", false, "Check and re-synchronize memberOf values before launch")
|
var resyncFlag = flag.Bool("resync", false, "Check and re-synchronize memberOf values before launch")
|
||||||
|
|
||||||
|
|
3
read.go
3
read.go
|
@ -17,11 +17,14 @@ func (server *Server) getAttribute(dn string, attr string) ([]string, error) {
|
||||||
return nil, err
|
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)
|
pairs, _, err := server.kv.List(path+"/attribute=", &server.readOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Collect values for the attribute, case-insensitively
|
||||||
values := []string{}
|
values := []string{}
|
||||||
for _, pair := range pairs {
|
for _, pair := range pairs {
|
||||||
if strings.EqualFold(pair.Key, path+"/attribute="+attr) {
|
if strings.EqualFold(pair.Key, path+"/attribute="+attr) {
|
||||||
|
|
92
util.go
92
util.go
|
@ -11,6 +11,13 @@ import (
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DNs ----
|
||||||
|
|
||||||
|
type dnComponent struct {
|
||||||
|
Type string
|
||||||
|
Value string
|
||||||
|
}
|
||||||
|
|
||||||
func dnToConsul(dn string) (string, error) {
|
func dnToConsul(dn string) (string, error) {
|
||||||
if strings.Contains(dn, "/") {
|
if strings.Contains(dn, "/") {
|
||||||
return "", fmt.Errorf("DN %s contains a /", 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)
|
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) {
|
func parseValue(value []byte) ([]string, error) {
|
||||||
val := []string{}
|
val := []string{}
|
||||||
err := json.Unmarshal(value, &val)
|
err := json.Unmarshal(value, &val)
|
||||||
|
@ -82,49 +131,6 @@ func parseConsulResult(data []*consul.KVPair) (map[string]Entry, error) {
|
||||||
return aggregator, nil
|
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 {
|
func checkRestrictedAttr(attr string) error {
|
||||||
RESTRICTED_ATTRS := []string{
|
RESTRICTED_ATTRS := []string{
|
||||||
ATTR_MEMBEROF,
|
ATTR_MEMBEROF,
|
||||||
|
|
36
write.go
36
write.go
|
@ -19,7 +19,31 @@ func (server *Server) putAttributes(dn string, attrs Entry) error {
|
||||||
return err
|
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
|
path := prefix + "/attribute=" + k
|
||||||
|
|
||||||
// Trim spaces and remove empty values
|
// 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
|
// If we have zero values, delete associated k/v pair
|
||||||
// Otherwise, write new values
|
// Otherwise, write new values
|
||||||
if len(values) == 0 {
|
if len(values) == 0 {
|
||||||
|
|
Loading…
Reference in a new issue