open-vault/http/sys_seal.go

203 lines
4.9 KiB
Go
Raw Normal View History

2015-03-12 06:05:16 +00:00
package http
import (
"encoding/base64"
2015-03-12 18:12:44 +00:00
"encoding/hex"
2015-03-12 06:05:16 +00:00
"errors"
"fmt"
2015-03-12 06:05:16 +00:00
"net/http"
"github.com/hashicorp/errwrap"
2015-03-31 18:45:44 +00:00
"github.com/hashicorp/vault/logical"
2015-03-12 06:05:16 +00:00
"github.com/hashicorp/vault/vault"
"github.com/hashicorp/vault/version"
2015-03-12 06:05:16 +00:00
)
func handleSysSeal(core *vault.Core) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
req, statusCode, err := buildLogicalRequest(w, r)
if err != nil || statusCode != 0 {
respondError(w, statusCode, err)
return
}
switch req.Operation {
case logical.UpdateOperation:
default:
2015-03-12 06:05:16 +00:00
respondError(w, http.StatusMethodNotAllowed, nil)
return
}
2015-03-31 18:45:44 +00:00
// Seal with the token above
if err := core.SealWithRequest(req); err != nil {
2015-03-12 06:05:16 +00:00
respondError(w, http.StatusInternalServerError, err)
return
}
respondOk(w, nil)
})
}
func handleSysStepDown(core *vault.Core) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
req, statusCode, err := buildLogicalRequest(w, r)
if err != nil || statusCode != 0 {
respondError(w, statusCode, err)
return
}
switch req.Operation {
case logical.UpdateOperation:
default:
respondError(w, http.StatusMethodNotAllowed, nil)
return
}
// Seal with the token above
if err := core.StepDown(req); err != nil {
respondError(w, http.StatusInternalServerError, err)
return
}
respondOk(w, nil)
})
}
2015-03-12 06:05:16 +00:00
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:
2015-03-12 06:05:16 +00:00
respondError(w, http.StatusMethodNotAllowed, nil)
return
}
// Parse the request
var req UnsealRequest
2015-03-12 18:12:44 +00:00
if err := parseRequest(r, &req); err != nil {
2015-03-12 06:05:16 +00:00
respondError(w, http.StatusBadRequest, err)
return
}
if !req.Reset && req.Key == "" {
2015-03-12 06:05:16 +00:00
respondError(
w, http.StatusBadRequest,
errors.New("'key' must specified in request body as JSON, or 'reset' set to true"))
2015-03-12 06:05:16 +00:00
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 {
// 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
}
}
2015-03-12 06:05:16 +00:00
}
// Return the seal status
handleSysSealStatusRaw(core, w, r)
})
}
func handleSysSealStatus(core *vault.Core) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "GET" {
respondError(w, http.StatusMethodNotAllowed, nil)
return
}
handleSysSealStatusRaw(core, w, r)
})
}
func handleSysSealStatusRaw(core *vault.Core, w http.ResponseWriter, r *http.Request) {
sealed, err := core.Sealed()
if err != nil {
respondError(w, http.StatusInternalServerError, err)
return
}
2016-04-04 14:44:22 +00:00
sealConfig, err := core.SealAccess().BarrierConfig()
2015-03-12 06:05:16 +00:00
if err != nil {
respondError(w, http.StatusInternalServerError, err)
return
}
if sealConfig == nil {
respondError(w, http.StatusBadRequest, fmt.Errorf(
"server is not yet initialized"))
return
}
2015-03-12 06:05:16 +00:00
// 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
}
2016-08-10 19:22:12 +00:00
if cluster == nil {
respondError(w, http.StatusInternalServerError, fmt.Errorf("failed to fetch cluster details"))
return
}
clusterName = cluster.Name
clusterID = cluster.ID
}
2015-03-12 06:05:16 +00:00
respondOk(w, &SealStatusResponse{
Sealed: sealed,
T: sealConfig.SecretThreshold,
N: sealConfig.SecretShares,
Progress: core.SecretProgress(),
Version: version.GetVersion().String(),
ClusterName: clusterName,
ClusterID: clusterID,
2015-03-12 06:05:16 +00:00
})
}
type SealStatusResponse struct {
Sealed bool `json:"sealed"`
T int `json:"t"`
N int `json:"n"`
Progress int `json:"progress"`
Version string `json:"version"`
ClusterName string `json:"cluster_name,omitempty"`
ClusterID string `json:"cluster_id,omitempty"`
2015-03-12 06:05:16 +00:00
}
type UnsealRequest struct {
Key string
Reset bool
2015-03-12 06:05:16 +00:00
}