From 7ee097c1ba2e11751437de738392ebfcf488b0fd Mon Sep 17 00:00:00 2001 From: James Phillips Date: Wed, 14 Dec 2016 19:42:37 -0800 Subject: [PATCH] Adds complete ACL support for listing events. --- command/agent/event_endpoint.go | 23 +++++++++- command/agent/event_endpoint_test.go | 66 ++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) diff --git a/command/agent/event_endpoint.go b/command/agent/event_endpoint.go index 94d35fc5a..84d2550c5 100644 --- a/command/agent/event_endpoint.go +++ b/command/agent/event_endpoint.go @@ -83,6 +83,14 @@ func (s *HTTPServer) EventList(resp http.ResponseWriter, req *http.Request) (int return nil, nil } + // Fetch the ACL token, if any. + var token string + s.parseToken(req, &token) + acl, err := s.agent.resolveToken(token) + if err != nil { + return nil, err + } + // Look for a name filter var nameFilter string if filt := req.URL.Query().Get("name"); filt != "" { @@ -126,7 +134,20 @@ RUN_QUERY: // Get the recent events events := s.agent.UserEvents() - // Filter the events if necessary + // Filter the events using the ACL, if present + if acl != nil { + for i := 0; i < len(events); i++ { + name := events[i].Name + if acl.EventRead(name) { + continue + } + s.agent.logger.Printf("[DEBUG] agent: dropping event %q from result due to ACLs", name) + events = append(events[:i], events[i+1:]...) + i-- + } + } + + // Filter the events if requested if nameFilter != "" { for i := 0; i < len(events); i++ { if events[i].Name != nameFilter { diff --git a/command/agent/event_endpoint_test.go b/command/agent/event_endpoint_test.go index d90ddc485..53927daeb 100644 --- a/command/agent/event_endpoint_test.go +++ b/command/agent/event_endpoint_test.go @@ -5,6 +5,7 @@ import ( "fmt" "net/http" "net/http/httptest" + "os" "strings" "testing" "time" @@ -192,6 +193,71 @@ func TestEventList_Filter(t *testing.T) { }) } +func TestEventList_ACLFilter(t *testing.T) { + dir, srv := makeHTTPServerWithACLs(t) + defer os.RemoveAll(dir) + defer srv.Shutdown() + defer srv.agent.Shutdown() + + // Fire an event. + p := &UserEvent{Name: "foo"} + if err := srv.agent.UserEvent("dc1", "root", p); err != nil { + t.Fatalf("err: %v", err) + } + + // Try no token. + { + testutil.WaitForResult(func() (bool, error) { + req, err := http.NewRequest("GET", "/v1/event/list", nil) + if err != nil { + return false, err + } + resp := httptest.NewRecorder() + obj, err := srv.EventList(resp, req) + if err != nil { + return false, err + } + + list, ok := obj.([]*UserEvent) + if !ok { + return false, fmt.Errorf("bad: %#v", obj) + } + if len(list) != 0 { + return false, fmt.Errorf("bad: %#v", list) + } + return true, nil + }, func(err error) { + t.Fatalf("err: %v", err) + }) + } + + // Try the root token. + { + testutil.WaitForResult(func() (bool, error) { + req, err := http.NewRequest("GET", "/v1/event/list?token=root", nil) + if err != nil { + return false, err + } + resp := httptest.NewRecorder() + obj, err := srv.EventList(resp, req) + if err != nil { + return false, err + } + + list, ok := obj.([]*UserEvent) + if !ok { + return false, fmt.Errorf("bad: %#v", obj) + } + if len(list) != 1 || list[0].Name != "foo" { + return false, fmt.Errorf("bad: %#v", list) + } + return true, nil + }, func(err error) { + t.Fatalf("err: %v", err) + }) + } +} + func TestEventList_Blocking(t *testing.T) { httpTest(t, func(srv *HTTPServer) { p := &UserEvent{Name: "test"}