From 348f2df0c09e2e3b517add5271e6eee583800be3 Mon Sep 17 00:00:00 2001 From: Daniel J Walsh Date: Mon, 5 Oct 2020 16:33:09 -0400 Subject: Support max_size logoptions Docker supports log-opt max_size and so does conmon (ALthough poorly). Adding support for this allows users to at least make sure their containers logs do not become a DOS vector. Signed-off-by: Daniel J Walsh --- cmd/podman/common/specgen.go | 12 +++++++++--- docs/source/markdown/podman-create.1.md | 18 ++++++++++++------ docs/source/markdown/podman-run.1.md | 16 +++++++++++----- libpod/container_config.go | 2 ++ libpod/oci_conmon_linux.go | 13 +++++++++---- libpod/options.go | 28 ++++++++++++++-------------- pkg/specgen/generate/container_create.go | 3 +++ pkg/specgen/specgen.go | 3 +++ test/e2e/logs_test.go | 16 ++++++++++++++++ 9 files changed, 79 insertions(+), 32 deletions(-) diff --git a/cmd/podman/common/specgen.go b/cmd/podman/common/specgen.go index 84ae70b6a..f427830c6 100644 --- a/cmd/podman/common/specgen.go +++ b/cmd/podman/common/specgen.go @@ -575,11 +575,17 @@ func FillOutSpecGen(s *specgen.SpecGenerator, c *ContainerCLIOpts, args []string if len(split) < 2 { return errors.Errorf("invalid log option %q", o) } - switch { - case split[0] == "driver": + switch strings.ToLower(split[0]) { + case "driver": s.LogConfiguration.Driver = split[1] - case split[0] == "path": + case "path": s.LogConfiguration.Path = split[1] + case "max-size": + logSize, err := units.FromHumanSize(split[1]) + if err != nil { + return errors.Wrapf(err, "%s is not a valid option", o) + } + s.LogConfiguration.Size = logSize default: logOpts[split[0]] = split[1] } diff --git a/docs/source/markdown/podman-create.1.md b/docs/source/markdown/podman-create.1.md index 28c340d2f..3303ae572 100644 --- a/docs/source/markdown/podman-create.1.md +++ b/docs/source/markdown/podman-create.1.md @@ -438,16 +438,22 @@ Not implemented Logging driver for the container. Currently available options are *k8s-file*, *journald*, and *none*, with *json-file* aliased to *k8s-file* for scripting compatibility. -**--log-opt**=*path* +**--log-opt**=*name*=*value* -Logging driver specific options. Used to set the path to the container log file. For example: +Set custom logging configuration. The following *name*s are supported: -`--log-opt path=/var/log/container/mycontainer.json` +- **path**: specify a path to the log file +(e.g. **--log-opt path=/var/log/container/mycontainer.json**); -**--log-opt**=*tag* +- **max-size**: specify a max size of the log file +(e.g. **--log-opt max-size=10mb**); -Set custom logging configuration. Presently supports the `tag` option -which specified a custom log tag for the container. For example: +- **tag**: specify a custom log tag for the container +(e.g. **--log-opt tag="{{.ImageName}}"**. + +It supports the same keys as **podman inspect --format**. + +This option is currently supported only by the **journald** log driver. `--log-opt tag="{{.ImageName}}"` diff --git a/docs/source/markdown/podman-run.1.md b/docs/source/markdown/podman-run.1.md index a27b1b175..d9bcc49ae 100644 --- a/docs/source/markdown/podman-run.1.md +++ b/docs/source/markdown/podman-run.1.md @@ -452,12 +452,18 @@ Logging driver for the container. Currently available options are **k8s-file**, **--log-opt**=*name*=*value* +Logging driver specific options. + Set custom logging configuration. The following *name*s are supported: -- **path**: specify a path to the log file (e.g. -**--log-opt path=/var/log/container/mycontainer.json**); -- **tag**: specify a custom log tag for the container (e.g. -**--log-opt tag="{{.ImageName}}"**. It supports the same -keys as **podman inspect --format**. + +**path**: specify a path to the log file + (e.g. **--log-opt path=/var/log/container/mycontainer.json**); + +**max-size**: specify a max size of the log file + (e.g. **--log-opt max-size=10mb**); + +**tag**: specify a custom log tag for the container + (e.g. **--log-opt tag="{{.ImageName}}"**. This option is currently supported only by the **journald** log driver. diff --git a/libpod/container_config.go b/libpod/container_config.go index 3fc058d52..fc93140dd 100644 --- a/libpod/container_config.go +++ b/libpod/container_config.go @@ -287,6 +287,8 @@ type ContainerMiscConfig struct { LogPath string `json:"logPath"` // LogTag is the tag used for logging LogTag string `json:"logTag"` + // LogSize is the tag used for logging + LogSize int64 `json:"logSize"` // LogDriver driver for logs LogDriver string `json:"logDriver"` // File containing the conmon PID diff --git a/libpod/oci_conmon_linux.go b/libpod/oci_conmon_linux.go index 1d4f33794..5e73bffe0 100644 --- a/libpod/oci_conmon_linux.go +++ b/libpod/oci_conmon_linux.go @@ -1352,10 +1352,6 @@ func (r *ConmonOCIRuntime) sharedConmonArgs(ctr *Container, cuuid, bundlePath, p } args = append(args, "-l", logDriverArg) - if r.logSizeMax >= 0 { - args = append(args, "--log-size-max", fmt.Sprintf("%v", r.logSizeMax)) - } - logLevel := logrus.GetLevel() args = append(args, "--log-level", logLevel.String()) @@ -1363,6 +1359,15 @@ func (r *ConmonOCIRuntime) sharedConmonArgs(ctr *Container, cuuid, bundlePath, p logrus.Debugf("%s messages will be logged to syslog", r.conmonPath) args = append(args, "--syslog") } + + size := r.logSizeMax + if ctr.config.LogSize > 0 { + size = ctr.config.LogSize + } + if size > 0 { + args = append(args, "--log-size-max", fmt.Sprintf("%v", size)) + } + if ociLogPath != "" { args = append(args, "--runtime-arg", "--log-format=json", "--runtime-arg", "--log", fmt.Sprintf("--runtime-arg=%s", ociLogPath)) } diff --git a/libpod/options.go b/libpod/options.go index f7190d0e3..1ffb78da9 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -328,20 +328,6 @@ func WithNoStore() RuntimeOption { } } -// WithMaxLogSize sets the maximum size of container logs. -// Positive sizes are limits in bytes, -1 is unlimited. -func WithMaxLogSize(limit int64) RuntimeOption { - return func(rt *Runtime) error { - if rt.valid { - return define.ErrRuntimeFinalized - } - - rt.config.Containers.LogSizeMax = limit - - return nil - } -} - // WithNoPivotRoot sets the runtime to use MS_MOVE instead of PIVOT_ROOT when // starting containers. func WithNoPivotRoot() RuntimeOption { @@ -543,6 +529,20 @@ func WithRuntimeFlags(runtimeFlags []string) RuntimeOption { // Container Creation Options +// WithMaxLogSize sets the maximum size of container logs. +// Positive sizes are limits in bytes, -1 is unlimited. +func WithMaxLogSize(limit int64) CtrCreateOption { + return func(ctr *Container) error { + if ctr.valid { + return define.ErrRuntimeFinalized + } + + ctr.config.LogSize = limit + + return nil + } +} + // WithShmDir sets the directory that should be mounted on /dev/shm. func WithShmDir(dir string) CtrCreateOption { return func(ctr *Container) error { diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go index 147450703..105e36bc6 100644 --- a/pkg/specgen/generate/container_create.go +++ b/pkg/specgen/generate/container_create.go @@ -260,6 +260,9 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen. if len(s.LogConfiguration.Path) > 0 { options = append(options, libpod.WithLogPath(s.LogConfiguration.Path)) } + if s.LogConfiguration.Size > 0 { + options = append(options, libpod.WithMaxLogSize(s.LogConfiguration.Size)) + } if len(s.LogConfiguration.Options) > 0 && s.LogConfiguration.Options["tag"] != "" { // Note: I'm really guessing here. options = append(options, libpod.WithLogTag(s.LogConfiguration.Options["tag"])) diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go index b8f37ec7a..fa4af7b2b 100644 --- a/pkg/specgen/specgen.go +++ b/pkg/specgen/specgen.go @@ -19,6 +19,9 @@ type LogConfig struct { // Only available if LogDriver is set to "json-file" or "k8s-file". // Optional. Path string `json:"path,omitempty"` + // Size is the maximimup size of the log file + // Optional. + Size int64 `json:"size,omitempty"` // A set of options to accompany the log driver. // Optional. Options map[string]string `json:"options,omitempty"` diff --git a/test/e2e/logs_test.go b/test/e2e/logs_test.go index 67ab71d20..9b3163856 100644 --- a/test/e2e/logs_test.go +++ b/test/e2e/logs_test.go @@ -321,4 +321,20 @@ var _ = Describe("Podman logs", func() { results.WaitWithDefaultTimeout() Expect(results).To(Exit(0)) }) + + It("using container with container log-size", func() { + logc := podmanTest.Podman([]string{"run", "--log-opt=max-size=10k", "-d", ALPINE, "sh", "-c", "echo podman podman podman"}) + logc.WaitWithDefaultTimeout() + Expect(logc).To(Exit(0)) + cid := logc.OutputToString() + + wait := podmanTest.Podman([]string{"wait", cid}) + wait.WaitWithDefaultTimeout() + Expect(wait).To(Exit(0)) + + results := podmanTest.Podman([]string{"logs", cid}) + results.WaitWithDefaultTimeout() + Expect(results).To(Exit(0)) + Expect(results.OutputToString()).To(Equal("podman podman podman")) + }) }) -- cgit v1.2.3-54-g00ecf