container create: add inspect data to event

When the new `events_container_create_inspect_data` option is enabled in
containers.conf set the `ContainersInspectData` event field for each
container-create event.

The data was requested for the purpose of auditing (e.g., intrusion
detection).

Jira: https://issues.redhat.com/browse/RUN-1702
Signed-off-by: Valentin Rothberg <vrothberg@redhat.com>
This commit is contained in:
Valentin Rothberg 2022-11-18 15:42:05 +01:00
parent c49de2210c
commit 71f92d263c
10 changed files with 99 additions and 8 deletions

2
go.mod
View File

@ -12,7 +12,7 @@ require (
github.com/containernetworking/cni v1.1.2
github.com/containernetworking/plugins v1.1.1
github.com/containers/buildah v1.28.1-0.20221123095548-1c1fa111e4cc
github.com/containers/common v0.50.2-0.20221127123657-5cbd6c092582
github.com/containers/common v0.50.2-0.20221128124429-24d78208a290
github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.23.1-0.20221124171848-19f10aac8007
github.com/containers/ocicrypt v1.1.6

4
go.sum
View File

@ -264,8 +264,8 @@ github.com/containernetworking/plugins v1.1.1 h1:+AGfFigZ5TiQH00vhR8qPeSatj53eNG
github.com/containernetworking/plugins v1.1.1/go.mod h1:Sr5TH/eBsGLXK/h71HeLfX19sZPp3ry5uHSkI4LPxV8=
github.com/containers/buildah v1.28.1-0.20221123095548-1c1fa111e4cc h1:PhYw1PLPiaApmKmjzX338u8iJRz2KGW1DyrvaPt7LVk=
github.com/containers/buildah v1.28.1-0.20221123095548-1c1fa111e4cc/go.mod h1:0HcSoS6BHXWzMKqtxY1L0gupebEX33oPC+X62lPi6+c=
github.com/containers/common v0.50.2-0.20221127123657-5cbd6c092582 h1:Fq+SGDW/BRqStCIviayyZ3lAM1OHvfuzHY9EFYpSzj4=
github.com/containers/common v0.50.2-0.20221127123657-5cbd6c092582/go.mod h1:rzuZglPq/5sz6n29nhyDPCXh44CZymkCR2sacEZb7zw=
github.com/containers/common v0.50.2-0.20221128124429-24d78208a290 h1:ds8YJg3Z91jOcqVR31aFFMH+BOobolXBeGktas58VgY=
github.com/containers/common v0.50.2-0.20221128124429-24d78208a290/go.mod h1:rzuZglPq/5sz6n29nhyDPCXh44CZymkCR2sacEZb7zw=
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.23.1-0.20221124171848-19f10aac8007 h1:UdyeWjzN5V4Gz5h5tX3l/whBHzrdvlPpZDKu4JobN68=

View File

@ -26,6 +26,14 @@ func (r *Runtime) newEventer() (events.Eventer, error) {
// newContainerEvent creates a new event based on a container
func (c *Container) newContainerEvent(status events.Status) {
if err := c.newContainerEventWithInspectData(status, false); err != nil {
logrus.Errorf("Unable to write container event: %v", err)
}
}
// newContainerEventWithInspectData creates a new event and sets the
// ContainerInspectData field if inspectData is set.
func (c *Container) newContainerEventWithInspectData(status events.Status, inspectData bool) error {
e := events.NewEvent(status)
e.ID = c.ID()
e.Name = c.Name()
@ -38,6 +46,24 @@ func (c *Container) newContainerEvent(status events.Status) {
Attributes: c.Labels(),
}
if inspectData {
err := func() error {
data, err := c.inspectLocked(true)
if err != nil {
return err
}
rawData, err := json.Marshal(data)
if err != nil {
return err
}
e.Details.ContainerInspectData = string(rawData)
return nil
}()
if err != nil {
return fmt.Errorf("adding inspect data to container-create event: %v", err)
}
}
// if the current event is a HealthStatus event, we need to get the current
// status of the container to pass to the event
if status == events.HealthStatus {
@ -48,9 +74,7 @@ func (c *Container) newContainerEvent(status events.Status) {
e.HealthStatus = containerHealthStatus
}
if err := c.runtime.eventer.Write(e); err != nil {
logrus.Errorf("Unable to write pod event: %q", err)
}
return c.runtime.eventer.Write(e)
}
// newContainerExitedEvent creates a new event for a container's death

View File

@ -50,6 +50,10 @@ type Event struct {
type Details struct {
// ID is the event ID
ID string
// ContainerInspectData includes the payload of the container's inspect
// data. Only set when events_container_create_inspect_data is set true
// in containers.conf.
ContainerInspectData string `json:",omitempty"`
// PodID is the ID of the pod associated with the container.
PodID string `json:",omitempty"`
// Attributes can be used to describe specifics about the event

View File

@ -63,6 +63,10 @@ func (e EventJournalD) Write(ee Event) error {
m["PODMAN_LABELS"] = string(b)
}
m["PODMAN_HEALTH_STATUS"] = ee.HealthStatus
if len(ee.Details.ContainerInspectData) > 0 {
m["PODMAN_CONTAINER_INSPECT_DATA"] = ee.Details.ContainerInspectData
}
case Network:
m["PODMAN_ID"] = ee.ID
m["PODMAN_NETWORK_NAME"] = ee.Network
@ -187,6 +191,7 @@ func newEventFromJournalEntry(entry *sdjournal.JournalEntry) (*Event, error) {
}
}
newEvent.HealthStatus = entry.Fields["PODMAN_HEALTH_STATUS"]
newEvent.Details.ContainerInspectData = entry.Fields["PODMAN_CONTAINER_INSPECT_DATA"]
case Network:
newEvent.ID = entry.Fields["PODMAN_ID"]
newEvent.Network = entry.Fields["PODMAN_NETWORK_NAME"]

View File

@ -578,7 +578,14 @@ func (r *Runtime) setupContainer(ctx context.Context, ctr *Container) (_ *Contai
} else if err := r.state.AddContainer(ctr); err != nil {
return nil, err
}
ctr.newContainerEvent(events.Create)
if ctr.runtime.config.Engine.EventsContainerCreateInspectData {
if err := ctr.newContainerEventWithInspectData(events.Create, true); err != nil {
return nil, err
}
} else {
ctr.newContainerEvent(events.Create)
}
return ctr, nil
}

View File

@ -249,3 +249,45 @@ EOF
run_podman 125 --events-backend none events --stream=false
is "$output" "Error: cannot read events with the \"none\" backend" "correct error message"
}
function _events_container_create_inspect_data {
containersConf=$PODMAN_TMPDIR/containers.conf
cat >$containersConf <<EOF
[engine]
events_logger="$1"
events_container_create_inspect_data=true
EOF
local cname=c$(random_string 15)
t0=$(date --iso-8601=seconds)
CONTAINERS_CONF=$containersConf run_podman create --name=$cname $IMAGE
run_podman container inspect --size=true $cname
inspect_json=$(jq -r --tab . <<< "$output")
run_podman --events-backend=$1 events \
--since="$t0" \
--filter=status=$cname \
--filter=status=create \
--stream=false \
--format="{{.ContainerInspectData}}"
events_json=$(jq -r --tab . <<< "[$output]")
assert "$inspect_json" = "$events_json" "JSON payload in event attributes is the same as the inspect one"
# Make sure that the inspect data doesn't show by default in
# podman-events.
run_podman --events-backend=$1 events \
--since="$t0" \
--filter=status=$cname \
--filter=status=create \
--stream=false
assert "$output" != ".*ConmonPidFile.*"
assert "$output" != ".*EffectiveCaps.*"
}
@test "events - container inspect data" {
skip_if_remote "remote does not support --events-backend"
_events_container_create_inspect_data journald
_events_container_create_inspect_data file
}

View File

@ -273,6 +273,11 @@ type EngineConfig struct {
// EventsLogger determines where events should be logged.
EventsLogger string `toml:"events_logger,omitempty"`
// EventsContainerCreateInspectData creates a more verbose
// container-create event which includes a JSON payload with detailed
// information about the container.
EventsContainerCreateInspectData bool `toml:"events_container_create_inspect_data,omitempty"`
// graphRoot internal stores the location of the graphroot
graphRoot string

View File

@ -410,6 +410,10 @@ default_sysctls = [
#
#events_logger = "journald"
# Creates a more verbose container-create event which includes a JSON payload
# with detailed information about the container.
#events_container_create_inspect_data = false
# A is a list of directories which are used to search for helper binaries.
#
#helper_binaries_dir = [

2
vendor/modules.txt vendored
View File

@ -118,7 +118,7 @@ github.com/containers/buildah/pkg/rusage
github.com/containers/buildah/pkg/sshagent
github.com/containers/buildah/pkg/util
github.com/containers/buildah/util
# github.com/containers/common v0.50.2-0.20221127123657-5cbd6c092582
# github.com/containers/common v0.50.2-0.20221128124429-24d78208a290
## explicit; go 1.17
github.com/containers/common/libimage
github.com/containers/common/libimage/define