mirror of
https://github.com/optim-enterprises-bv/vault.git
synced 2025-10-30 18:17:55 +00:00
Recovery Mode (#7559)
* Initial work * rework * s/dr/recovery * Add sys/raw support to recovery mode (#7577) * Factor the raw paths out so they can be run with a SystemBackend. # Conflicts: # vault/logical_system.go * Add handleLogicalRecovery which is like handleLogical but is only sufficient for use with the sys-raw endpoint in recovery mode. No authentication is done yet. * Integrate with recovery-mode. We now handle unauthenticated sys/raw requests, albeit on path v1/raw instead v1/sys/raw. * Use sys/raw instead raw during recovery. * Don't bother persisting the recovery token. Authenticate sys/raw requests with it. * RecoveryMode: Support generate-root for autounseals (#7591) * Recovery: Abstract config creation and log settings * Recovery mode integration test. (#7600) * Recovery: Touch up (#7607) * Recovery: Touch up * revert the raw backend creation changes * Added recovery operation token prefix * Move RawBackend to its own file * Update API path and hit it using CLI flag on generate-root * Fix a panic triggered when handling a request that yields a nil response. (#7618) * Improve integ test to actually make changes while in recovery mode and verify they're still there after coming back in regular mode. * Refuse to allow a second recovery token to be generated. * Resize raft cluster to size 1 and start as leader (#7626) * RecoveryMode: Setup raft cluster post unseal (#7635) * Setup raft cluster post unseal in recovery mode * Remove marking as unsealed as its not needed * Address review comments * Accept only one seal config in recovery mode as there is no scope for migration
This commit is contained in:
@@ -4,6 +4,8 @@ import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/hashicorp/vault/sdk/helper/consts"
|
||||
"go.uber.org/atomic"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -18,7 +20,7 @@ import (
|
||||
"github.com/hashicorp/vault/vault"
|
||||
)
|
||||
|
||||
func buildLogicalRequest(core *vault.Core, w http.ResponseWriter, r *http.Request) (*logical.Request, io.ReadCloser, int, error) {
|
||||
func buildLogicalRequestNoAuth(perfStandby bool, w http.ResponseWriter, r *http.Request) (*logical.Request, io.ReadCloser, int, error) {
|
||||
ns, err := namespace.FromContext(r.Context())
|
||||
if err != nil {
|
||||
return nil, nil, http.StatusBadRequest, nil
|
||||
@@ -78,7 +80,7 @@ func buildLogicalRequest(core *vault.Core, w http.ResponseWriter, r *http.Reques
|
||||
passHTTPReq = true
|
||||
origBody = r.Body
|
||||
} else {
|
||||
origBody, err = parseRequest(core, r, w, &data)
|
||||
origBody, err = parseRequest(perfStandby, r, w, &data)
|
||||
if err == io.EOF {
|
||||
data = nil
|
||||
err = nil
|
||||
@@ -105,14 +107,32 @@ func buildLogicalRequest(core *vault.Core, w http.ResponseWriter, r *http.Reques
|
||||
return nil, nil, http.StatusBadRequest, errwrap.Wrapf("failed to generate identifier for the request: {{err}}", err)
|
||||
}
|
||||
|
||||
req, err := requestAuth(core, r, &logical.Request{
|
||||
req := &logical.Request{
|
||||
ID: request_id,
|
||||
Operation: op,
|
||||
Path: path,
|
||||
Data: data,
|
||||
Connection: getConnection(r),
|
||||
Headers: r.Header,
|
||||
})
|
||||
}
|
||||
|
||||
if passHTTPReq {
|
||||
req.HTTPRequest = r
|
||||
}
|
||||
if responseWriter != nil {
|
||||
req.ResponseWriter = logical.NewHTTPResponseWriter(responseWriter)
|
||||
}
|
||||
|
||||
return req, origBody, 0, nil
|
||||
}
|
||||
|
||||
func buildLogicalRequest(core *vault.Core, w http.ResponseWriter, r *http.Request) (*logical.Request, io.ReadCloser, int, error) {
|
||||
req, origBody, status, err := buildLogicalRequestNoAuth(core.PerfStandby(), w, r)
|
||||
if err != nil {
|
||||
return nil, nil, status, err
|
||||
}
|
||||
|
||||
req, err = requestAuth(core, r, req)
|
||||
if err != nil {
|
||||
if errwrap.Contains(err, logical.ErrPermissionDenied.Error()) {
|
||||
return nil, nil, http.StatusForbidden, nil
|
||||
@@ -135,12 +155,6 @@ 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 passHTTPReq {
|
||||
req.HTTPRequest = r
|
||||
}
|
||||
if responseWriter != nil {
|
||||
req.ResponseWriter = logical.NewHTTPResponseWriter(responseWriter)
|
||||
}
|
||||
return req, origBody, 0, nil
|
||||
}
|
||||
|
||||
@@ -168,6 +182,32 @@ func handleLogicalNoForward(core *vault.Core) http.Handler {
|
||||
return handleLogicalInternal(core, false, true)
|
||||
}
|
||||
|
||||
func handleLogicalRecovery(raw *vault.RawBackend, token *atomic.String) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
req, _, statusCode, err := buildLogicalRequestNoAuth(false, w, r)
|
||||
if err != nil || statusCode != 0 {
|
||||
respondError(w, statusCode, err)
|
||||
return
|
||||
}
|
||||
reqToken := r.Header.Get(consts.AuthHeaderName)
|
||||
if reqToken == "" || token.Load() == "" || reqToken != token.Load() {
|
||||
respondError(w, http.StatusForbidden, nil)
|
||||
}
|
||||
|
||||
resp, err := raw.HandleRequest(r.Context(), req)
|
||||
if respondErrorCommon(w, req, resp, err) {
|
||||
return
|
||||
}
|
||||
|
||||
var httpResp *logical.HTTPResponse
|
||||
if resp != nil {
|
||||
httpResp = logical.LogicalResponseToHTTPResponse(resp)
|
||||
httpResp.RequestID = req.ID
|
||||
}
|
||||
respondOk(w, httpResp)
|
||||
})
|
||||
}
|
||||
|
||||
// handleLogicalInternal is a common helper that returns a handler for
|
||||
// processing logical requests. The behavior depends on the various boolean
|
||||
// toggles. Refer to usage on functions for possible behaviors.
|
||||
|
||||
Reference in New Issue
Block a user