Repository: kubernetes-sigs/security-profiles-operator
Pull request #531 (2021-07-08 11:28:50)

Add syslog support to log enricher


#### What type of PR is this?

/kind feature


#### What this PR does / why we need it:
This adds support for `/var/log/syslog` log files if auditd is not available on a node.

#### Which issue(s) this PR fixes:

<!--
*Automatically closes linked issue when PR is merged.
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.

Fixes #

or

None
-->
None
#### Does this PR have test?
None
<!--
If tests aren't applicable just write N/A.
-->

#### Special notes for your reviewer:
None
#### Does this PR introduce a user-facing change?

<!--
If no, just write "NONE" in the release-note block below.
If yes, a release note is required:
Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required".

For more information on release notes see: https://git.k8s.io/community/contributors/guide/release-notes.md
-->

```release-note
Added syslog support for log enricher.
```


k8s-ci-robot: [APPROVALNOTIFIER] This PR is **APPROVED**

This pull-request has been approved by: *<a href="https://github.com/kubernetes-sigs/security-profiles-operator/pull/531#" title="Author self-approved">saschagrunert</a>*

The full list of commands accepted by this bot can be found [here](https://go.k8s.io/bot-commands?repo=kubernetes-sigs%2Fsecurity-profiles-operator).

The pull request process is described [here](https://git.k8s.io/community/contributors/guide/owners.md#the-code-review-process)

<details >
Needs approval from an approver in each of these files:

- ~~[OWNERS](https://github.com/kubernetes-sigs/security-profiles-operator/blob/master/OWNERS)~~ [saschagrunert]

Approvers can indicate their approval by writing `/approve` in a comment
Approvers can cancel approval by writing `/approve cancel` in a comment
</details>
<!-- META={"approvers":[]} -->
k8s-ci-robot: @saschagrunert: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-security-profiles-operator-verify | cf59efac5bf81d5435773353352b244bd7321ad4 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_security-profiles-operator/531/pull-security-profiles-operator-verify/1413097746772004864) | `/test pull-security-profiles-operator-verify`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=security-profiles-operator&pr=531). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Asaschagrunert). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/security-profiles-operator/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
codecov-commenter: # [Codecov](https://codecov.io/gh/kubernetes-sigs/security-profiles-operator/pull/531?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) Report
> Merging [#531](https://codecov.io/gh/kubernetes-sigs/security-profiles-operator/pull/531?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (cf59efa) into [master](https://codecov.io/gh/kubernetes-sigs/security-profiles-operator/commit/c8dab31210c6d532e23dfdb5164397d5b0a2dcd2?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (c8dab31) will **decrease** coverage by `0.02%`.
> The diff coverage is `60.00%`.


```diff
@@            Coverage Diff             @@
##           master     #531      +/-   ##
==========================================
- Coverage   44.06%   44.03%   -0.03%     
==========================================
  Files          25       25              
  Lines        1305     1308       +3     
==========================================
+ Hits          575      576       +1     
- Misses        694      695       +1     
- Partials       36       37       +1     
```

k8s-ci-robot: @saschagrunert: The following test **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-security-profiles-operator-build-image | 4edcf659214ec49058dd9c29cfc28d4e98a041b2 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_security-profiles-operator/531/pull-security-profiles-operator-build-image/1413100451766734848) | `/test pull-security-profiles-operator-build-image`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=security-profiles-operator&pr=531). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Asaschagrunert). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/security-profiles-operator/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->
saschagrunert: /test pull-security-profiles-operator-build-image


Patch:
diff --git a/dependencies.yaml b/dependencies.yaml
index ff0a77917..e5d1ced1c 100644
--- a/dependencies.yaml
+++ b/dependencies.yaml
@@ -28,7 +28,7 @@ dependencies:
       match: KUSTOMIZE_VERSION
 
   - name: cert-manager
-    version: 1.3.1
+    version: 1.4.0
     refPaths:
     - path: test/e2e_test.go
       match: jetstack/cert-manager
diff --git a/installation-usage.md b/installation-usage.md
index 140b288e7..c57923cf9 100644
--- a/installation-usage.md
+++ b/installation-usage.md
@@ -46,7 +46,7 @@ architectures `amd64` and `arm64` for now. To deploy the operator, first install
 cert-manager via `kubectl`:
 
 ```sh
-$ kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.3.1/cert-manager.yaml
+$ kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.4.0/cert-manager.yaml
 $ kubectl --namespace cert-manager wait --for condition=ready pod -l app.kubernetes.io/instance=cert-manager
 ```
 
@@ -211,8 +211,9 @@ $ kubectl get pod test-pod -o jsonpath='{.spec.containers[*].securityContext.sec
 ### Record profiles from workloads with `ProfileRecordings`
 
 The operator is capable of recording seccomp profiles by the usage of the
-[oci-seccomp-bpf-hook][bpf-hook] or by evaluating the [audit][auditd] logs. Both
-methods have its pros and cons as well as separate technical requirements.
+[oci-seccomp-bpf-hook][bpf-hook] or by evaluating the [audit][auditd] or
+[syslog][syslog] files. Both methods have its pros and cons as well as separate
+technical requirements.
 
 #### Hook based recording
 
@@ -407,8 +408,8 @@ workload via a BPF module.
 When using the log enricher for recording seccomp profiles, please ensure that
 the feature [is enabled within the spod](#using-the-log-enricher) configuration
 resource. The log based recording works in the same way with
-[containerd][containerd] and [CRI-O][cri-o], while using the node local
-[audit][auditd] logs as input source of truth.
+[containerd][containerd] and [CRI-O][cri-o], while using the node local logs as
+input source of truth.
 
 To record by using the enricher, create a `ProfileRecording` which is using
 `recorder: logs`:
@@ -644,13 +645,16 @@ privileged mode to be able to read the audit logs from the local node. It is als
 required that the enricher is able to read the host processes and therefore runs
 within host PID namespace (`hostPID`).
 
-Further requirements to the Kubernetes node have to be fulfilled to use the log
-enrichment feature:
+One of the following requirements to the Kubernetes node have to be fulfilled to
+use the log enrichment feature:
 
 - [auditd][auditd] needs to run and has to be configured to log into
   `/var/log/audit/audit.log`
+- [syslog][syslog] can be used as fallback to auditd and needs to log into
+  `/var/log/syslog`
 
 [auditd]: https://man7.org/linux/man-pages/man8/auditd.8.html
+[syslog]: https://man7.org/linux/man-pages/man3/syslog.3.html
 
 If all requirements are met, then the feature can be enabled by patching the
 `spod` configuration:
diff --git a/internal/pkg/config/config.go b/internal/pkg/config/config.go
index 4b27772fc..930fcb50d 100644
--- a/internal/pkg/config/config.go
+++ b/internal/pkg/config/config.go
@@ -73,6 +73,9 @@ const (
 	// AuditLogPath is the path to the auditd log file.
 	AuditLogPath = "/var/log/audit/audit.log"
 
+	// SyslogLogPath is the path to the syslog log file.
+	SyslogLogPath = "/var/log/syslog"
+
 	// LogEnricherProfile is the seccomp profile name for tracing syscalls from
 	// the log enricher.
 	LogEnricherProfile = "log-enricher-trace"
diff --git a/internal/pkg/daemon/enricher/enricher.go b/internal/pkg/daemon/enricher/enricher.go
index dacf4d197..984bdd821 100644
--- a/internal/pkg/daemon/enricher/enricher.go
+++ b/internal/pkg/daemon/enricher/enricher.go
@@ -25,6 +25,7 @@ import (
 	"github.com/go-logr/logr"
 	"github.com/nxadm/tail"
 	"github.com/pkg/errors"
+	"sigs.k8s.io/release-utils/util"
 
 	api "sigs.k8s.io/security-profiles-operator/api/server"
 	"sigs.k8s.io/security-profiles-operator/internal/pkg/config"
@@ -92,9 +93,12 @@ func (e *Enricher) Run() error {
 		return errors.Wrap(err, "create syscall recording client")
 	}
 
+	// Use auditd logs as main source or syslog as fallback.
+	filePath := logFilePath()
+
 	// If the file does not exist, then tail will wait for it to appear
 	tailFile, err := e.impl.TailFile(
-		config.AuditLogPath,
+		filePath,
 		tail.Config{
 			ReOpen: true,
 			Follow: true,
@@ -108,7 +112,7 @@ func (e *Enricher) Run() error {
 		return errors.Wrap(err, "tailing file")
 	}
 
-	e.logger.Info("Reading from file " + config.AuditLogPath)
+	e.logger.Info("Reading from file " + filePath)
 	for l := range e.impl.Lines(tailFile) {
 		if l.Err != nil {
 			e.logger.Error(l.Err, "failed to tail")
@@ -197,3 +201,13 @@ func (e *Enricher) Run() error {
 
 	return errors.New("enricher failed")
 }
+
+// logFilePath returns either the path to the audit logs or falls back to
+// syslog if the audit log path does not exist.
+func logFilePath() string {
+	filePath := config.SyslogLogPath
+	if util.Exists(config.AuditLogPath) {
+		filePath = config.AuditLogPath
+	}
+	return filePath
+}
diff --git a/internal/pkg/manager/spod/bindata/spod.go b/internal/pkg/manager/spod/bindata/spod.go
index 1c62a71d5..da6bdbc48 100644
--- a/internal/pkg/manager/spod/bindata/spod.go
+++ b/internal/pkg/manager/spod/bindata/spod.go
@@ -358,10 +358,15 @@ semodule -i /opt/spo-profiles/selinuxd.cil
 						ImagePullPolicy: v1.PullAlways,
 						VolumeMounts: []v1.VolumeMount{
 							{
-								Name:      "host-varlogaudit-volume",
+								Name:      "host-auditlog-volume",
 								MountPath: filepath.Dir(config.AuditLogPath),
 								ReadOnly:  true,
 							},
+							{
+								Name:      "host-syslog-volume",
+								MountPath: filepath.Dir(config.SyslogLogPath),
+								ReadOnly:  true,
+							},
 						},
 						SecurityContext: &v1.SecurityContext{
 							ReadOnlyRootFilesystem: &truly,
@@ -518,7 +523,7 @@ semodule -i /opt/spo-profiles/selinuxd.cil
 						},
 					},
 					{
-						Name: "host-varlogaudit-volume",
+						Name: "host-auditlog-volume",
 						VolumeSource: v1.VolumeSource{
 							HostPath: &v1.HostPathVolumeSource{
 								Path: filepath.Dir(config.AuditLogPath),
@@ -526,6 +531,15 @@ semodule -i /opt/spo-profiles/selinuxd.cil
 							},
 						},
 					},
+					{
+						Name: "host-syslog-volume",
+						VolumeSource: v1.VolumeSource{
+							HostPath: &v1.HostPathVolumeSource{
+								Path: filepath.Dir(config.SyslogLogPath),
+								Type: &hostPathDirectoryOrCreate,
+							},
+						},
+					},
 					{
 						Name: "metrics-cert-volume",
 						VolumeSource: v1.VolumeSource{


Test patch:
diff --git a/internal/pkg/daemon/enricher/audit_test.go b/internal/pkg/daemon/enricher/audit_test.go
index 3957e9e2e..e864d63ce 100644
--- a/internal/pkg/daemon/enricher/audit_test.go
+++ b/internal/pkg/daemon/enricher/audit_test.go
@@ -35,6 +35,12 @@ func Test_isAuditLine(t *testing.T) {
 			`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=1326 lines with timestamp",
+			//nolint:lll
+			`Jul  8 10:31:23 ubuntu2004 kernel: [  270.853767] audit: type=1326 audit(1625740283.502:574): auid=4294967295 uid=0 gid=0 ses=4294967295 pid=4709 comm="sh" exe="/bin/busybox" sig=0 arch=c000003e syscall=13 compat=0 ip=0x7f3c012e467b code=0x7ffc0000`,
+			true,
+		},
 		{
 			"Should identify type=SECCOMP log lines",
 			//nolint:lll
diff --git a/test/e2e_test.go b/test/e2e_test.go
index c6027c645..ad6f48bb3 100644
--- a/test/e2e_test.go
+++ b/test/e2e_test.go
@@ -31,7 +31,7 @@ import (
 )
 
 const (
-	certmanager       = "https://github.com/jetstack/cert-manager/releases/download/v1.3.1/cert-manager.yaml"
+	certmanager       = "https://github.com/jetstack/cert-manager/releases/download/v1.4.0/cert-manager.yaml"
 	manifest          = "deploy/operator.yaml"
 	namespaceManifest = "deploy/namespace-operator.yaml"
 	testNamespace     = "test-ns"