open-vault/vault/quotas/quotas_test.go

120 lines
5.0 KiB
Go

// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package quotas
import (
"context"
"testing"
"time"
"github.com/go-test/deep"
log "github.com/hashicorp/go-hclog"
"github.com/hashicorp/vault/helper/metricsutil"
"github.com/hashicorp/vault/sdk/helper/logging"
"github.com/stretchr/testify/require"
)
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().(*RateLimitQuota)
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)
}
func TestQuotas_Precedence(t *testing.T) {
qm, err := NewManager(logging.NewVaultLogger(log.Trace), nil, metricsutil.BlackholeSink())
require.NoError(t, err)
setQuotaFunc := func(t *testing.T, name, nsPath, mountPath, pathSuffix, role string) Quota {
t.Helper()
quota := NewRateLimitQuota(name, nsPath, mountPath, pathSuffix, role, 10, time.Second, 0)
require.NoError(t, qm.SetQuota(context.Background(), TypeRateLimit.String(), quota, true))
return quota
}
checkQuotaFunc := func(t *testing.T, nsPath, mountPath, pathSuffix, role string, expected Quota) {
t.Helper()
quota, err := qm.QueryQuota(&Request{
Type: TypeRateLimit,
NamespacePath: nsPath,
MountPath: mountPath,
Role: role,
Path: nsPath + mountPath + pathSuffix,
})
require.NoError(t, err)
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 global mount + path specific quota and expect that to be returned.
rateLimitGlobalMountPathQuota := setQuotaFunc(t, "rateLimitGlobalMountPathQuota", "", "testmount/", "testpath", "")
checkQuotaFunc(t, "", "testmount/", "testpath", "", rateLimitGlobalMountPathQuota)
// 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/", "testpath", "", rateLimitNSMountQuota)
// Define a namespace mount + glob and expect that to be returned.
rateLimitNSMountGlob := setQuotaFunc(t, "rateLimitNSMountGlob", "testns/", "testmount/", "*", "")
checkQuotaFunc(t, "testns/", "testmount/", "testpath", "", rateLimitNSMountGlob)
// Define a namespace mount + path specific quota with a glob and expect that to be returned.
rateLimitNSMountPathSuffixGlob := setQuotaFunc(t, "rateLimitNSMountPathSuffixGlob", "testns/", "testmount/", "test*", "")
checkQuotaFunc(t, "testns/", "testmount/", "testpath", "", rateLimitNSMountPathSuffixGlob)
// Define a namespace mount + path specific quota with a glob at the end of the path and expect that to be returned.
rateLimitNSMountPathSuffixGlobAfterPath := setQuotaFunc(t, "rateLimitNSMountPathSuffixGlobAfterPath", "testns/", "testmount/", "testpath*", "")
checkQuotaFunc(t, "testns/", "testmount/", "testpath", "", rateLimitNSMountPathSuffixGlobAfterPath)
// Define a namespace mount + path specific quota and expect that to be returned.
rateLimitNSMountPathQuota := setQuotaFunc(t, "rateLimitNSMountPathQuota", "testns/", "testmount/", "testpath", "")
checkQuotaFunc(t, "testns/", "testmount/", "testpath", "", rateLimitNSMountPathQuota)
// Define a namespace mount + role specific quota and expect that to be returned.
rateLimitNSMountRoleQuota := setQuotaFunc(t, "rateLimitNSMountPathQuota", "testns/", "testmount/", "", "role")
checkQuotaFunc(t, "testns/", "testmount/", "", "role", rateLimitNSMountRoleQuota)
// Now that many quota types are defined, verify that the most specific
// matches are returned per namespace.
checkQuotaFunc(t, "", "", "", "", rateLimitGlobalQuota)
checkQuotaFunc(t, "testns/", "", "", "", rateLimitNSQuota)
}