open-vault/command/agent/cache/proxy.go
ncabatoff ef1926b5e4 Agent auto auth wrapping new config checks (#6479)
* Simplify Run(): the function that was being sent over a channel doesn't
need to close over anything except latestToken, and we don't need to
create a new one each iteration.  Instead just pass the relevant items,
namely the token and sink to work on.

* Disallow the following config combinations:
1. auto_auth.method.wrap_ttl > 0 and multiple file sinks
2. auto_auth.method.wrap_ttl > 0 and single file sink with wrap_ttl > 0
3. auto_auth.method.wrap_ttl > 0 and cache.use_auto_auth_token = true

* Expose errors that occur when APIProxy is forwarding request to Vault.

* Fix merge issues.
2019-04-05 16:12:54 -04:00

77 lines
2 KiB
Go

package cache
import (
"bytes"
"context"
"io/ioutil"
"net/http"
"time"
"github.com/hashicorp/vault/api"
)
// SendRequest is the input for Proxier.Send.
type SendRequest struct {
Token string
Request *http.Request
// RequestBody is the stored body bytes from Request.Body. It is set here to
// avoid reading and re-setting the stream multiple times.
RequestBody []byte
}
// SendResponse is the output from Proxier.Send.
type SendResponse struct {
Response *api.Response
// ResponseBody is the stored body bytes from Response.Body. It is set here to
// avoid reading and re-setting the stream multiple times.
ResponseBody []byte
CacheMeta *CacheMeta
}
// CacheMeta contains metadata information about the response,
// such as whether it was a cache hit or miss, and the age of the
// cached entry.
type CacheMeta struct {
Hit bool
Age time.Duration
}
// Proxier is the interface implemented by different components that are
// responsible for performing specific tasks, such as caching and proxying. All
// these tasks combined together would serve the request received by the agent.
type Proxier interface {
Send(ctx context.Context, req *SendRequest) (*SendResponse, error)
}
// NewSendResponse creates a new SendResponse and takes care of initializing its
// fields properly.
func NewSendResponse(apiResponse *api.Response, responseBody []byte) (*SendResponse, error) {
resp := &SendResponse{
Response: apiResponse,
CacheMeta: &CacheMeta{},
}
// If a response body is separately provided we set that as the SendResponse.ResponseBody,
// otherwise we will do an ioutil.ReadAll to extract the response body from apiResponse.
switch {
case len(responseBody) > 0:
resp.ResponseBody = responseBody
case apiResponse.Body != nil:
respBody, err := ioutil.ReadAll(apiResponse.Body)
if err != nil {
return nil, err
}
// Close the old body
apiResponse.Body.Close()
// Re-set the response body after reading from the Reader
apiResponse.Body = ioutil.NopCloser(bytes.NewReader(respBody))
resp.ResponseBody = respBody
}
return resp, nil
}