func handleSysLeaderGet(core *vault.Core, w http.ResponseWriter, r *http.Request) { haEnabled := true isLeader, address, err := core.Leader() if err == vault.ErrHANotEnabled { haEnabled = false err = nil } if err != nil { respondError(w, http.StatusInternalServerError, err) return } respondOk(w, &LeaderResponse{ HAEnabled: haEnabled, IsSelf: isLeader, LeaderAddress: address, }) }
// respondStandby is used to trigger a redirect in the case that this Vault is currently a hot standby func respondStandby(core *vault.Core, w http.ResponseWriter, reqURL *url.URL) { // Request the leader address _, redirectAddr, err := core.Leader() if err != nil { respondError(w, http.StatusInternalServerError, err) return } // If there is no leader, generate a 503 error if redirectAddr == "" { err = fmt.Errorf("no active Vault instance found") respondError(w, http.StatusServiceUnavailable, err) return } // Parse the redirect location redirectURL, err := url.Parse(redirectAddr) if err != nil { respondError(w, http.StatusInternalServerError, err) return } // Generate a redirect URL finalURL := url.URL{ Scheme: redirectURL.Scheme, Host: redirectURL.Host, Path: reqURL.Path, RawQuery: reqURL.RawQuery, } // Ensure there is a scheme, default to https if finalURL.Scheme == "" { finalURL.Scheme = "https" } // If we have an address, redirect! We use a 307 code // because we don't actually know if its permanent and // the request method should be preserved. w.Header().Set("Location", finalURL.String()) w.WriteHeader(307) }
// handleRequestForwarding determines whether to forward a request or not, // falling back on the older behavior of redirecting the client func handleRequestForwarding(core *vault.Core, handler http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Header.Get(vault.IntNoForwardingHeaderName) != "" { handler.ServeHTTP(w, r) return } if r.Header.Get(NoRequestForwardingHeaderName) != "" { // Forwarding explicitly disabled, fall back to previous behavior core.Logger().Trace("http/handleRequestForwarding: forwarding disabled by client request") handler.ServeHTTP(w, r) return } // Note: in an HA setup, this call will also ensure that connections to // the leader are set up, as that happens once the advertised cluster // values are read during this function isLeader, leaderAddr, err := core.Leader() if err != nil { if err == vault.ErrHANotEnabled { // Standalone node, serve request normally handler.ServeHTTP(w, r) return } // Some internal error occurred respondError(w, http.StatusInternalServerError, err) return } if isLeader { // No forwarding needed, we're leader handler.ServeHTTP(w, r) return } if leaderAddr == "" { respondError(w, http.StatusInternalServerError, fmt.Errorf("node not active but active node not found")) return } // Attempt forwarding the request. If we cannot forward -- perhaps it's // been disabled on the active node -- this will return with an // ErrCannotForward and we simply fall back statusCode, header, retBytes, err := core.ForwardRequest(r) if err != nil { if err == vault.ErrCannotForward { core.Logger().Trace("http/handleRequestForwarding: cannot forward (possibly disabled on active node), falling back") } else { core.Logger().Error("http/handleRequestForwarding: error forwarding request", "error", err) } // Fall back to redirection handler.ServeHTTP(w, r) return } if header != nil { for k, v := range header { for _, j := range v { w.Header().Add(k, j) } } } w.WriteHeader(statusCode) w.Write(retBytes) return }) }
func (c *ServerCommand) enableDev(core *vault.Core, rootTokenID string) (*vault.InitResult, error) { // Initialize it with a basic single key init, err := core.Initialize(&vault.InitParams{ BarrierConfig: &vault.SealConfig{ SecretShares: 1, SecretThreshold: 1, }, RecoveryConfig: nil, }) if err != nil { return nil, err } // Copy the key so that it can be zeroed key := make([]byte, len(init.SecretShares[0])) copy(key, init.SecretShares[0]) // Unseal the core unsealed, err := core.Unseal(key) if err != nil { return nil, err } if !unsealed { return nil, fmt.Errorf("failed to unseal Vault for dev mode") } isLeader, _, err := core.Leader() if err != nil && err != vault.ErrHANotEnabled { return nil, fmt.Errorf("failed to check active status: %v", err) } if err == nil { leaderCount := 5 for !isLeader { if leaderCount == 0 { buf := make([]byte, 1<<16) runtime.Stack(buf, true) return nil, fmt.Errorf("failed to get active status after five seconds; call stack is\n%s\n", buf) } time.Sleep(1 * time.Second) isLeader, _, err = core.Leader() if err != nil { return nil, fmt.Errorf("failed to check active status: %v", err) } leaderCount-- } } if rootTokenID != "" { req := &logical.Request{ ID: "dev-gen-root", Operation: logical.UpdateOperation, ClientToken: init.RootToken, Path: "auth/token/create", Data: map[string]interface{}{ "id": rootTokenID, "policies": []string{"root"}, "no_parent": true, "no_default_policy": true, }, } resp, err := core.HandleRequest(req) if err != nil { return nil, fmt.Errorf("failed to create root token with ID %s: %s", rootTokenID, err) } if resp == nil { return nil, fmt.Errorf("nil response when creating root token with ID %s", rootTokenID) } if resp.Auth == nil { return nil, fmt.Errorf("nil auth when creating root token with ID %s", rootTokenID) } init.RootToken = resp.Auth.ClientToken req.ID = "dev-revoke-init-root" req.Path = "auth/token/revoke-self" req.Data = nil resp, err = core.HandleRequest(req) if err != nil { return nil, fmt.Errorf("failed to revoke initial root token: %s", err) } } // Set the token tokenHelper, err := c.TokenHelper() if err != nil { return nil, err } if err := tokenHelper.Store(init.RootToken); err != nil { return nil, err } return init, nil }
// handleRequestForwarding determines whether to forward a request or not, // falling back on the older behavior of redirecting the client func handleRequestForwarding(core *vault.Core, handler http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Header.Get(vault.IntNoForwardingHeaderName) != "" { handler.ServeHTTP(w, r) return } if r.Header.Get(NoRequestForwardingHeaderName) != "" { // Forwarding explicitly disabled, fall back to previous behavior core.Logger().Printf("[TRACE] http/handleRequestForwarding: forwarding disabled by client request") handler.ServeHTTP(w, r) return } // Note: in an HA setup, this call will also ensure that connections to // the leader are set up, as that happens once the advertised cluster // values are read during this function isLeader, leaderAddr, err := core.Leader() if err != nil { if err == vault.ErrHANotEnabled { // Standalone node, serve request normally handler.ServeHTTP(w, r) return } // Some internal error occurred respondError(w, http.StatusInternalServerError, err) return } if isLeader { // No forwarding needed, we're leader handler.ServeHTTP(w, r) return } if leaderAddr == "" { respondError(w, http.StatusInternalServerError, fmt.Errorf("node not active but active node not found")) return } // Attempt forwarding the request. If we cannot forward -- perhaps it's // been disabled on the active node -- this will return with an // ErrCannotForward and we simply fall back resp, err := core.ForwardRequest(r) if err != nil { if err == vault.ErrCannotForward { core.Logger().Printf("[TRACE] http/handleRequestForwarding: cannot forward (possibly disabled on active node), falling back") } else { core.Logger().Printf("[ERR] http/handleRequestForwarding: error forwarding request: %v", err) } // Fall back to redirection handler.ServeHTTP(w, r) return } defer resp.Body.Close() // Read the body into a buffer so we can write it back out to the // original requestor buf := bytes.NewBuffer(nil) _, err = buf.ReadFrom(resp.Body) if err != nil { core.Logger().Printf("[ERR] http/handleRequestForwarding: error reading response body: %v", err) respondError(w, http.StatusInternalServerError, err) return } w.WriteHeader(resp.StatusCode) w.Write(buf.Bytes()) return }) }