Backport of Add Configurable LDAP Max Page Size into release/1.13.x (#20283)

* Add Configurable LDAP Max Page Size (#19032)

* Add config flag for LDAP max page size

* Add changelog

* move changelog to correct file

* cleanup

* Default to non-paged searching for with -1

* Update website/content/api-docs/auth/ldap.mdx

Co-authored-by: Austin Gebauer <34121980+austingebauer@users.noreply.github.com>

* Update website/content/docs/auth/ldap.mdx

Co-authored-by: Austin Gebauer <34121980+austingebauer@users.noreply.github.com>

* Update tests

---------

Co-authored-by: Austin Gebauer <34121980+austingebauer@users.noreply.github.com>

* remove

---------

Co-authored-by: Luis (LT) Carbonell <lt.carbonell@hashicorp.com>
Co-authored-by: Austin Gebauer <34121980+austingebauer@users.noreply.github.com>
This commit is contained in:
hc-github-team-secure-vault-core
2023-04-20 18:07:15 -04:00
committed by GitHub
parent 7dcb2ba989
commit fc1bbf436f
8 changed files with 33 additions and 6 deletions

View File

@@ -1194,6 +1194,7 @@ func TestLdapAuthBackend_ConfigUpgrade(t *testing.T) {
"token_period": "5m",
"token_explicit_max_ttl": "24h",
"request_timeout": cfg.RequestTimeout,
"max_page_size": cfg.MaximumPageSize,
"connection_timeout": cfg.ConnectionTimeout,
},
Storage: storage,
@@ -1238,6 +1239,7 @@ func TestLdapAuthBackend_ConfigUpgrade(t *testing.T) {
RequestTimeout: cfg.RequestTimeout,
ConnectionTimeout: cfg.ConnectionTimeout,
UsernameAsAlias: false,
MaximumPageSize: 1000,
},
}

3
changelog/19032.txt Normal file
View File

@@ -0,0 +1,3 @@
```release-note:bug
auth/ldap: Add max_page_size configurable to LDAP configuration
```

View File

@@ -33,6 +33,7 @@ func PrepareTestContainer(t *testing.T, version string) (cleanup func(), cfg *ld
cfg.GroupDN = "ou=people,dc=planetexpress,dc=com"
cfg.GroupAttr = "cn"
cfg.RequestTimeout = 60
cfg.MaximumPageSize = 1000
svc, err := runner.StartService(context.Background(), func(ctx context.Context, host string, port int) (docker.ServiceConfig, error) {
connURL := fmt.Sprintf("ldap://%s:%d", host, port)

View File

@@ -417,7 +417,7 @@ func (c *Client) performLdapFilterGroupsSearchPaging(cfg *ConfigEntry, conn Pagi
cfg.GroupAttr,
},
SizeLimit: math.MaxInt32,
}, math.MaxInt32)
}, uint32(cfg.MaximumPageSize))
if err != nil {
return nil, fmt.Errorf("LDAP search failed: %w", err)
}
@@ -536,7 +536,7 @@ func (c *Client) GetLdapGroups(cfg *ConfigEntry, conn Connection, userDN string,
if cfg.UseTokenGroups {
entries, err = c.performLdapTokenGroupsSearch(cfg, conn, userDN)
} else {
if paging, ok := conn.(PagingConnection); ok {
if paging, ok := conn.(PagingConnection); ok && cfg.MaximumPageSize >= 0 {
entries, err = c.performLdapFilterGroupsSearchPaging(cfg, paging, userDN, username)
} else {
entries, err = c.performLdapFilterGroupsSearch(cfg, conn, userDN, username)

View File

@@ -6,6 +6,7 @@ import (
"encoding/pem"
"errors"
"fmt"
"math"
"strings"
"text/template"
@@ -232,6 +233,12 @@ Default: ({{.UserAttr}}={{.Username}})`,
Description: "Timeout, in seconds, when attempting to connect to the LDAP server before trying the next URL in the configuration.",
Default: "30s",
},
"max_page_size": {
Type: framework.TypeInt,
Description: "The maximum number of results to return for a single paged query. If not set, the server default will be used for paged searches. A requested max_page_size of 0 is interpreted as no limit by LDAP servers. If set to a negative value, search requests will not be paged.",
Default: math.MaxInt32,
},
}
}
@@ -402,6 +409,10 @@ func NewConfigEntry(existing *ConfigEntry, d *framework.FieldData) (*ConfigEntry
cfg.ConnectionTimeout = d.Get("connection_timeout").(int)
}
if _, ok := d.Raw["max_page_size"]; ok || !hadExisting {
cfg.MaximumPageSize = d.Get("max_page_size").(int)
}
return cfg, nil
}
@@ -429,6 +440,7 @@ type ConfigEntry struct {
UsePre111GroupCNBehavior *bool `json:"use_pre111_group_cn_behavior"`
RequestTimeout int `json:"request_timeout"`
ConnectionTimeout int `json:"connection_timeout"`
MaximumPageSize int `json:"max_page_size"`
// These json tags deviate from snake case because there was a past issue
// where the tag was being ignored, causing it to be jsonified as "CaseSensitiveNames", etc.
@@ -468,6 +480,7 @@ func (c *ConfigEntry) PasswordlessMap() map[string]interface{} {
"request_timeout": c.RequestTimeout,
"connection_timeout": c.ConnectionTimeout,
"username_as_alias": c.UsernameAsAlias,
"max_page_size": c.MaximumPageSize,
}
if c.CaseSensitiveNames != nil {
m["case_sensitive_names"] = *c.CaseSensitiveNames

View File

@@ -171,6 +171,7 @@ var jsonConfigDefault = []byte(`
"username_as_alias": false,
"request_timeout": 90,
"connection_timeout": 30,
"max_page_size": 2147483647,
"CaseSensitiveNames": false,
"ClientTLSCert": "",
"ClientTLSKey": ""

View File

@@ -94,6 +94,12 @@ This endpoint configures the LDAP auth method.
returning _user_ objects, use: `memberOf`. The default is `cn`.
- `username_as_alias` `(bool: false)` - If set to true, forces the auth method
to use the username passed by the user as the alias name.
- `max_page_size` `(int: math.MaxInt32)` - If set to a value greater than 0, the LDAP
backend will use the LDAP server's paged search control to request pages of
up to the given size. This can be used to avoid hitting the LDAP server's
maximum result size limit. A value of 0 will be interpreted by the LDAP
server as unlimited. If set to -1, the LDAP backend will not use the
paged search control.
@include 'tokenfields.mdx'
@@ -126,7 +132,8 @@ $ curl \
"url": "ldaps://ldap.myorg.com:636",
"username_as_alias": false,
"userattr": "samaccountname",
"userdn": "ou=Users,dc=example,dc=com"
"userdn": "ou=Users,dc=example,dc=com",
"max_page_size": 1000
}
```

View File

@@ -152,7 +152,7 @@ Use `vault path-help` for more details.
### Other
- `username_as_alias` (bool, optional) - If set to true, forces the auth method to use the username passed by the user as the alias name.
- `max_page_size` (int, optional) - The maximum number of results to return for a single LDAP query. This is useful for preventing large queries from being run against the LDAP server. The default is the maximum value for an int32.
## Examples: