1
0
Fork 0
mirror of https://github.com/moby/moby.git synced 2022-11-09 12:21:53 -05:00

Fix 19575: Docker events doesn't work with authorization plugin

To support the requirement of blocking the request after the daemon
responded the authorization plugin use a `response recorder` that replay
the response after the flow ends.

This commit adds support for commands that hijack the connection and
flushes data via the http.Flusher interface. This resolves the error
with the event endpoint.

Signed-off-by: Liron Levin <liron@twistlock.com>
This commit is contained in:
Liron Levin 2016-02-04 17:41:41 +02:00
parent 858f852da4
commit 5ffc810df2
4 changed files with 146 additions and 9 deletions

View file

@ -11,10 +11,15 @@ import (
"os"
"strings"
"bufio"
"bytes"
"github.com/docker/docker/pkg/authorization"
"github.com/docker/docker/pkg/integration/checker"
"github.com/docker/docker/pkg/plugins"
"github.com/go-check/check"
"os/exec"
"strconv"
"time"
)
const (
@ -221,6 +226,71 @@ func (s *DockerAuthzSuite) TestAuthZPluginDenyResponse(c *check.C) {
c.Assert(res, check.Equals, fmt.Sprintf("Error response from daemon: authorization denied by plugin %s: %s\n", testAuthZPlugin, unauthorizedMessage))
}
// TestAuthZPluginAllowEventStream verifies event stream propogates correctly after request pass through by the authorization plugin
func (s *DockerAuthzSuite) TestAuthZPluginAllowEventStream(c *check.C) {
testRequires(c, DaemonIsLinux)
// Start the authorization plugin
err := s.d.Start("--authorization-plugin=" + testAuthZPlugin)
c.Assert(err, check.IsNil)
s.ctrl.reqRes.Allow = true
s.ctrl.resRes.Allow = true
startTime := strconv.FormatInt(daemonTime(c).Unix(), 10)
// Add another command to to enable event pipelining
eventsCmd := exec.Command(s.d.cmd.Path, "--host", s.d.sock(), "events", "--since", startTime)
stdout, err := eventsCmd.StdoutPipe()
if err != nil {
c.Assert(err, check.IsNil)
}
observer := eventObserver{
buffer: new(bytes.Buffer),
command: eventsCmd,
scanner: bufio.NewScanner(stdout),
startTime: startTime,
}
err = observer.Start()
c.Assert(err, checker.IsNil)
defer observer.Stop()
// Create a container and wait for the creation events
_, err = s.d.Cmd("pull", "busybox")
c.Assert(err, check.IsNil)
out, err := s.d.Cmd("run", "-d", "busybox", "top")
c.Assert(err, check.IsNil)
containerID := strings.TrimSpace(out)
events := map[string]chan bool{
"create": make(chan bool),
"start": make(chan bool),
}
matcher := matchEventLine(containerID, "container", events)
processor := processEventMatch(events)
go observer.Match(matcher, processor)
// Ensure all events are received
for event, eventChannel := range events {
select {
case <-time.After(5 * time.Second):
// Fail the test
observer.CheckEventError(c, containerID, event, matcher)
c.FailNow()
case <-eventChannel:
// Ignore, event received
}
}
// Ensure both events and container endpoints are passed to the authorization plugin
assertURIRecorded(c, s.ctrl.requestsURIs, "/events")
assertURIRecorded(c, s.ctrl.requestsURIs, "/containers/create")
assertURIRecorded(c, s.ctrl.requestsURIs, fmt.Sprintf("/containers/%s/start", containerID))
}
func (s *DockerAuthzSuite) TestAuthZPluginErrorResponse(c *check.C) {
err := s.d.Start("--authorization-plugin=" + testAuthZPlugin)
c.Assert(err, check.IsNil)