mirror of
https://github.com/hashicorp/vault.git
synced 2025-12-01 15:41:22 +01:00
http: audit endpoints
This commit is contained in:
parent
a8390aa2db
commit
47d52be3ae
@ -26,6 +26,8 @@ func Handler(core *vault.Core) http.Handler {
|
|||||||
mux.Handle("/v1/sys/revoke/", handleSysRevoke(core))
|
mux.Handle("/v1/sys/revoke/", handleSysRevoke(core))
|
||||||
mux.Handle("/v1/sys/revoke-prefix/", handleSysRevokePrefix(core))
|
mux.Handle("/v1/sys/revoke-prefix/", handleSysRevokePrefix(core))
|
||||||
mux.Handle("/v1/sys/auth/", handleSysAuth(core))
|
mux.Handle("/v1/sys/auth/", handleSysAuth(core))
|
||||||
|
mux.Handle("/v1/sys/audit", handleSysListAudit(core))
|
||||||
|
mux.Handle("/v1/sys/audit/", handleSysAudit(core))
|
||||||
mux.Handle("/v1/", handleLogical(core))
|
mux.Handle("/v1/", handleLogical(core))
|
||||||
return mux
|
return mux
|
||||||
}
|
}
|
||||||
|
|||||||
113
http/sys_audit.go
Normal file
113
http/sys_audit.go
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/logical"
|
||||||
|
"github.com/hashicorp/vault/vault"
|
||||||
|
)
|
||||||
|
|
||||||
|
func handleSysListAudit(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
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := core.HandleRequest(requestAuth(r, &logical.Request{
|
||||||
|
Operation: logical.ReadOperation,
|
||||||
|
Path: "sys/audit",
|
||||||
|
}))
|
||||||
|
if err != nil {
|
||||||
|
respondError(w, http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
respondOk(w, resp.Data)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleSysAudit(core *vault.Core) http.Handler {
|
||||||
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
switch r.Method {
|
||||||
|
case "POST":
|
||||||
|
fallthrough
|
||||||
|
case "PUT":
|
||||||
|
handleSysEnableAudit(core, w, r)
|
||||||
|
case "DELETE":
|
||||||
|
handleSysDisableAudit(core, w, r)
|
||||||
|
default:
|
||||||
|
respondError(w, http.StatusMethodNotAllowed, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleSysDisableAudit(core *vault.Core, w http.ResponseWriter, r *http.Request) {
|
||||||
|
// Determine the path...
|
||||||
|
prefix := "/v1/sys/audit/"
|
||||||
|
if !strings.HasPrefix(r.URL.Path, prefix) {
|
||||||
|
respondError(w, http.StatusNotFound, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
path := r.URL.Path[len(prefix):]
|
||||||
|
if path == "" {
|
||||||
|
respondError(w, http.StatusNotFound, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := core.HandleRequest(requestAuth(r, &logical.Request{
|
||||||
|
Operation: logical.DeleteOperation,
|
||||||
|
Path: "sys/audit/" + path,
|
||||||
|
}))
|
||||||
|
if err != nil {
|
||||||
|
respondError(w, http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
respondOk(w, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
func handleSysEnableAudit(core *vault.Core, w http.ResponseWriter, r *http.Request) {
|
||||||
|
// Determine the path...
|
||||||
|
prefix := "/v1/sys/audit/"
|
||||||
|
if !strings.HasPrefix(r.URL.Path, prefix) {
|
||||||
|
respondError(w, http.StatusNotFound, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
path := r.URL.Path[len(prefix):]
|
||||||
|
if path == "" {
|
||||||
|
respondError(w, http.StatusNotFound, nil)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse the request if we can
|
||||||
|
var req enableAuditRequest
|
||||||
|
if err := parseRequest(r, &req); err != nil {
|
||||||
|
respondError(w, http.StatusBadRequest, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err := core.HandleRequest(requestAuth(r, &logical.Request{
|
||||||
|
Operation: logical.WriteOperation,
|
||||||
|
Path: "sys/audit/" + path,
|
||||||
|
Data: map[string]interface{}{
|
||||||
|
"type": req.Type,
|
||||||
|
"description": req.Description,
|
||||||
|
"options": req.Options,
|
||||||
|
},
|
||||||
|
}))
|
||||||
|
if err != nil {
|
||||||
|
respondError(w, http.StatusInternalServerError, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
respondOk(w, nil)
|
||||||
|
}
|
||||||
|
|
||||||
|
type enableAuditRequest struct {
|
||||||
|
Type string `json:"type"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Options map[string]string `json:"options"`
|
||||||
|
}
|
||||||
68
http/sys_audit_test.go
Normal file
68
http/sys_audit_test.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/vault"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSysAudit(t *testing.T) {
|
||||||
|
core, _, token := vault.TestCoreUnsealed(t)
|
||||||
|
ln, addr := TestServer(t, core)
|
||||||
|
defer ln.Close()
|
||||||
|
TestServerAuth(t, addr, token)
|
||||||
|
|
||||||
|
resp := testHttpPost(t, addr+"/v1/sys/audit/noop", map[string]interface{}{
|
||||||
|
"type": "noop",
|
||||||
|
})
|
||||||
|
testResponseStatus(t, resp, 204)
|
||||||
|
|
||||||
|
resp, err := http.Get(addr + "/v1/sys/audit")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var actual map[string]interface{}
|
||||||
|
expected := map[string]interface{}{
|
||||||
|
"noop": map[string]interface{}{
|
||||||
|
"type": "noop",
|
||||||
|
"description": "",
|
||||||
|
"options": map[string]interface{}{},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
testResponseStatus(t, resp, 200)
|
||||||
|
testResponseBody(t, resp, &actual)
|
||||||
|
if !reflect.DeepEqual(actual, expected) {
|
||||||
|
t.Fatalf("bad: %#v", actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSysDisableAudit(t *testing.T) {
|
||||||
|
core, _, token := vault.TestCoreUnsealed(t)
|
||||||
|
ln, addr := TestServer(t, core)
|
||||||
|
defer ln.Close()
|
||||||
|
TestServerAuth(t, addr, token)
|
||||||
|
|
||||||
|
resp := testHttpPost(t, addr+"/v1/sys/audit/foo", map[string]interface{}{
|
||||||
|
"type": "noop",
|
||||||
|
})
|
||||||
|
testResponseStatus(t, resp, 204)
|
||||||
|
|
||||||
|
resp = testHttpDelete(t, addr+"/v1/sys/audit/foo")
|
||||||
|
testResponseStatus(t, resp, 204)
|
||||||
|
|
||||||
|
resp, err := http.Get(addr + "/v1/sys/audit")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var actual map[string]interface{}
|
||||||
|
expected := map[string]interface{}{}
|
||||||
|
testResponseStatus(t, resp, 200)
|
||||||
|
testResponseBody(t, resp, &actual)
|
||||||
|
if !reflect.DeepEqual(actual, expected) {
|
||||||
|
t.Fatalf("bad: %#v", actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -3,6 +3,7 @@ package vault
|
|||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/hashicorp/vault/audit"
|
||||||
"github.com/hashicorp/vault/logical"
|
"github.com/hashicorp/vault/logical"
|
||||||
"github.com/hashicorp/vault/logical/framework"
|
"github.com/hashicorp/vault/logical/framework"
|
||||||
"github.com/hashicorp/vault/physical"
|
"github.com/hashicorp/vault/physical"
|
||||||
@ -13,6 +14,11 @@ import (
|
|||||||
|
|
||||||
// TestCore returns a pure in-memory, uninitialized core for testing.
|
// TestCore returns a pure in-memory, uninitialized core for testing.
|
||||||
func TestCore(t *testing.T) *Core {
|
func TestCore(t *testing.T) *Core {
|
||||||
|
noopAudits := map[string]audit.Factory{
|
||||||
|
"noop": func(map[string]string) (audit.Backend, error) {
|
||||||
|
return new(noopAudit), nil
|
||||||
|
},
|
||||||
|
}
|
||||||
noopBackends := make(map[string]logical.Factory)
|
noopBackends := make(map[string]logical.Factory)
|
||||||
noopBackends["noop"] = func(map[string]string) (logical.Backend, error) {
|
noopBackends["noop"] = func(map[string]string) (logical.Backend, error) {
|
||||||
return new(framework.Backend), nil
|
return new(framework.Backend), nil
|
||||||
@ -21,6 +27,7 @@ func TestCore(t *testing.T) *Core {
|
|||||||
physicalBackend := physical.NewInmem()
|
physicalBackend := physical.NewInmem()
|
||||||
c, err := NewCore(&CoreConfig{
|
c, err := NewCore(&CoreConfig{
|
||||||
Physical: physicalBackend,
|
Physical: physicalBackend,
|
||||||
|
AuditBackends: noopAudits,
|
||||||
LogicalBackends: noopBackends,
|
LogicalBackends: noopBackends,
|
||||||
CredentialBackends: noopBackends,
|
CredentialBackends: noopBackends,
|
||||||
})
|
})
|
||||||
@ -71,3 +78,13 @@ func TestKeyCopy(key []byte) []byte {
|
|||||||
copy(result, key)
|
copy(result, key)
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type noopAudit struct{}
|
||||||
|
|
||||||
|
func (n *noopAudit) LogRequest(a *logical.Auth, r *logical.Request) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *noopAudit) LogResponse(a *logical.Auth, r *logical.Request, re *logical.Response, err error) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user