diff --git a/changelog/18273.txt b/changelog/18273.txt new file mode 100644 index 000000000..46033c782 --- /dev/null +++ b/changelog/18273.txt @@ -0,0 +1,3 @@ +```release-note:bug +core/quotas: Fix issue with improper application of default rate limit quota exempt paths +``` \ No newline at end of file diff --git a/vault/external_tests/quotas/quotas_test.go b/vault/external_tests/quotas/quotas_test.go index 0dc5c4117..0456759cc 100644 --- a/vault/external_tests/quotas/quotas_test.go +++ b/vault/external_tests/quotas/quotas_test.go @@ -253,6 +253,37 @@ func TestQuotas_RateLimitQuota_ExemptPaths(t *testing.T) { require.Zero(t, numFail) } +func TestQuotas_RateLimitQuota_DefaultExemptPaths(t *testing.T) { + conf, opts := teststorage.ClusterSetup(coreConfig, nil, nil) + opts.NoDefaultQuotas = true + + cluster := vault.NewTestCluster(t, conf, opts) + cluster.Start() + defer cluster.Cleanup() + + core := cluster.Cores[0].Core + client := cluster.Cores[0].Client + vault.TestWaitActive(t, core) + + _, err := client.Logical().Write("sys/quotas/rate-limit/rlq", map[string]interface{}{ + "rate": 1, + }) + require.NoError(t, err) + + resp, err := client.Logical().Read("sys/health") + require.NoError(t, err) + require.NotNil(t, resp) + require.NotNil(t, resp.Data) + + // The second sys/health call should not fail as /v1/sys/health is + // part of the default exempt paths + resp, err = client.Logical().Read("sys/health") + require.NoError(t, err) + // If the response is nil, then we are being rate limited + require.NotNil(t, resp) + require.NotNil(t, resp.Data) +} + func TestQuotas_RateLimitQuota_Mount(t *testing.T) { conf, opts := teststorage.ClusterSetup(coreConfig, nil, nil) cluster := vault.NewTestCluster(t, conf, opts) diff --git a/vault/quotas/quotas.go b/vault/quotas/quotas.go index dde756e1e..deb2d352f 100644 --- a/vault/quotas/quotas.go +++ b/vault/quotas/quotas.go @@ -117,13 +117,13 @@ var ( ) var defaultExemptPaths = []string{ - "/v1/sys/generate-recovery-token/attempt", - "/v1/sys/generate-recovery-token/update", - "/v1/sys/generate-root/attempt", - "/v1/sys/generate-root/update", - "/v1/sys/health", - "/v1/sys/seal-status", - "/v1/sys/unseal", + "sys/generate-recovery-token/attempt", + "sys/generate-recovery-token/update", + "sys/generate-root/attempt", + "sys/generate-root/update", + "sys/health", + "sys/seal-status", + "sys/unseal", } // Access provides information to reach back to the quota checker. @@ -724,15 +724,6 @@ func (m *Manager) RateLimitResponseHeadersEnabled() bool { return m.config.EnableRateLimitResponseHeaders } -// RateLimitExemptPaths returns the list of exempt paths from all rate limit -// resource quotas from the Manager's configuration. -func (m *Manager) RateLimitExemptPaths() []string { - m.quotaConfigLock.RLock() - defer m.quotaConfigLock.RUnlock() - - return m.config.RateLimitExemptPaths -} - // RateLimitPathExempt returns a boolean dictating if a given path is exempt from // any rate limit quota. If not rate limit path manager is defined, false is // returned. diff --git a/website/content/docs/concepts/resource-quotas.mdx b/website/content/docs/concepts/resource-quotas.mdx index 0408612a9..a06cd19f1 100644 --- a/website/content/docs/concepts/resource-quotas.mdx +++ b/website/content/docs/concepts/resource-quotas.mdx @@ -58,13 +58,13 @@ By default, the following paths are exempt from rate limiting. However, Vault operators can override the set of paths that are exempt from all rate limit resource quotas by updating the `rate_limit_exempt_paths` configuration field. -- `/v1/sys/generate-recovery-token/attempt` -- `/v1/sys/generate-recovery-token/update` -- `/v1/sys/generate-root/attempt` -- `/v1/sys/generate-root/update` -- `/v1/sys/health` -- `/v1/sys/seal-status` -- `/v1/sys/unseal` +- `sys/generate-recovery-token/attempt` +- `sys/generate-recovery-token/update` +- `sys/generate-root/attempt` +- `sys/generate-root/update` +- `sys/health` +- `sys/seal-status` +- `sys/unseal` ## Tutorial