Skip to content

Commit

Permalink
Make enricher run unprivileged
Browse files Browse the repository at this point in the history
  • Loading branch information
pjbgf committed Mar 4, 2021
1 parent 65ad696 commit 8207398
Show file tree
Hide file tree
Showing 12 changed files with 228 additions and 471 deletions.
1 change: 0 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ module sigs.k8s.io/security-profiles-operator
go 1.15

require (
github.com/cirocosta/dmesg_exporter v0.0.0-20190515130104-6e3e42fc8d7b
github.com/containers/common v0.35.2
github.com/crossplane/crossplane-runtime v0.13.0
github.com/go-logr/logr v0.4.0
Expand Down
7 changes: 0 additions & 7 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,6 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmEg9bt0VpxxWqJlO4iwu3FBdHUzV7wQVg=
github.com/cilium/ebpf v0.0.0-20200507155900-a9f01edf17e3/go.mod h1:XT+cAw5wfvsodedcijoh1l9cf7v1x9FlFB/3VmF/O8s=
github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
github.com/cirocosta/dmesg_exporter v0.0.0-20190515130104-6e3e42fc8d7b h1:jk36mztUq5PHmR1J6H5FQg/vur4rrAowTuCPFamr5wQ=
github.com/cirocosta/dmesg_exporter v0.0.0-20190515130104-6e3e42fc8d7b/go.mod h1:WZ6urbJg8HKOXim+GvWEB2mm2qhOpXWb8ILiIYjYyns=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
Expand Down Expand Up @@ -637,7 +635,6 @@ github.com/onsi/ginkgo v1.14.1/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9k
github.com/onsi/ginkgo v1.15.0 h1:1V1NfVQR87RtWAgp1lv9JZJ5Jap+XFGKPi00andXGi4=
github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
Expand Down Expand Up @@ -687,7 +684,6 @@ github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndr
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/pquerna/ffjson v0.0.0-20181028064349-e517b90714f7/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M=
github.com/pquerna/ffjson v0.0.0-20190813045741-dac163c6c0a9/go.mod h1:YARuvh7BUWHNhzDq2OM5tzR2RiCcN2D7sapiKyCel/M=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
Expand All @@ -700,7 +696,6 @@ github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
Expand All @@ -709,7 +704,6 @@ github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+
github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/procfs v0.0.0-20180125133057-cb4147076ac7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20180920065004-418d78d0b9a7/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
Expand Down Expand Up @@ -1029,7 +1023,6 @@ golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180920110915-d641721ec2de/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down
65 changes: 51 additions & 14 deletions internal/pkg/daemon/enricher/audit.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,37 +23,74 @@ import (
"github.com/pkg/errors"
)

// Initially only seccomp logs are supported
// type IDs are defined at https://elixir.bootlin.com/linux/latest/source/include/uapi/linux/audit.h
var auditRegex = regexp.MustCompile(`audit:.+type=1326.+audit\((.+)\).+pid=(\b\d+\b).+exe="(.+)".+syscall=(\b\d+\b).*`)
var (
//nolint:lll
seccompLineRegex = regexp.MustCompile(`(type=SECCOMP|audit:.+type=1326).+audit\((.+)\).+pid=(\b\d+\b).+exe="(.+)".+syscall=(\b\d+\b).*`)
selinuxLineRegex = regexp.MustCompile(`type=AVC.+audit\((.+)\).+pid=(\b\d+\b).*`)
)

// minimum numbers of captures expected on a supported log line.
var minCapturesExpected = 5
var (
minSeccompCapturesExpected = 5
minSelinuxCapturesExpected = 3
)

// isAuditLine checks whether logLine is a supported audit line.
func isAuditLine(logLine string) bool {
captures := auditRegex.FindStringSubmatch(logLine)
captures := seccompLineRegex.FindStringSubmatch(logLine)
if len(captures) >= minSeccompCapturesExpected {
return true
}

return len(captures) > 1
captures = selinuxLineRegex.FindStringSubmatch(logLine)
return len(captures) >= minSelinuxCapturesExpected
}

// extractAuditLine extracts an auditline from logLine.
func extractAuditLine(logLine string) (*auditLine, error) {
captures := auditRegex.FindStringSubmatch(logLine)
if len(captures) < minCapturesExpected {
return nil, errors.Wrap(errUnsupportedLogLine, logLine)
if seccomp := extractSeccompLine(logLine); seccomp != nil {
return seccomp, nil
}

if selinux := extractSelinuxLine(logLine); selinux != nil {
return selinux, nil
}

return nil, errors.Wrap(errUnsupportedLogLine, logLine)
}

func extractSeccompLine(logLine string) *auditLine {
captures := seccompLineRegex.FindStringSubmatch(logLine)
if len(captures) < minSeccompCapturesExpected {
return nil
}

line := auditLine{}
line.Type = "seccomp"
line.TimestampID = captures[1]
line.Executable = captures[3]
if v, err := strconv.Atoi(captures[2]); err == nil {
line.TimestampID = captures[2]
line.Executable = captures[4]
if v, err := strconv.Atoi(captures[3]); err == nil {
line.ProcessID = v
}
if v, err := strconv.Atoi(captures[4]); err == nil {
if v, err := strconv.Atoi(captures[5]); err == nil {
line.SystemCallID = v
}

return &line, nil
return &line
}

func extractSelinuxLine(logLine string) *auditLine {
captures := selinuxLineRegex.FindStringSubmatch(logLine)
if len(captures) < minSelinuxCapturesExpected {
return nil
}

line := auditLine{}
line.Type = "selinux"
line.TimestampID = captures[1]
if v, err := strconv.Atoi(captures[2]); err == nil {
line.ProcessID = v
}

return &line
}
40 changes: 39 additions & 1 deletion internal/pkg/daemon/enricher/audit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,17 @@ func Test_isAuditLine(t *testing.T) {
want bool
}{
{
"Should identify seccomp log lines",
"Should identify type=1326 log lines",
//nolint:lll
`audit: type=1326 audit(1611996299.149:466250): auid=4294967295 uid=0 gid=0 ses=4294967295 pid=615549 comm="sh" exe="/bin/busybox" sig=0 arch=c000003e syscall=1 compat=0 ip=0x7f61a81c5923 code=0x7ffc0000`,
true,
},
{
"Should identify type=SECCOMP log lines",
//nolint:lll
`type=SECCOMP msg=audit(1613596317.899:6461): auid=4294967295 uid=0 gid=0 ses=4294967295 subj=system_u:system_r:spc_t:s0:c284,c594 pid=2039886 comm="ls" exe="/bin/ls" sig=0 arch=c000003e syscall=3 compat=0 ip=0x7f62dce3d4c7 code=0x7ffc0000AUID="unset" UID="root" GID="root" ARCH=x86_64 SYSCALL=close`,
true,
},
{
"Should ignore unsupported log types",
//nolint:lll
Expand All @@ -46,6 +52,12 @@ func Test_isAuditLine(t *testing.T) {
`type=1326 syscall=1`,
false,
},
{
"Should identify SELinux log lines",
//nolint:lll
`type=AVC msg=audit(1613173578.156:2945): avc: denied { read } for pid=75593 comm="security-profil" name="token" dev="tmpfs" ino=612459 scontext=system_u:system_r:container_t:s0:c4,c808 tcontext=system_u:object_r:var_lib_t:s0 tclass=lnk_file permissive=0`,
true,
},
}
for _, tt := range tests {
tt := tt
Expand Down Expand Up @@ -78,6 +90,32 @@ func Test_extractAuditLine(t *testing.T) {
},
nil,
},
{
"Should extract seccomp log lines",
//nolint:lll
`type=SECCOMP msg=audit(1613596317.899:6461): auid=4294967295 uid=0 gid=0 ses=4294967295 subj=system_u:system_r:spc_t:s0:c284,c594 pid=2039886 comm="ls" exe="/bin/ls" sig=0 arch=c000003e syscall=3 compat=0 ip=0x7f62dce3d4c7 code=0x7ffc0000AUID="unset" UID="root" GID="root" ARCH=x86_64 SYSCALL=close`,
&auditLine{
Type: "seccomp",
TimestampID: "1613596317.899:6461",
SystemCallID: 3,
ProcessID: 2039886,
Executable: "/bin/ls",
},
nil,
},
{
"Should extract selinux log lines",
//nolint:lll
`type=AVC msg=audit(1613173578.156:2945): avc: denied { read } for pid=75593 comm="security-profil" name="token" dev="tmpfs" ino=612459 scontext=system_u:system_r:container_t:s0:c4,c808 tcontext=system_u:object_r:var_lib_t:s0 tclass=lnk_file permissive=0`,
&auditLine{
Type: "selinux",
TimestampID: "1613173578.156:2945",
SystemCallID: 0,
ProcessID: 75593,
Executable: "",
},
nil,
},
}
for _, tt := range tests {
tt := tt
Expand Down
42 changes: 41 additions & 1 deletion internal/pkg/daemon/enricher/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,12 @@ limitations under the License.
package enricher

import (
"bufio"
"context"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"

"github.com/pkg/errors"
Expand All @@ -28,7 +32,8 @@ import (
)

const (
crioPrefix = "cri-o://"
crioCgroupRegex = `\/.+-([a-f0-9]+)`
crioPrefix = "cri-o://"
)

// NOTE(jaosorior): Should this actually be namespace-scoped?
Expand Down Expand Up @@ -80,3 +85,38 @@ func containerIDRaw(containerID string) (string, error) {

return "", errors.Wrap(errUnsupportedContainerRuntime, containerID)
}

func getContainerID(processID int) string {
cgroupFile := fmt.Sprintf("/proc/%d/cgroup", processID)
file, err := os.Open(filepath.Clean(cgroupFile))
if err != nil {
logger.Error(nil, "could not open cgroup", "process-id", processID)
return ""
}
defer func() {
cerr := file.Close()
if err == nil {
err = cerr
}
}()

scanner := bufio.NewScanner(file)
scanner.Split(bufio.ScanLines)
for scanner.Scan() {
if containerID := extractID(scanner.Text()); containerID != "" {
return containerID
}
}

return ""
}

func extractID(cgroup string) string {
containerIDRegex := regexp.MustCompile(crioCgroupRegex)
capture := containerIDRegex.FindStringSubmatch(cgroup)
if len(capture) > 1 {
return capture[1]
}

return ""
}
57 changes: 57 additions & 0 deletions internal/pkg/daemon/enricher/container_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
Copyright 2020 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package enricher

import (
"testing"

"github.com/stretchr/testify/require"
)

func TestExtractContainerID(t *testing.T) {
t.Parallel()
tests := []struct {
name string
cgroupLine string
want string
}{
{
"Should extract crio ID",
//nolint:lll
`4:net_cls,net_prio:/kubepods/besteffort/pod26ba375c-2266-4ecc-bf2d-b626db8762af/crio-af208fd68bf39a07a439ed0c9b6609b9ae63ecd8a5f1a2af3e0db48b945b320a`,
"af208fd68bf39a07a439ed0c9b6609b9ae63ecd8a5f1a2af3e0db48b945b320a",
},
{
"Should return empty when not found",
`0::/system.slice/crio.service`,
"",
},
{
"Should extract crio ID ending with .scope",
`0::/system.slice/crio-conmon-5819a498721cf8bb7e334809c9e48aa310bfc98801eb8017034ad17fb0749920.scope`,
"5819a498721cf8bb7e334809c9e48aa310bfc98801eb8017034ad17fb0749920",
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got := extractID(tt.cgroupLine)
require.Equal(t, tt.want, got)
})
}
}

0 comments on commit 8207398

Please sign in to comment.