2020-06-26 21:13:16 +00:00
|
|
|
package quotas
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"testing"
|
2020-07-29 19:15:05 +00:00
|
|
|
"time"
|
2020-06-26 21:13:16 +00:00
|
|
|
|
|
|
|
"github.com/go-test/deep"
|
|
|
|
log "github.com/hashicorp/go-hclog"
|
2020-10-13 23:38:21 +00:00
|
|
|
"github.com/hashicorp/vault/helper/metricsutil"
|
2020-06-26 21:13:16 +00:00
|
|
|
"github.com/hashicorp/vault/sdk/helper/logging"
|
2020-07-29 19:15:05 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
2020-06-26 21:13:16 +00:00
|
|
|
)
|
|
|
|
|
2021-02-09 10:46:09 +00:00
|
|
|
func TestQuotas_MountPathOverwrite(t *testing.T) {
|
|
|
|
qm, err := NewManager(logging.NewVaultLogger(log.Trace), nil, metricsutil.BlackholeSink())
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
quota := NewRateLimitQuota("tq", "", "kv1/", 10, time.Second, 0)
|
|
|
|
require.NoError(t, qm.SetQuota(context.Background(), TypeRateLimit.String(), quota, false))
|
|
|
|
quota = quota.Clone()
|
|
|
|
quota.MountPath = "kv2/"
|
|
|
|
require.NoError(t, qm.SetQuota(context.Background(), TypeRateLimit.String(), quota, false))
|
|
|
|
|
|
|
|
q, err := qm.QueryQuota(&Request{
|
|
|
|
Type: TypeRateLimit,
|
|
|
|
MountPath: "kv1/",
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Nil(t, q)
|
|
|
|
|
|
|
|
require.NoError(t, qm.DeleteQuota(context.Background(), TypeRateLimit.String(), "tq"))
|
|
|
|
|
|
|
|
q, err = qm.QueryQuota(&Request{
|
|
|
|
Type: TypeRateLimit,
|
|
|
|
MountPath: "kv1/",
|
|
|
|
})
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Nil(t, q)
|
|
|
|
}
|
|
|
|
|
2020-06-26 21:13:16 +00:00
|
|
|
func TestQuotas_Precedence(t *testing.T) {
|
|
|
|
qm, err := NewManager(logging.NewVaultLogger(log.Trace), nil, metricsutil.BlackholeSink())
|
2020-07-29 19:15:05 +00:00
|
|
|
require.NoError(t, err)
|
2020-06-26 21:13:16 +00:00
|
|
|
|
|
|
|
setQuotaFunc := func(t *testing.T, name, nsPath, mountPath string) Quota {
|
|
|
|
t.Helper()
|
2020-08-17 02:09:18 +00:00
|
|
|
quota := NewRateLimitQuota(name, nsPath, mountPath, 10, time.Second, 0)
|
2020-07-29 19:15:05 +00:00
|
|
|
require.NoError(t, qm.SetQuota(context.Background(), TypeRateLimit.String(), quota, true))
|
2020-06-26 21:13:16 +00:00
|
|
|
return quota
|
|
|
|
}
|
|
|
|
|
|
|
|
checkQuotaFunc := func(t *testing.T, nsPath, mountPath string, expected Quota) {
|
|
|
|
t.Helper()
|
2020-07-13 18:42:39 +00:00
|
|
|
quota, err := qm.QueryQuota(&Request{
|
2020-06-26 21:13:16 +00:00
|
|
|
Type: TypeRateLimit,
|
|
|
|
NamespacePath: nsPath,
|
|
|
|
MountPath: mountPath,
|
|
|
|
})
|
2020-07-29 19:15:05 +00:00
|
|
|
require.NoError(t, err)
|
|
|
|
|
2020-06-26 21:13:16 +00:00
|
|
|
if diff := deep.Equal(expected, quota); len(diff) > 0 {
|
|
|
|
t.Fatal(diff)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// No quota present. Expect nil.
|
|
|
|
checkQuotaFunc(t, "", "", nil)
|
|
|
|
|
|
|
|
// Define global quota and expect that to be returned.
|
|
|
|
rateLimitGlobalQuota := setQuotaFunc(t, "rateLimitGlobalQuota", "", "")
|
|
|
|
checkQuotaFunc(t, "", "", rateLimitGlobalQuota)
|
|
|
|
|
|
|
|
// Define a global mount specific quota and expect that to be returned.
|
|
|
|
rateLimitGlobalMountQuota := setQuotaFunc(t, "rateLimitGlobalMountQuota", "", "testmount")
|
|
|
|
checkQuotaFunc(t, "", "testmount", rateLimitGlobalMountQuota)
|
|
|
|
|
|
|
|
// Define a namespace quota and expect that to be returned.
|
|
|
|
rateLimitNSQuota := setQuotaFunc(t, "rateLimitNSQuota", "testns", "")
|
|
|
|
checkQuotaFunc(t, "testns", "", rateLimitNSQuota)
|
|
|
|
|
|
|
|
// Define a namespace mount specific quota and expect that to be returned.
|
|
|
|
rateLimitNSMountQuota := setQuotaFunc(t, "rateLimitNSMountQuota", "testns", "testmount")
|
|
|
|
checkQuotaFunc(t, "testns", "testmount", rateLimitNSMountQuota)
|
|
|
|
|
|
|
|
// Now that many quota types are defined, verify that the most specific
|
|
|
|
// matches are returned per namespace.
|
|
|
|
checkQuotaFunc(t, "", "", rateLimitGlobalQuota)
|
|
|
|
checkQuotaFunc(t, "testns", "", rateLimitNSQuota)
|
|
|
|
}
|