agent/caching: test renaming; add api-level cache-clear test (#6305)

* test renaming; add api-level cache-clear test

* fix import ordering
This commit is contained in:
Calvin Leung Huang 2019-02-28 10:05:55 -08:00 committed by Brian Kassouf
parent 4ecaa1b597
commit 5eb50a261e
4 changed files with 150 additions and 12 deletions

View file

@ -10,7 +10,7 @@ import (
"github.com/hashicorp/vault/helper/namespace"
)
func TestCache_APIProxy(t *testing.T) {
func TestAPIProxy(t *testing.T) {
cleanup, client, _, _ := setupClusterAndAgent(namespace.RootContext(nil), t, nil)
defer cleanup()

View file

@ -3,6 +3,7 @@ package cache
import (
"context"
"fmt"
"io"
"io/ioutil"
"math/rand"
"net"
@ -18,6 +19,7 @@ import (
kv "github.com/hashicorp/vault-plugin-secrets-kv"
"github.com/hashicorp/vault/api"
"github.com/hashicorp/vault/builtin/credential/userpass"
"github.com/hashicorp/vault/command/agent/cache/cachememdb"
"github.com/hashicorp/vault/command/agent/sink/mock"
"github.com/hashicorp/vault/helper/consts"
"github.com/hashicorp/vault/helper/logging"
@ -50,13 +52,12 @@ func setupClusterAndAgent(ctx context.Context, t *testing.T, coreConfig *vault.C
DisableMlock: true,
DisableCache: true,
Logger: logging.NewVaultLogger(hclog.Trace),
CredentialBackends: map[string]logical.Factory{
"userpass": userpass.Factory,
},
}
}
if coreConfig.CredentialBackends == nil {
// Always set up the userpass backend since we use that to generate an admin
// token for the client that will make proxied requests to through the agent.
if coreConfig.CredentialBackends == nil || coreConfig.CredentialBackends["userpass"] == nil {
coreConfig.CredentialBackends = map[string]logical.Factory{
"userpass": userpass.Factory,
}
@ -935,7 +936,7 @@ func TestCache_NonCacheable(t *testing.T) {
}
}
func TestCache_AuthResponse(t *testing.T) {
func TestCache_Caching_AuthResponse(t *testing.T) {
cleanup, _, testClient, _ := setupClusterAndAgent(namespace.RootContext(nil), t, nil)
defer cleanup()
@ -985,7 +986,7 @@ func TestCache_AuthResponse(t *testing.T) {
}
}
func TestCache_LeaseResponse(t *testing.T) {
func TestCache_Caching_LeaseResponse(t *testing.T) {
coreConfig := &vault.CoreConfig{
DisableMlock: true,
DisableCache: true,
@ -1064,3 +1065,132 @@ func TestCache_LeaseResponse(t *testing.T) {
}
}
}
func TestCache_Caching_CacheClear(t *testing.T) {
t.Run("request_path", func(t *testing.T) {
testCachingCacheClearCommon(t, "request_path")
})
t.Run("lease", func(t *testing.T) {
testCachingCacheClearCommon(t, "lease")
})
t.Run("token", func(t *testing.T) {
testCachingCacheClearCommon(t, "token")
})
t.Run("token_accessor", func(t *testing.T) {
testCachingCacheClearCommon(t, "token_accessor")
})
t.Run("all", func(t *testing.T) {
testCachingCacheClearCommon(t, "all")
})
}
func testCachingCacheClearCommon(t *testing.T, clearType string) {
coreConfig := &vault.CoreConfig{
DisableMlock: true,
DisableCache: true,
Logger: hclog.NewNullLogger(),
LogicalBackends: map[string]logical.Factory{
"kv": vault.LeasedPassthroughBackendFactory,
},
}
cleanup, client, testClient, leaseCache := setupClusterAndAgent(namespace.RootContext(nil), t, coreConfig)
defer cleanup()
err := client.Sys().Mount("kv", &api.MountInput{
Type: "kv",
})
if err != nil {
t.Fatal(err)
}
// Write data to the lease-kv backend
_, err = testClient.Logical().Write("kv/foo", map[string]interface{}{
"value": "bar",
"ttl": "1h",
})
if err != nil {
t.Fatal(err)
}
// Proxy this request, agent should cache the response
resp, err := testClient.Logical().Read("kv/foo")
if err != nil {
t.Fatal(err)
}
gotLeaseID := resp.LeaseID
// Verify the entry exists
idx, err := leaseCache.db.Get(cachememdb.IndexNameLease, gotLeaseID)
if err != nil {
t.Fatal(err)
}
if idx == nil {
t.Fatalf("expected cached entry, got: %v", idx)
}
data := map[string]interface{}{
"type": clearType,
}
// We need to set the value here depending on what we're trying to test.
// Some values are be static, but others are dynamically generated at runtime.
switch clearType {
case "request_path":
data["value"] = "/v1/kv/foo"
case "lease":
data["value"] = resp.LeaseID
case "token":
data["value"] = testClient.Token()
case "token_accessor":
lookupResp, err := client.Auth().Token().Lookup(testClient.Token())
if err != nil {
t.Fatal(err)
}
data["value"] = lookupResp.Data["accessor"]
case "all":
default:
t.Fatalf("invalid type provided: %v", clearType)
}
r := testClient.NewRequest("PUT", consts.AgentPathCacheClear)
if err := r.SetJSONBody(data); err != nil {
t.Fatal(err)
}
ctx, cancelFunc := context.WithCancel(context.Background())
defer cancelFunc()
apiResp, err := testClient.RawRequestWithContext(ctx, r)
if resp != nil {
defer apiResp.Body.Close()
}
if apiResp != nil && apiResp.StatusCode == 404 {
_, parseErr := api.ParseSecret(apiResp.Body)
switch parseErr {
case nil:
case io.EOF:
default:
t.Fatal(err)
}
}
if err != nil {
t.Fatal(err)
}
time.Sleep(100 * time.Millisecond)
// Verify the entry is cleared
idx, err = leaseCache.db.Get(cachememdb.IndexNameLease, gotLeaseID)
if err != nil {
t.Fatal(err)
}
if idx != nil {
t.Fatalf("expected entry to be nil, got: %v", idx)
}
}

View file

@ -411,6 +411,14 @@ func computeIndexID(req *SendRequest) (string, error) {
// HandleCacheClear returns a handlerFunc that can perform cache clearing operations.
func (c *LeaseCache) HandleCacheClear(ctx context.Context) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Only handle POST/PUT requests
switch r.Method {
case http.MethodPost:
case http.MethodPut:
default:
return
}
req := new(cacheClearRequest)
if err := jsonutil.DecodeJSONFromReader(r.Body, req); err != nil {
if err == io.EOF {

View file

@ -76,7 +76,7 @@ func TestCache_ComputeIndexID(t *testing.T) {
}
}
func TestCache_LeaseCache_EmptyToken(t *testing.T) {
func TestLeaseCache_EmptyToken(t *testing.T) {
responses := []*SendResponse{
&SendResponse{
Response: &api.Response{
@ -106,7 +106,7 @@ func TestCache_LeaseCache_EmptyToken(t *testing.T) {
}
}
func TestCache_LeaseCache_SendCacheable(t *testing.T) {
func TestLeaseCache_SendCacheable(t *testing.T) {
// Emulate 2 responses from the api proxy. One returns a new token and the
// other returns a lease.
responses := []*SendResponse{
@ -187,7 +187,7 @@ func TestCache_LeaseCache_SendCacheable(t *testing.T) {
}
}
func TestCache_LeaseCache_SendNonCacheable(t *testing.T) {
func TesteaseCache_SendNonCacheable(t *testing.T) {
responses := []*SendResponse{
&SendResponse{
Response: &api.Response{
@ -236,7 +236,7 @@ func TestCache_LeaseCache_SendNonCacheable(t *testing.T) {
}
}
func TestCache_LeaseCache_SendNonCacheableNonTokenLease(t *testing.T) {
func TestLeaseCache_SendNonCacheableNonTokenLease(t *testing.T) {
// Create the cache
responses := []*SendResponse{
&SendResponse{
@ -291,7 +291,7 @@ func TestCache_LeaseCache_SendNonCacheableNonTokenLease(t *testing.T) {
}
}
func TestCache_LeaseCache_HandleCacheClear(t *testing.T) {
func TestLeaseCache_HandleCacheClear(t *testing.T) {
lc := testNewLeaseCache(t, nil)
handler := lc.HandleCacheClear(context.Background())