func handleSysSealStatusRaw(core *vault.Core, w http.ResponseWriter, r *http.Request) { sealed, err := core.Sealed() if err != nil { respondError(w, http.StatusInternalServerError, err) return } sealConfig, err := core.SealAccess().BarrierConfig() if err != nil { respondError(w, http.StatusInternalServerError, err) return } if sealConfig == nil { respondError(w, http.StatusBadRequest, fmt.Errorf( "server is not yet initialized")) return } respondOk(w, &SealStatusResponse{ Sealed: sealed, T: sealConfig.SecretThreshold, N: sealConfig.SecretShares, Progress: core.SecretProgress(), }) }
func handleSysUnseal(core *vault.Core) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.Method { case "PUT": case "POST": default: respondError(w, http.StatusMethodNotAllowed, nil) return } // Parse the request var req UnsealRequest if err := parseRequest(r, &req); err != nil { respondError(w, http.StatusBadRequest, err) return } if !req.Reset && req.Key == "" { respondError( w, http.StatusBadRequest, errors.New("'key' must specified in request body as JSON, or 'reset' set to true")) return } if req.Reset { sealed, err := core.Sealed() if err != nil { respondError(w, http.StatusInternalServerError, err) return } if !sealed { respondError(w, http.StatusBadRequest, errors.New("vault is unsealed")) return } core.ResetUnsealProcess() } else { // Decode the key, which is hex encoded key, err := hex.DecodeString(req.Key) if err != nil { respondError( w, http.StatusBadRequest, errors.New("'key' must be a valid hex-string")) return } // Attempt the unseal if _, err := core.Unseal(key); err != nil { // Ignore ErrInvalidKey because its a user error that we // mask away. We just show them the seal status. if !errwrap.ContainsType(err, new(vault.ErrInvalidKey)) { respondError(w, http.StatusInternalServerError, err) return } } } // Return the seal status handleSysSealStatusRaw(core, w, r) }) }
func getSysHealth(core *vault.Core, r *http.Request) (int, *HealthResponse, error) { // Check if being a standby is allowed for the purpose of a 200 OK _, standbyOK := r.URL.Query()["standbyok"] // FIXME: Change the sealed code to http.StatusServiceUnavailable at some // point sealedCode := http.StatusInternalServerError if code, found, ok := fetchStatusCode(r, "sealedcode"); !ok { return http.StatusBadRequest, nil, nil } else if found { sealedCode = code } standbyCode := http.StatusTooManyRequests // Consul warning code if code, found, ok := fetchStatusCode(r, "standbycode"); !ok { return http.StatusBadRequest, nil, nil } else if found { standbyCode = code } activeCode := http.StatusOK if code, found, ok := fetchStatusCode(r, "activecode"); !ok { return http.StatusBadRequest, nil, nil } else if found { activeCode = code } // Check system status sealed, _ := core.Sealed() standby, _ := core.Standby() init, err := core.Initialized() if err != nil { return http.StatusInternalServerError, nil, err } // Determine the status code code := activeCode switch { case !init: code = http.StatusInternalServerError case sealed: code = sealedCode case !standbyOK && standby: code = standbyCode } // Format the body body := &HealthResponse{ Initialized: init, Sealed: sealed, Standby: standby, ServerTimeUTC: time.Now().UTC().Unix(), } return code, body, nil }
func handleSysSealStatusRaw(core *vault.Core, w http.ResponseWriter, r *http.Request) { sealed, err := core.Sealed() if err != nil { respondError(w, http.StatusInternalServerError, err) return } sealConfig, err := core.SealAccess().BarrierConfig() if err != nil { respondError(w, http.StatusInternalServerError, err) return } if sealConfig == nil { respondError(w, http.StatusBadRequest, fmt.Errorf( "server is not yet initialized")) return } // Fetch the local cluster name and identifier var clusterName, clusterID string if !sealed { cluster, err := core.Cluster() if err != nil { respondError(w, http.StatusInternalServerError, err) return } if cluster == nil { respondError(w, http.StatusInternalServerError, fmt.Errorf("failed to fetch cluster details")) return } clusterName = cluster.Name clusterID = cluster.ID } respondOk(w, &SealStatusResponse{ Sealed: sealed, T: sealConfig.SecretThreshold, N: sealConfig.SecretShares, Progress: core.SecretProgress(), Version: version.GetVersion().VersionNumber(), ClusterName: clusterName, ClusterID: clusterID, }) }
func handleSysHealthGet(core *vault.Core, w http.ResponseWriter, r *http.Request) { // Check if being a standby is allowed for the purpose of a 200 OK _, standbyOK := r.URL.Query()["standbyok"] // Check system status sealed, _ := core.Sealed() standby, _ := core.Standby() init, err := core.Initialized() if err != nil { respondError(w, http.StatusInternalServerError, err) return } // Determine the status code code := http.StatusOK switch { case !init: code = http.StatusInternalServerError case sealed: code = http.StatusInternalServerError case !standbyOK && standby: code = 429 // Consul warning code } // Format the body body := &HealthResponse{ Initialized: init, Sealed: sealed, Standby: standby, ServerTimeUTC: time.Now().UTC().Unix(), } // Generate the response w.Header().Add("Content-Type", "application/json") w.WriteHeader(code) enc := json.NewEncoder(w) enc.Encode(body) }
func handleSysUnseal(core *vault.Core) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.Method { case "PUT": case "POST": default: respondError(w, http.StatusMethodNotAllowed, nil) return } // Parse the request var req UnsealRequest if err := parseRequest(r, w, &req); err != nil { respondError(w, http.StatusBadRequest, err) return } if !req.Reset && req.Key == "" { respondError( w, http.StatusBadRequest, errors.New("'key' must specified in request body as JSON, or 'reset' set to true")) return } if req.Reset { sealed, err := core.Sealed() if err != nil { respondError(w, http.StatusInternalServerError, err) return } if !sealed { respondError(w, http.StatusBadRequest, errors.New("vault is unsealed")) return } core.ResetUnsealProcess() } else { // Decode the key, which is base64 or hex encoded min, max := core.BarrierKeyLength() key, err := hex.DecodeString(req.Key) // We check min and max here to ensure that a string that is base64 // encoded but also valid hex will not be valid and we instead base64 // decode it if err != nil || len(key) < min || len(key) > max { key, err = base64.StdEncoding.DecodeString(req.Key) if err != nil { respondError( w, http.StatusBadRequest, errors.New("'key' must be a valid hex or base64 string")) return } } // Attempt the unseal if _, err := core.Unseal(key); err != nil { switch { case errwrap.ContainsType(err, new(vault.ErrInvalidKey)): case errwrap.Contains(err, vault.ErrBarrierInvalidKey.Error()): case errwrap.Contains(err, vault.ErrBarrierNotInit.Error()): case errwrap.Contains(err, vault.ErrBarrierSealed.Error()): case errwrap.Contains(err, vault.ErrStandby.Error()): default: respondError(w, http.StatusInternalServerError, err) return } respondError(w, http.StatusBadRequest, err) return } } // Return the seal status handleSysSealStatusRaw(core, w, r) }) }
func getSysHealth(core *vault.Core, r *http.Request) (int, *HealthResponse, error) { // Check if being a standby is allowed for the purpose of a 200 OK _, standbyOK := r.URL.Query()["standbyok"] uninitCode := http.StatusNotImplemented if code, found, ok := fetchStatusCode(r, "uninitcode"); !ok { return http.StatusBadRequest, nil, nil } else if found { uninitCode = code } sealedCode := http.StatusServiceUnavailable if code, found, ok := fetchStatusCode(r, "sealedcode"); !ok { return http.StatusBadRequest, nil, nil } else if found { sealedCode = code } standbyCode := http.StatusTooManyRequests // Consul warning code if code, found, ok := fetchStatusCode(r, "standbycode"); !ok { return http.StatusBadRequest, nil, nil } else if found { standbyCode = code } activeCode := http.StatusOK if code, found, ok := fetchStatusCode(r, "activecode"); !ok { return http.StatusBadRequest, nil, nil } else if found { activeCode = code } // Check system status sealed, _ := core.Sealed() standby, _ := core.Standby() init, err := core.Initialized() if err != nil { return http.StatusInternalServerError, nil, err } // Determine the status code code := activeCode switch { case !init: code = uninitCode case sealed: code = sealedCode case !standbyOK && standby: code = standbyCode } // Fetch the local cluster name and identifier var clusterName, clusterID string if !sealed { cluster, err := core.Cluster() if err != nil { return http.StatusInternalServerError, nil, err } if cluster == nil { return http.StatusInternalServerError, nil, fmt.Errorf("failed to fetch cluster details") } clusterName = cluster.Name clusterID = cluster.ID } // Format the body body := &HealthResponse{ Initialized: init, Sealed: sealed, Standby: standby, ServerTimeUTC: time.Now().UTC().Unix(), Version: version.GetVersion().VersionNumber(), ClusterName: clusterName, ClusterID: clusterID, } return code, body, nil }
func handleSysHealthGet(core *vault.Core, w http.ResponseWriter, r *http.Request) { // Check if being a standby is allowed for the purpose of a 200 OK _, standbyOK := r.URL.Query()["standbyok"] // FIXME: Change the sealed code to http.StatusServiceUnavailable at some // point sealedCode := http.StatusInternalServerError if code, found, ok := fetchStatusCode(r, "sealedcode"); !ok { respondError(w, http.StatusBadRequest, nil) return } else if found { sealedCode = code } standbyCode := http.StatusTooManyRequests // Consul warning code if code, found, ok := fetchStatusCode(r, "standbycode"); !ok { respondError(w, http.StatusBadRequest, nil) return } else if found { standbyCode = code } activeCode := http.StatusOK if code, found, ok := fetchStatusCode(r, "activecode"); !ok { respondError(w, http.StatusBadRequest, nil) return } else if found { activeCode = code } // Check system status sealed, _ := core.Sealed() standby, _ := core.Standby() init, err := core.Initialized() if err != nil { respondError(w, http.StatusInternalServerError, err) return } // Determine the status code code := activeCode switch { case !init: code = http.StatusInternalServerError case sealed: code = sealedCode case !standbyOK && standby: code = standbyCode } // Format the body body := &HealthResponse{ Initialized: init, Sealed: sealed, Standby: standby, ServerTimeUTC: time.Now().UTC().Unix(), } // Generate the response w.Header().Add("Content-Type", "application/json") w.WriteHeader(code) enc := json.NewEncoder(w) enc.Encode(body) }