Repository: kubernetes-sigs/security-profiles-operator
Pull request #520 (2021-07-05 10:01:27)

Enhance enricher e2e tests
#### What type of PR is this?

/kind cleanup


#### What this PR does / why we need it:
Make the enricher based e2e tests more robust and add more test cases.
#### Which issue(s) this PR fixes:

None

#### Does this PR have test?

None

#### 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
None
```


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/520#" 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":[]} -->
codecov-commenter: # [Codecov](https://codecov.io/gh/kubernetes-sigs/security-profiles-operator/pull/520?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) Report
> Merging [#520](https://codecov.io/gh/kubernetes-sigs/security-profiles-operator/pull/520?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (870a12e) into [master](https://codecov.io/gh/kubernetes-sigs/security-profiles-operator/commit/ac205ac7fb35ca8fd28796f156fc7bb219420d69?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) (ac205ac) will **not change** coverage.
> The diff coverage is `n/a`.


```diff
@@           Coverage Diff           @@
##           master     #520   +/-   ##
=======================================
  Coverage   43.11%   43.11%           
=======================================
  Files          24       24           
  Lines        1285     1285           
=======================================
  Hits          554      554           
  Misses        692      692           
  Partials       39       39           
```

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-test-e2e | 7b3e878d856ad6579b50393fbe16d9f75acd85d6 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_security-profiles-operator/520/pull-security-profiles-operator-test-e2e/1412002287286489088) | `/test pull-security-profiles-operator-test-e2e`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=security-profiles-operator&pr=520). [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 -->
k8s-ci-robot: @saschagrunert: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-security-profiles-operator-test-e2e | 7b3e878d856ad6579b50393fbe16d9f75acd85d6 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_security-profiles-operator/520/pull-security-profiles-operator-test-e2e/1412002287286489088) | `/test pull-security-profiles-operator-test-e2e`
pull-security-profiles-operator-verify | 7b3e878d856ad6579b50393fbe16d9f75acd85d6 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_security-profiles-operator/520/pull-security-profiles-operator-verify/1412002287181631488) | `/test pull-security-profiles-operator-verify`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=security-profiles-operator&pr=520). [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 -->
k8s-ci-robot: @saschagrunert: The following tests **failed**, say `/retest` to rerun all failed tests:

Test name | Commit | Details | Rerun command
--- | --- | --- | ---
pull-security-profiles-operator-test-e2e | 7b3e878d856ad6579b50393fbe16d9f75acd85d6 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_security-profiles-operator/520/pull-security-profiles-operator-test-e2e/1412002287286489088) | `/test pull-security-profiles-operator-test-e2e`
pull-security-profiles-operator-verify | acc3e85d801225e65c34489cfba2c18146296060 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_security-profiles-operator/520/pull-security-profiles-operator-verify/1412002665407188992) | `/test pull-security-profiles-operator-verify`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=security-profiles-operator&pr=520). [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 -->
k8s-ci-robot: @saschagrunert: The following tests **failed**, say `/retest` to rerun all failed tests:

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

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=security-profiles-operator&pr=520). [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 -->
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-test-e2e | 745ea4e20cb3f8aef29af788a90268c55b6f91fa | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_security-profiles-operator/520/pull-security-profiles-operator-test-e2e/1412007405474025472) | `/test pull-security-profiles-operator-test-e2e`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=security-profiles-operator&pr=520). [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-test-e2e
saschagrunert: Yay, green tests :green_circle: 
saschagrunert: PTAL @JAORMX @jhrozek

Patch:
diff --git a/installation-usage.md b/installation-usage.md
index fd2bd5c98..e7ea2eee5 100644
--- a/installation-usage.md
+++ b/installation-usage.md
@@ -9,7 +9,9 @@
   - [Apply profile to pod](#apply-profile-to-pod)
   - [Base syscalls for a container runtime](#base-syscalls-for-a-container-runtime)
   - [Bind workloads to profiles with ProfileBindings](#bind-workloads-to-profiles-with-profilebindings)
-  - [Record profiles from workloads with ProfileRecordings](#record-profiles-from-workloads-with-profilerecordings)
+  - [Record profiles from workloads with <code>ProfileRecordings</code>](#record-profiles-from-workloads-with-)
+    - [Hook based recording](#hook-based-recording)
+    - [Log enricher based recording](#log-enricher-based-recording)
 - [Restricting to a Single Namespace](#restricting-to-a-single-namespace)
 - [Using metrics](#using-metrics)
   - [Available metrics](#available-metrics)
@@ -206,15 +208,19 @@ $ kubectl get pod test-pod -o jsonpath='{.spec.containers[*].securityContext.sec
 {"localhostProfile":"operator/default/generic/profile-complain-unsafe.json","type":"Localhost"}
 ```
 
-### Record profiles from workloads with ProfileRecordings
+### 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]. [OCI hooks][hooks] are part of the OCI
-runtime-spec, which allow to hook into the container creation process. The
-Kubernetes container runtime [CRI-O][cri-o] supports those hooks out of the box,
-but has to be configured to listen on the hooks directory where the
-[oci-seccomp-bpf-hook.json][hook-json] located. This can be done via a drop-in
-configuration file, for example:
+[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.
+
+#### Hook based recording
+
+[OCI hooks][hooks] are part of the OCI runtime-spec, which allow to hook into
+the container creation process. The Kubernetes container runtime [CRI-O][cri-o]
+supports those hooks out of the box, but has to be configured to listen on the
+hooks directory where the [oci-seccomp-bpf-hook.json][hook-json] is located.
+This can be done via a drop-in configuration file, for example:
 
 ```
 $ cat /etc/crio/crio.conf.d/03-hooks.conf
@@ -234,6 +240,12 @@ and CRI-O work nicely together.
 [hook-json]: https://github.com/containers/oci-seccomp-bpf-hook/blob/50e711/oci-seccomp-bpf-hook.json
 [path]: https://github.com/containers/oci-seccomp-bpf-hook/blob/50e711/oci-seccomp-bpf-hook.json#L4
 
+Unfortunately, [containerd][containerd] is not [capable of running OCI
+hooks][containerd-hooks], yet.
+
+[containerd]: https://containerd.io
+[containerd-hooks]: https://github.com/containerd/cri/issues/405
+
 We can create a new `ProfileRecording` to indicate to the operator that a
 specific workload should be recorded:
 
@@ -244,15 +256,18 @@ metadata:
   name: test-recording
 spec:
   kind: SeccompProfile
+  recorder: hook
   podSelector:
     matchLabels:
       app: alpine
 ```
 
-This means that every workload which contains the label `app=alpine` will from
-now on be recorded into the `SeccompProfile` CRD with the name `test-recording`.
-Please be aware that the resource will be overwritten if recordings are executed
-multiple times.
+Please note the `recorder: hook`, which has to be used to use the hook based
+recording feature. Recordings are linked to workloads by using a `podSelector`,
+which means that every workload, which contains the label `app=alpine`, will
+from now on be recorded into the `SeccompProfile` CRD with the name
+`test-recording`. Please be aware that the resource will be overwritten if
+recordings are executed multiple times.
 
 Now we can start the recording by running a workload which contains the label:
 
@@ -315,6 +330,7 @@ metadata:
   name: recording
 spec:
   kind: SeccompProfile
+  recorder: hook
   podSelector:
     matchLabels:
       app: my-app
@@ -386,6 +402,79 @@ development purposes. It is not recommended to use the OCI hook in production
 clusters because it runs as highly privileged process to trace the container
 workload via a BPF module.
 
+#### Log enricher based recording
+
+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.
+
+To record by using the enricher, create a `ProfileRecording` which is using
+`recorder: logs`:
+
+```yaml
+apiVersion: security-profiles-operator.x-k8s.io/v1alpha1
+kind: ProfileRecording
+metadata:
+  name: test-recording
+spec:
+  kind: SeccompProfile
+  recorder: logs
+  podSelector:
+    matchLabels:
+      app: my-app
+```
+
+Then we can create a workload to be recorded, for example two containers within
+a single pod:
+
+```yaml
+apiVersion: v1
+kind: Pod
+metadata:
+  name: my-pod
+  labels:
+    app: my-app
+spec:
+  containers:
+    - name: nginx
+      image: quay.io/security-profiles-operator/test-nginx:1.19.1
+    - name: redis
+      image: quay.io/security-profiles-operator/redis:6.2.1
+```
+
+If the pod is up and running:
+
+```
+> kubectl get pods
+NAME     READY   STATUS    RESTARTS   AGE
+my-pod   2/2     Running   0          18s
+```
+
+Then the enricher should indicate that it receives audit logs for those containers:
+
+```
+> kubectl -n security-profiles-operator logs --since=1m ds/spod log-enricher
+…
+I0705 12:08:18.729660 1843190 enricher.go:136] log-enricher "msg"="audit"  "container"="redis" "executable"="/usr/local/bin/redis-server" "namespace"="default" "node"="127.0.0.1" "pid"=1847839 "pod"="my-pod" "syscallID"=232 "syscallName"="epoll_wait" "timestamp"="1625486870.273:187492" "type"="seccomp"
+```
+
+Now, if we remove the pod:
+
+```
+> kubectl delete pod my-pod
+```
+
+Then the operator will reconcile two seccomp profiles:
+
+```
+> kubectl get sp
+NAME                   STATUS      AGE
+test-recording-nginx   Installed   15s
+test-recording-redis   Installed   15s
+```
+
 ## Restricting to a Single Namespace
 
 The security-profiles-operator can optionally be run to watch SeccompProfiles in


Test patch:
diff --git a/test/e2e_test.go b/test/e2e_test.go
index 81b590c4f..c6027c645 100644
--- a/test/e2e_test.go
+++ b/test/e2e_test.go
@@ -126,9 +126,11 @@ func (e *e2e) TestSecurityProfilesOperator() {
 	e.Run("cluster-wide: Seccomp: Verify profile recording", func() {
 		e.testCaseProfileRecordingStaticPodHook()
 		e.testCaseProfileRecordingStaticPodLogs()
-		e.testCaseProfileRecordingKubectlRun()
-		e.testCaseProfileRecordingMultiContainer()
-		e.testCaseProfileRecordingDeployment()
+		e.testCaseProfileRecordingKubectlRunHook()
+		e.testCaseProfileRecordingMultiContainerHook()
+		e.testCaseProfileRecordingMultiContainerLogs()
+		e.testCaseProfileRecordingDeploymentHook()
+		e.testCaseProfileRecordingDeploymentLogs()
 	})
 
 	// Clean up cluster-wide deployment to prepare for namespace deployment
diff --git a/test/tc_profilerecordings_test.go b/test/tc_profilerecordings_test.go
index 48a4dac48..9e22672a4 100644
--- a/test/tc_profilerecordings_test.go
+++ b/test/tc_profilerecordings_test.go
@@ -19,6 +19,7 @@ package e2e_test
 import (
 	"io/ioutil"
 	"os"
+	"regexp"
 	"time"
 )
 
@@ -28,18 +29,45 @@ const (
 	recordingName            = "test-recording"
 )
 
+func (e *e2e) waitForEnricherLogs(since time.Time, conditions ...*regexp.Regexp) {
+	for i := 0; i < 10; i++ {
+		e.logf("Waiting for enricher to record syscalls")
+		logs := e.kubectlOperatorNS(
+			"logs",
+			"--since-time="+since.Format(time.RFC3339),
+			"ds/spod",
+			"log-enricher",
+		)
+
+		matchAll := true
+		for _, condition := range conditions {
+			if !condition.MatchString(logs) {
+				matchAll = false
+			}
+		}
+		if matchAll {
+			break
+		}
+
+		time.Sleep(3 * time.Second)
+	}
+}
+
 func (e *e2e) testCaseProfileRecordingStaticPodHook() {
 	e.profileRecordingTestCase()
-	e.profileRecordingStaticPod(exampleRecordingHookPath, 0)
+	e.profileRecordingStaticPod(exampleRecordingHookPath)
 }
 
 func (e *e2e) testCaseProfileRecordingStaticPodLogs() {
 	e.profileRecordingTestCase()
 	e.logEnricherOnlyTestCase()
-	e.profileRecordingStaticPod(exampleRecordingLogsPath, 10*time.Second)
+	e.profileRecordingStaticPod(
+		exampleRecordingLogsPath,
+		regexp.MustCompile(`(?m)"syscallName"="setuid"`),
+	)
 }
 
-func (e *e2e) profileRecordingStaticPod(recording string, sleepTime time.Duration) {
+func (e *e2e) profileRecordingStaticPod(recording string, waitConditions ...*regexp.Regexp) {
 	e.logf("Creating recording for static pod test")
 	e.kubectl("create", "-f", recording)
 
@@ -63,6 +91,8 @@ spec:
 	e.Nil(err)
 	err = testPodFile.Close()
 	e.Nil(err)
+
+	since := time.Now() // nolint: ifshort
 	e.kubectl("create", "-f", testPodFile.Name())
 
 	e.logf("Waiting for test pod to be initialized")
@@ -70,41 +100,61 @@ spec:
 	e.retryGet("pod", podName)
 	e.waitFor("condition=ready", "pod", podName)
 
-	time.Sleep(sleepTime)
+	if waitConditions != nil {
+		e.waitForEnricherLogs(since, waitConditions...)
+	}
+
 	e.kubectl("delete", "pod", podName)
 
 	resourceName := recordingName + "-nginx"
 	profile := e.retryGetSeccompProfile(resourceName)
-	e.Contains(profile, "close")
+	e.Contains(profile, "setuid")
 
 	e.kubectl("delete", "-f", recording)
 	e.Nil(os.Remove(testPodFile.Name()))
 	e.kubectl("delete", "sp", resourceName)
 }
 
-func (e *e2e) testCaseProfileRecordingKubectlRun() {
+func (e *e2e) testCaseProfileRecordingKubectlRunHook() {
 	e.profileRecordingTestCase()
 
 	e.logf("Creating recording for kubectl run test")
 	e.kubectl("create", "-f", exampleRecordingHookPath)
-	defer e.kubectl("delete", "-f", exampleRecordingHookPath)
 
 	e.logf("Creating test pod")
 	e.kubectlRun("--labels=app=alpine", "fedora", "--", "echo", "test")
 
 	resourceName := recordingName + "-fedora"
 	profile := e.retryGetSeccompProfile(resourceName)
-	defer e.kubectl("delete", "sp", resourceName)
 	e.Contains(profile, "prctl")
 	e.NotContains(profile, "mkdir")
+
+	e.kubectl("delete", "-f", exampleRecordingHookPath)
+	e.kubectl("delete", "sp", resourceName)
+}
+
+func (e *e2e) testCaseProfileRecordingMultiContainerHook() {
+	e.profileRecordingTestCase()
+	e.profileRecordingMultiContainer(exampleRecordingHookPath)
+}
+
+func (e *e2e) testCaseProfileRecordingMultiContainerLogs() {
+	e.profileRecordingTestCase()
+	e.logEnricherOnlyTestCase()
+	e.profileRecordingMultiContainer(
+		exampleRecordingLogsPath,
+		regexp.MustCompile(`(?m)"container"="nginx".*"syscallName"="setuid"`),
+		regexp.MustCompile(`(?m)"container"="redis".*"syscallName"="epoll_wait"`),
+	)
 }
 
-func (e *e2e) testCaseProfileRecordingMultiContainer() {
+func (e *e2e) profileRecordingMultiContainer(
+	recording string, waitConditions ...*regexp.Regexp,
+) {
 	e.profileRecordingTestCase()
 
 	e.logf("Creating recording for multi container test")
-	e.kubectl("create", "-f", exampleRecordingHookPath)
-	defer e.kubectl("delete", "-f", exampleRecordingHookPath)
+	e.kubectl("create", "-f", recording)
 
 	e.logf("Creating test pod")
 	const testPod = `
@@ -124,32 +174,61 @@ spec:
 `
 	testPodFile, err := ioutil.TempFile(os.TempDir(), "recording-pod*.yaml")
 	e.Nil(err)
-	defer os.Remove(testPodFile.Name())
 	_, err = testPodFile.Write([]byte(testPod))
 	e.Nil(err)
 	err = testPodFile.Close()
 	e.Nil(err)
+
+	since := time.Now() // nolint: ifshort
 	e.kubectl("create", "-f", testPodFile.Name())
 
 	e.logf("Waiting for test pod to be initialized")
 	const podName = "my-pod"
 	e.retryGet("pod", podName)
 	e.waitFor("condition=ready", "pod", podName)
+
+	if waitConditions != nil {
+		e.waitForEnricherLogs(since, waitConditions...)
+	}
+
 	e.kubectl("delete", "pod", podName)
 
-	profileRedis := e.retryGetSeccompProfile(recordingName + "-redis")
-	profileNginx := e.retryGetSeccompProfile(recordingName + "-nginx")
-	defer e.kubectl("delete", "sp", "--all")
-	e.Contains(profileNginx, "unlink")
-	e.Contains(profileRedis, "nanosleep")
+	const profileNameRedis = recordingName + "-redis"
+	profileRedis := e.retryGetSeccompProfile(profileNameRedis)
+	e.Contains(profileRedis, "epoll_wait")
+
+	const profileNameNginx = recordingName + "-nginx"
+	profileNginx := e.retryGetSeccompProfile(profileNameNginx)
+	e.Contains(profileNginx, "close")
+
+	e.kubectl("delete", "-f", recording)
+	e.Nil(os.Remove(testPodFile.Name()))
+	e.kubectl("delete", "sp", profileNameRedis, profileNameNginx)
+}
+
+func (e *e2e) testCaseProfileRecordingDeploymentHook() {
+	e.profileRecordingTestCase()
+	e.profileRecordingDeployment(exampleRecordingHookPath)
 }
 
-func (e *e2e) testCaseProfileRecordingDeployment() {
+func (e *e2e) testCaseProfileRecordingDeploymentLogs() {
+	e.profileRecordingTestCase()
+	e.logEnricherOnlyTestCase()
+	e.profileRecordingDeployment(
+		exampleRecordingLogsPath,
+		regexp.MustCompile(
+			`(?s)"container"="nginx".*"syscallName"="setuid"`+
+				`.*"container"="nginx".*"syscallName"="setuid"`),
+	)
+}
+
+func (e *e2e) profileRecordingDeployment(
+	recording string, waitConditions ...*regexp.Regexp,
+) {
 	e.profileRecordingTestCase()
 
 	e.logf("Creating recording for deployment test")
-	e.kubectl("create", "-f", exampleRecordingHookPath)
-	defer e.kubectl("delete", "-f", exampleRecordingHookPath)
+	e.kubectl("create", "-f", recording)
 
 	e.logf("Creating test deployment")
 	const testDeployment = `
@@ -173,23 +252,34 @@ spec:
 `
 	testFile, err := ioutil.TempFile(os.TempDir(), "recording-deployment*.yaml")
 	e.Nil(err)
-	defer os.Remove(testFile.Name())
 	_, err = testFile.Write([]byte(testDeployment))
 	e.Nil(err)
 	err = testFile.Close()
 	e.Nil(err)
+
+	since := time.Now() // nolint: ifshort
 	e.kubectl("create", "-f", testFile.Name())
+
 	const deployName = "my-deployment"
 	e.retryGet("deploy", deployName)
 	e.waitFor("condition=available", "deploy", deployName)
+
+	if waitConditions != nil {
+		e.waitForEnricherLogs(since, waitConditions...)
+	}
+
 	e.kubectl("delete", "deploy", deployName)
 
-	profile0 := e.retryGetSeccompProfile(recordingName + "-nginx-0")
-	profile1 := e.retryGetSeccompProfile(recordingName + "-nginx-1")
-	e.Contains(profile0, "unlink")
-	e.Contains(profile1, "unlink")
-	defer e.kubectl("delete", "sp", recordingName+"-nginx-0")
-	defer e.kubectl("delete", "sp", recordingName+"-nginx-1")
+	const profileName0 = recordingName + "-nginx-0"
+	const profileName1 = recordingName + "-nginx-1"
+	profile0 := e.retryGetSeccompProfile(profileName0)
+	profile1 := e.retryGetSeccompProfile(profileName1)
+	e.Contains(profile0, "setuid")
+	e.Contains(profile1, "setuid")
+
+	e.kubectl("delete", "-f", recording)
+	e.Nil(os.Remove(testFile.Name()))
+	e.kubectl("delete", "sp", profileName0, profileName1)
 }
 
 func (e *e2e) retryGetSeccompProfile(args ...string) string {