http: start the API server

This commit is contained in:
Mitchell Hashimoto
2015-03-11 23:05:16 -07:00
parent 019f9ae5b9
commit 59ce4265de
3 changed files with 151 additions and 0 deletions

52
http/handler.go Normal file
View File

@@ -0,0 +1,52 @@
package http
import (
"encoding/json"
"net/http"
"github.com/hashicorp/vault/vault"
)
// Handler returns an http.Handler for the API. This can be used on
// its own to mount the Vault API within another web server.
func Handler(core *vault.Core) http.Handler {
mux := http.NewServeMux()
mux.Handle("/sys/seal-status", handleSysSealStatus(core))
mux.Handle("/sys/seal", handleSysSeal(core))
mux.Handle("/sys/unseal", handleSysUnseal(core))
return mux
}
func parseRequest(r *http.Request, out interface{}) error {
dec := json.NewDecoder(r.Body)
return dec.Decode(out)
}
func respondError(w http.ResponseWriter, status int, err error) {
w.Header().Add("Content-Type", "application/json")
w.WriteHeader(status)
resp := &ErrorResponse{Errors: make([]string, 0, 1)}
if err != nil {
resp.Errors = append(resp.Errors, err.Error())
}
enc := json.NewEncoder(w)
enc.Encode(resp)
}
func respondOk(w http.ResponseWriter, body interface{}) {
w.Header().Add("Content-Type", "application/json")
if body == nil {
w.WriteHeader(http.StatusNoContent)
} else {
w.WriteHeader(http.StatusOK)
enc := json.NewEncoder(w)
enc.Encode(body)
}
}
type ErrorResponse struct {
Errors []string `json:"errors"`
}

1
http/server.go Normal file
View File

@@ -0,0 +1 @@
package http

98
http/sys_seal.go Normal file
View File

@@ -0,0 +1,98 @@
package http
import (
"errors"
"net/http"
"github.com/hashicorp/vault/vault"
)
func handleSysSeal(core *vault.Core) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "PUT" {
respondError(w, http.StatusMethodNotAllowed, nil)
return
}
if err := core.Seal(); err != nil {
respondError(w, http.StatusInternalServerError, err)
return
}
respondOk(w, nil)
})
}
func handleSysUnseal(core *vault.Core) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.Method != "PUT" {
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.Key == "" {
respondError(
w, http.StatusBadRequest,
errors.New("'key' must specified in request body as JSON"))
return
}
// Attempt the unseal
if _, err := core.Unseal([]byte(req.Key)); err != nil {
respondError(w, http.StatusInternalServerError, err)
return
}
// 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
}
sealConfig, err := core.SealConfig()
if err != nil {
respondError(w, http.StatusInternalServerError, err)
return
}
respondOk(w, &SealStatusResponse{
Sealed: sealed,
T: sealConfig.SecretThreshold,
N: sealConfig.SecretShares,
Progress: core.SecretProgress(),
})
}
type SealStatusResponse struct {
Sealed bool `json:"sealed"`
T int `json:"t"`
N int `json:"n"`
Progress int `json:"progress"`
}
type UnsealRequest struct {
Key string
}