2023-03-15 16:00:52 +00:00
|
|
|
// Copyright (c) HashiCorp, Inc.
|
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
2019-02-15 01:10:36 +00:00
|
|
|
package cache
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2019-03-07 01:23:20 +00:00
|
|
|
"encoding/json"
|
2019-02-15 01:10:36 +00:00
|
|
|
"fmt"
|
2019-03-07 01:23:20 +00:00
|
|
|
"io/ioutil"
|
2021-01-26 20:09:37 +00:00
|
|
|
"math/rand"
|
2019-03-07 01:23:20 +00:00
|
|
|
"net/http"
|
|
|
|
"strings"
|
2019-03-12 20:21:02 +00:00
|
|
|
"time"
|
2019-03-07 01:23:20 +00:00
|
|
|
|
2023-04-03 18:14:47 +00:00
|
|
|
"github.com/hashicorp/vault/helper/useragent"
|
|
|
|
|
2019-03-07 01:23:20 +00:00
|
|
|
"github.com/hashicorp/vault/api"
|
2019-02-15 01:10:36 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// mockProxier is a mock implementation of the Proxier interface, used for testing purposes.
|
|
|
|
// The mock will return the provided responses every time it reaches its Send method, up to
|
|
|
|
// the last provided response. This lets tests control what the next/underlying Proxier layer
|
|
|
|
// might expect to return.
|
|
|
|
type mockProxier struct {
|
|
|
|
proxiedResponses []*SendResponse
|
|
|
|
responseIndex int
|
|
|
|
}
|
|
|
|
|
|
|
|
func newMockProxier(responses []*SendResponse) *mockProxier {
|
|
|
|
return &mockProxier{
|
|
|
|
proxiedResponses: responses,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *mockProxier) Send(ctx context.Context, req *SendRequest) (*SendResponse, error) {
|
|
|
|
if p.responseIndex >= len(p.proxiedResponses) {
|
|
|
|
return nil, fmt.Errorf("index out of bounds: responseIndex = %d, responses = %d", p.responseIndex, len(p.proxiedResponses))
|
|
|
|
}
|
|
|
|
resp := p.proxiedResponses[p.responseIndex]
|
|
|
|
|
|
|
|
p.responseIndex++
|
|
|
|
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *mockProxier) ResponseIndex() int {
|
|
|
|
return p.responseIndex
|
|
|
|
}
|
2019-03-07 01:23:20 +00:00
|
|
|
|
|
|
|
func newTestSendResponse(status int, body string) *SendResponse {
|
2023-04-03 18:14:47 +00:00
|
|
|
headers := make(http.Header)
|
|
|
|
headers.Add("User-Agent", useragent.AgentProxyString())
|
2019-03-07 01:23:20 +00:00
|
|
|
resp := &SendResponse{
|
|
|
|
Response: &api.Response{
|
|
|
|
Response: &http.Response{
|
|
|
|
StatusCode: status,
|
2023-04-03 18:14:47 +00:00
|
|
|
Header: headers,
|
2019-03-07 01:23:20 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
2019-03-12 20:21:02 +00:00
|
|
|
resp.Response.Header.Set("Date", time.Now().Format(http.TimeFormat))
|
2019-03-07 01:23:20 +00:00
|
|
|
|
|
|
|
if body != "" {
|
|
|
|
resp.Response.Body = ioutil.NopCloser(strings.NewReader(body))
|
|
|
|
resp.ResponseBody = []byte(body)
|
|
|
|
}
|
|
|
|
|
|
|
|
if json.Valid([]byte(body)) {
|
|
|
|
resp.Response.Header.Set("content-type", "application/json")
|
|
|
|
}
|
|
|
|
|
|
|
|
return resp
|
|
|
|
}
|
2020-01-30 15:08:42 +00:00
|
|
|
|
|
|
|
type mockTokenVerifierProxier struct {
|
|
|
|
currentToken string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *mockTokenVerifierProxier) Send(ctx context.Context, req *SendRequest) (*SendResponse, error) {
|
|
|
|
p.currentToken = req.Token
|
|
|
|
resp := newTestSendResponse(http.StatusOK,
|
2020-05-14 13:19:27 +00:00
|
|
|
`{"data": {"id": "`+p.currentToken+`"}}`)
|
2020-01-30 15:08:42 +00:00
|
|
|
|
|
|
|
return resp, nil
|
|
|
|
}
|
|
|
|
|
2020-05-14 13:19:27 +00:00
|
|
|
func (p *mockTokenVerifierProxier) GetCurrentRequestToken() string {
|
2020-01-30 15:08:42 +00:00
|
|
|
return p.currentToken
|
2020-05-14 13:19:27 +00:00
|
|
|
}
|
2021-01-26 20:09:37 +00:00
|
|
|
|
|
|
|
type mockDelayProxier struct {
|
|
|
|
cacheableResp bool
|
|
|
|
delay int
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *mockDelayProxier) Send(ctx context.Context, req *SendRequest) (*SendResponse, error) {
|
|
|
|
if p.delay > 0 {
|
|
|
|
select {
|
|
|
|
case <-ctx.Done():
|
|
|
|
return nil, ctx.Err()
|
|
|
|
case <-time.After(time.Duration(p.delay) * time.Millisecond):
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If this is a cacheable response, we return a unique response every time
|
|
|
|
if p.cacheableResp {
|
|
|
|
rand.Seed(time.Now().Unix())
|
|
|
|
s := fmt.Sprintf(`{"lease_id": "%d", "renewable": true, "data": {"foo": "bar"}}`, rand.Int())
|
|
|
|
return newTestSendResponse(http.StatusOK, s), nil
|
|
|
|
}
|
|
|
|
|
|
|
|
return newTestSendResponse(http.StatusOK, `{"value": "output"}`), nil
|
|
|
|
}
|