From 7d63830eb1cc7898463dd21cc9217682874c3d52 Mon Sep 17 00:00:00 2001 From: Sebastien Blot Date: Tue, 5 Apr 2022 02:08:12 +0200 Subject: [PATCH 1/2] handle containers with TTY in docker acquis --- pkg/acquisition/modules/docker/docker.go | 40 +++++++++++++++++++----- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/pkg/acquisition/modules/docker/docker.go b/pkg/acquisition/modules/docker/docker.go index e8113a2d939..4f0102adb68 100644 --- a/pkg/acquisition/modules/docker/docker.go +++ b/pkg/acquisition/modules/docker/docker.go @@ -64,6 +64,7 @@ type ContainerConfig struct { t *tomb.Tomb logger *log.Entry Labels map[string]string + Tty bool } func (d *DockerSource) Configure(Config []byte, logger *log.Entry) error { @@ -284,9 +285,14 @@ func (d *DockerSource) OneShotAcquisition(out chan types.Event, t *tomb.Tomb) er return err } // we use this library to normalize docker API logs (cf. https://ahmet.im/blog/docker-logs-api-binary-format-explained/) - reader := dlog.NewReader(dockerReader) foundOne = true - scanner := bufio.NewScanner(reader) + var scanner *bufio.Scanner + if containerConfig.Tty { + scanner = bufio.NewScanner(dockerReader) + } else { + reader := dlog.NewReader(dockerReader) + scanner = bufio.NewScanner(reader) + } for scanner.Scan() { line := scanner.Text() if line == "" { @@ -304,6 +310,10 @@ func (d *DockerSource) OneShotAcquisition(out chan types.Event, t *tomb.Tomb) er out <- evt d.logger.Debugf("Sent line to parsing: %+v", evt.Line.Raw) } + err = scanner.Err() + if err != nil { + d.logger.Errorf("Got error from docker read: %s", err) + } d.runningContainerState[container.ID] = containerConfig } } @@ -333,10 +343,18 @@ func (d *DockerSource) CanRun() error { return nil } +func (d *DockerSource) getContainerTTY(containerId string) bool { + containerDetails, err := d.Client.ContainerInspect(context.Background(), containerId) + if err != nil { + return false + } + return containerDetails.Config.Tty +} + func (d *DockerSource) EvalContainer(container dockerTypes.Container) (*ContainerConfig, bool) { for _, containerID := range d.Config.ContainerID { if containerID == container.ID { - return &ContainerConfig{ID: container.ID, Name: container.Names[0], Labels: d.Config.Labels}, true + return &ContainerConfig{ID: container.ID, Name: container.Names[0], Labels: d.Config.Labels, Tty: d.getContainerTTY(container.ID)}, true } } @@ -346,7 +364,7 @@ func (d *DockerSource) EvalContainer(container dockerTypes.Container) (*Containe name = name[1:] } if name == containerName { - return &ContainerConfig{ID: container.ID, Name: name, Labels: d.Config.Labels}, true + return &ContainerConfig{ID: container.ID, Name: name, Labels: d.Config.Labels, Tty: d.getContainerTTY(container.ID)}, true } } @@ -354,14 +372,14 @@ func (d *DockerSource) EvalContainer(container dockerTypes.Container) (*Containe for _, cont := range d.compiledContainerID { if matched := cont.Match([]byte(container.ID)); matched { - return &ContainerConfig{ID: container.ID, Name: container.Names[0], Labels: d.Config.Labels}, true + return &ContainerConfig{ID: container.ID, Name: container.Names[0], Labels: d.Config.Labels, Tty: d.getContainerTTY(container.ID)}, true } } for _, cont := range d.compiledContainerName { for _, name := range container.Names { if matched := cont.Match([]byte(name)); matched { - return &ContainerConfig{ID: container.ID, Name: name, Labels: d.Config.Labels}, true + return &ContainerConfig{ID: container.ID, Name: name, Labels: d.Config.Labels, Tty: d.getContainerTTY(container.ID)}, true } } @@ -454,9 +472,15 @@ func (d *DockerSource) TailDocker(container *ContainerConfig, outChan chan types container.logger.Errorf("unable to read logs from container: %+v", err) return err } + + var scanner *bufio.Scanner // we use this library to normalize docker API logs (cf. https://ahmet.im/blog/docker-logs-api-binary-format-explained/) - reader := dlog.NewReader(dockerReader) - scanner := bufio.NewScanner(reader) + if container.Tty { + scanner = bufio.NewScanner(dockerReader) + } else { + reader := dlog.NewReader(dockerReader) + scanner = bufio.NewScanner(reader) + } readerChan := make(chan string) readerTomb := &tomb.Tomb{} readerTomb.Go(func() error { From 7044a184cc3d9e31988721c108ba7d46c0230a76 Mon Sep 17 00:00:00 2001 From: Sebastien Blot Date: Tue, 5 Apr 2022 09:39:51 +0200 Subject: [PATCH 2/2] fix tests crash --- pkg/acquisition/modules/docker/docker_test.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/pkg/acquisition/modules/docker/docker_test.go b/pkg/acquisition/modules/docker/docker_test.go index ea459ff2b96..6ea99d47e54 100644 --- a/pkg/acquisition/modules/docker/docker_test.go +++ b/pkg/acquisition/modules/docker/docker_test.go @@ -12,6 +12,7 @@ import ( "github.com/crowdsecurity/crowdsec/pkg/cstest" "github.com/crowdsecurity/crowdsec/pkg/types" dockerTypes "github.com/docker/docker/api/types" + dockerContainer "github.com/docker/docker/api/types/container" "github.com/docker/docker/client" log "github.com/sirupsen/logrus" "gopkg.in/tomb.v2" @@ -228,6 +229,15 @@ func (cli *mockDockerCli) ContainerLogs(ctx context.Context, container string, o return r, nil } +func (cli *mockDockerCli) ContainerInspect(ctx context.Context, c string) (dockerTypes.ContainerJSON, error) { + r := dockerTypes.ContainerJSON{ + Config: &dockerContainer.Config{ + Tty: false, + }, + } + return r, nil +} + func TestOneShot(t *testing.T) { log.Infof("Test 'TestOneShot'")