rambler-oss/keyreader

View on GitHub
access.go

Summary

Maintainability
A
0 mins
Test Coverage
C
72%
package main

import (
    "strings"

    u "github.com/iavael/goutil"
    "gopkg.in/ldap.v2"
)

// TrustModel type
type TrustModel uint8

const (
    tmFull TrustModel = iota
    tmHost
    tmDeny
)

type hostInterface interface {
    inNetGroups([]string) bool
    matchACL(string) bool
}

// Host struct
type Host struct {
    names []string
}

func (h Host) matchACL(acl string) bool {
    debugLog("Search ACL %s in hosts", acl)
    result := u.MemberOfSlice(acl, h.names)
    if result {
        debugLog("ACL %s found in hosts", acl)
    } else {
        debugLog("ACL %s not found in hosts", acl)
    }
    return result
}

func checkAccess(user string, host hostInterface, entries []*ldap.Entry) bool {

    debugLog("Checking ACLs and getting trustModel")
    var (
        tmodel TrustModel
    )

    for _, entry := range entries {
        debugLog("Checking %s", entry.DN)
        if tm := entry.GetAttributeValues("trustModel"); len(tm) > 1 {
            logger.Warn("More than 1 trustModel attribute in DN %s, skipping", entry.DN)
            continue
        } else if len(tm) == 1 {
            switch strings.ToLower(tm[0]) {
            case "fullaccess":
                debugLog("TrustModel is 'FullAccess'")
                tmodel = tmFull
            case "byhost":
                debugLog("TrustModel is 'ByHost'")
                tmodel = tmHost
            case "deny":
                tmodel = tmDeny
            default:
                logger.Warn("Unknown trustmodel \"%s\" in DN %s, assuming \"ByHost\"", tm[0], entry.DN)
            }
        } else {
            debugLog("Unknown trustmodel in DN %s, assuming \"ByHost\"", entry.DN)
            tmodel = tmHost
        }

        if tmodel == tmDeny {
            logger.Info("User %s has 'deny' trustmodel", user)
            return false
        }
        if tmodel == tmFull {
            logger.Info("Granting access to user %s by trustmodel \"FullAccess\"", user)
            return true
        }

        if tmodel == tmHost {
            if checkByHost(user, entry, host) {
                return true
            }
        }
    }
    debugLog("Access denied: Unknown trustModel")
    return false
}

func checkByHost(user string, entry *ldap.Entry, host hostInterface) bool {
    var netgroups []string
    debugLog("Checking ACL")
    for _, acl := range entry.GetAttributeValues("accessTo") {
        if strings.HasPrefix(acl, "+") {
            netgroups = append(netgroups, acl[1:])
        } else if host.matchACL(acl) {
            logger.Info("Granting access to user %s by trustmodel \"ByHost\"", user)
            return true
        }
    }

    debugLog("Host was not found in ACL")
    if host.inNetGroups(netgroups) {
        logger.Info("Granting access to user %s by trustmodel \"ByHost\"", user)
        return true
    }
    debugLog("Host not found in netgroups, access denied")
    return false
}