// SanitizePolicies performs the common input validation tasks // which are performed on the list of policies across Vault. // The resulting collection will have no duplicate elements. // If 'root' policy was present in the list of policies, then // all other policies will be ignored, the result will contain // just the 'root'. In cases where 'root' is not present, if // 'default' policy is not already present, it will be added // if addDefault is set to true. func SanitizePolicies(policies []string, addDefault bool) []string { defaultFound := false for i, p := range policies { policies[i] = strings.ToLower(strings.TrimSpace(p)) // Eliminate unnamed policies. if policies[i] == "" { continue } // If 'root' policy is present, ignore all other policies. if policies[i] == "root" { policies = []string{"root"} defaultFound = true break } if policies[i] == "default" { defaultFound = true } } // Always add 'default' except only if the policies contain 'root'. if addDefault && (len(policies) == 0 || !defaultFound) { policies = append(policies, "default") } return strutil.RemoveDuplicates(policies) }
func (b *backend) Login(req *logical.Request, username string, password string) ([]string, *logical.Response, error) { cfg, err := b.Config(req) if err != nil { return nil, nil, err } if cfg == nil { return nil, logical.ErrorResponse("ldap backend not configured"), nil } c, err := cfg.DialLDAP() if err != nil { return nil, logical.ErrorResponse(err.Error()), nil } if c == nil { return nil, logical.ErrorResponse("invalid connection returned from LDAP dial"), nil } bindDN, err := b.getBindDN(cfg, c, username) if err != nil { return nil, logical.ErrorResponse(err.Error()), nil } if b.Logger().IsDebug() { b.Logger().Debug("auth/ldap: BindDN fetched", "username", username, "binddn", bindDN) } // Try to bind as the login user. This is where the actual authentication takes place. if err = c.Bind(bindDN, password); err != nil { return nil, logical.ErrorResponse(fmt.Sprintf("LDAP bind failed: %v", err)), nil } userDN, err := b.getUserDN(cfg, c, bindDN) if err != nil { return nil, logical.ErrorResponse(err.Error()), nil } ldapGroups, err := b.getLdapGroups(cfg, c, userDN, username) if err != nil { return nil, logical.ErrorResponse(err.Error()), nil } if b.Logger().IsDebug() { b.Logger().Debug("auth/ldap: Groups fetched from server", "num_server_groups", len(ldapGroups), "server_groups", ldapGroups) } ldapResponse := &logical.Response{ Data: map[string]interface{}{}, } if len(ldapGroups) == 0 { errString := fmt.Sprintf( "no LDAP groups found in groupDN '%s'; only policies from locally-defined groups available", cfg.GroupDN) ldapResponse.AddWarning(errString) } var allGroups []string // Import the custom added groups from ldap backend user, err := b.User(req.Storage, username) if err == nil && user != nil && user.Groups != nil { if b.Logger().IsDebug() { b.Logger().Debug("auth/ldap: adding local groups", "num_local_groups", len(user.Groups), "local_groups", user.Groups) } allGroups = append(allGroups, user.Groups...) } // Merge local and LDAP groups allGroups = append(allGroups, ldapGroups...) // Retrieve policies var policies []string for _, groupName := range allGroups { group, err := b.Group(req.Storage, groupName) if err == nil && group != nil { policies = append(policies, group.Policies...) } } // Policies from each group may overlap policies = strutil.RemoveDuplicates(policies) if len(policies) == 0 { errStr := "user is not a member of any authorized group" if len(ldapResponse.Warnings()) > 0 { errStr = fmt.Sprintf("%s; additionally, %s", errStr, ldapResponse.Warnings()[0]) } ldapResponse.Data["error"] = errStr return nil, ldapResponse, nil } return policies, ldapResponse, nil }