From 2ce78375f62a4fd33695c77efe36bf6c3c6d6735 Mon Sep 17 00:00:00 2001 From: Calvin Leung Huang Date: Fri, 6 Sep 2019 12:40:15 -0700 Subject: [PATCH] logical/request: store the entire http.Request object instead (#7412) This allows logical operations (along with a non-nil response writer) to process http handler funcs within the operation function while keeping auth and audit checks that the logical request flow provides. --- http/logical.go | 10 +++++----- sdk/logical/request.go | 8 ++++---- vault/logical_system_raft.go | 4 ++-- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/http/logical.go b/http/logical.go index 10f909f170..d179a2873b 100644 --- a/http/logical.go +++ b/http/logical.go @@ -27,7 +27,7 @@ func buildLogicalRequest(core *vault.Core, w http.ResponseWriter, r *http.Reques var data map[string]interface{} var origBody io.ReadCloser - var requestReader io.ReadCloser + var passHTTPReq bool var responseWriter http.ResponseWriter // Determine the operation @@ -68,10 +68,10 @@ func buildLogicalRequest(core *vault.Core, w http.ResponseWriter, r *http.Reques // Parse the request if we can if op == logical.UpdateOperation { // If we are uploading a snapshot we don't want to parse it. Instead - // we will simply add the request body to the logical request object + // we will simply add the HTTP request to the logical request object // for later consumption. if path == "sys/storage/raft/snapshot" || path == "sys/storage/raft/snapshot-force" { - requestReader = r.Body + passHTTPReq = true origBody = r.Body } else { origBody, err = parseRequest(core, r, w, &data) @@ -131,8 +131,8 @@ func buildLogicalRequest(core *vault.Core, w http.ResponseWriter, r *http.Reques return nil, nil, http.StatusBadRequest, errwrap.Wrapf(fmt.Sprintf(`failed to parse %s header: {{err}}`, PolicyOverrideHeaderName), err) } - if requestReader != nil { - req.RequestReader = requestReader + if passHTTPReq { + req.HTTPRequest = r } if responseWriter != nil { req.ResponseWriter = logical.NewHTTPResponseWriter(responseWriter) diff --git a/sdk/logical/request.go b/sdk/logical/request.go index 98d56cec8f..7e7de20732 100644 --- a/sdk/logical/request.go +++ b/sdk/logical/request.go @@ -2,7 +2,7 @@ package logical import ( "fmt" - "io" + "net/http" "strings" "time" ) @@ -173,9 +173,9 @@ type Request struct { // we can delete it before sending off to plugins ClientTokenSource ClientTokenSource - // RequestReader if set can be used to read the full request body from the - // http request that generated this logical.Request object. - RequestReader io.ReadCloser `json:"-" sentinel:""` + // HTTPRequest, if set, can be used to access fields from the HTTP request + // that generated this logical.Request object, such as the request body. + HTTPRequest *http.Request `json:"-" sentinel:""` // ResponseWriter if set can be used to stream a response value to the http // request that generated this logical.Request object. diff --git a/vault/logical_system_raft.go b/vault/logical_system_raft.go index f2eac7df9c..2edca49b1f 100644 --- a/vault/logical_system_raft.go +++ b/vault/logical_system_raft.go @@ -307,7 +307,7 @@ func (b *SystemBackend) handleStorageRaftSnapshotWrite(force bool) framework.Ope if !ok { return logical.ErrorResponse("raft storage is not in use"), logical.ErrInvalidRequest } - if req.RequestReader == nil { + if req.HTTPRequest == nil || req.HTTPRequest.Body == nil { return nil, errors.New("no reader for request") } @@ -320,7 +320,7 @@ func (b *SystemBackend) handleStorageRaftSnapshotWrite(force bool) framework.Ope // don't have to hold the full snapshot in memory. We also want to do // the restore in two parts so we can restore the snapshot while the // stateLock is write locked. - snapFile, cleanup, metadata, err := raftStorage.WriteSnapshotToTemp(req.RequestReader, access) + snapFile, cleanup, metadata, err := raftStorage.WriteSnapshotToTemp(req.HTTPRequest.Body, access) switch { case err == nil: case strings.Contains(err.Error(), "failed to open the sealed hashes"):