Repository: kubernetes-sigs/security-profiles-operator
Pull request #351 (2021-03-05 19:00:10)

Add use case about correlating log entries to containers
#### What type of PR is this?

/kind documentation

#### What this PR does / why we need it:

Adds a new use case highlighting that Kirsti needs to be able to correlate audit logs to specific containers.

#### Which issue(s) this PR fixes:

None

#### Does this PR have test?

N/A

#### Special notes for your reviewer:

Follow-up from from [slack thread](https://kubernetes.slack.com/archives/C013FQNB0A2/p1614926114064100).

#### Does this PR introduce a user-facing change?

```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/351#" title="Author self-approved">pjbgf</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)~~ [pjbgf]

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-io: # [Codecov](https://codecov.io/gh/kubernetes-sigs/security-profiles-operator/pull/351?src=pr&el=h1) Report
> Merging [#351](https://codecov.io/gh/kubernetes-sigs/security-profiles-operator/pull/351?src=pr&el=desc) (be0c0f4) into [master](https://codecov.io/gh/kubernetes-sigs/security-profiles-operator/commit/e7b700d45fd3062261d17a7f1163314b42854acc?el=desc) (e7b700d) will **not change** coverage.
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/kubernetes-sigs/security-profiles-operator/pull/351/graphs/tree.svg?width=650&height=150&src=pr&token=37VIWSZ1ZT)](https://codecov.io/gh/kubernetes-sigs/security-profiles-operator/pull/351?src=pr&el=tree)

```diff
@@           Coverage Diff           @@
##           master     #351   +/-   ##
=======================================
  Coverage   27.75%   27.75%           
=======================================
  Files          10       10           
  Lines         753      753           
=======================================
  Hits          209      209           
  Misses        525      525           
  Partials       19       19           
```

| Flag | Coverage Δ | |
|---|---|---|
| unittests | `27.75% <ø> (ø)` | |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags#carryforward-flags-in-the-pull-request-comment) to find out more.


------

[Continue to review full report at Codecov](https://codecov.io/gh/kubernetes-sigs/security-profiles-operator/pull/351?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/kubernetes-sigs/security-profiles-operator/pull/351?src=pr&el=footer). Last update [e7b700d...be0c0f4](https://codecov.io/gh/kubernetes-sigs/security-profiles-operator/pull/351?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

pjbgf: /test pull-security-profiles-operator-test-e2e
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/351#pullrequestreview-605739442" title="LGTM">JAORMX</a>*, *<a href="https://github.com/kubernetes-sigs/security-profiles-operator/pull/351#" title="Author self-approved">pjbgf</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)~~ [pjbgf]

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":[]} -->
JAORMX: /retest
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/351#pullrequestreview-605739442" title="LGTM">JAORMX</a>*, *<a href="https://github.com/kubernetes-sigs/security-profiles-operator/pull/351#" title="Author self-approved">pjbgf</a>*, *<a href="https://github.com/kubernetes-sigs/security-profiles-operator/pull/351#pullrequestreview-606056466" title="LGTM">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)~~ [pjbgf,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":[]} -->

Patch:
diff --git a/README.md b/README.md
index fd0ff817a..64d6dbaeb 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,8 @@
 # Kubernetes Security Profiles Operator
 
+[![build](https://github.com/kubernetes-sigs/security-profiles-operator/actions/workflows/build.yml/badge.svg)](https://github.com/kubernetes-sigs/security-profiles-operator/actions/workflows/build.yml)
+[![test](https://github.com/kubernetes-sigs/security-profiles-operator/actions/workflows/test.yml/badge.svg)](https://github.com/kubernetes-sigs/security-profiles-operator/actions/workflows/test.yml)
+
 This project is the starting point for the _Security Profiles Operator_, an
 out-of-tree Kubernetes enhancement which aims to make managing and applying
 seccomp and AppArmor profiles more easy and straight forward in Kubernetes.
diff --git a/api/seccompprofile/v1alpha1/seccompprofile_types.go b/api/seccompprofile/v1alpha1/seccompprofile_types.go
index ee857e8b1..276317264 100644
--- a/api/seccompprofile/v1alpha1/seccompprofile_types.go
+++ b/api/seccompprofile/v1alpha1/seccompprofile_types.go
@@ -23,10 +23,6 @@ import (
 
 // SeccompProfileSpec defines the desired state of SeccompProfile.
 type SeccompProfileSpec struct {
-	// the type of application workload for which the profile is targeted. Will be a subdirectory in the profile path on disk.
-	//nolint:lll
-	TargetWorkload string `json:"targetWorkload"`
-
 	// name of base profile (in the same namespace) what will be unioned into this profile
 	BaseProfileName string `json:"baseProfileName,omitempty"`
 
diff --git a/deploy/base/crd.yaml b/deploy/base/crd.yaml
index 5511f8bd1..9d35ac9c7 100644
--- a/deploy/base/crd.yaml
+++ b/deploy/base/crd.yaml
@@ -319,13 +319,8 @@ spec:
                   - names
                   type: object
                 type: array
-              targetWorkload:
-                description: the type of application workload for which the profile
-                  is targeted. Will be a subdirectory in the profile path on disk.
-                type: string
             required:
             - defaultAction
-            - targetWorkload
             type: object
           status:
             description: SeccompProfileStatus contains status of the deployed SeccompProfile.
diff --git a/deploy/namespace-operator.yaml b/deploy/namespace-operator.yaml
index d46d4bef2..fbdf117e4 100644
--- a/deploy/namespace-operator.yaml
+++ b/deploy/namespace-operator.yaml
@@ -278,12 +278,8 @@ spec:
                   - names
                   type: object
                 type: array
-              targetWorkload:
-                description: the type of application workload for which the profile is targeted. Will be a subdirectory in the profile path on disk.
-                type: string
             required:
             - defaultAction
-            - targetWorkload
             type: object
           status:
             description: SeccompProfileStatus contains status of the deployed SeccompProfile.
diff --git a/deploy/operator.yaml b/deploy/operator.yaml
index 71a152758..ded9ed54b 100644
--- a/deploy/operator.yaml
+++ b/deploy/operator.yaml
@@ -278,12 +278,8 @@ spec:
                   - names
                   type: object
                 type: array
-              targetWorkload:
-                description: the type of application workload for which the profile is targeted. Will be a subdirectory in the profile path on disk.
-                type: string
             required:
             - defaultAction
-            - targetWorkload
             type: object
           status:
             description: SeccompProfileStatus contains status of the deployed SeccompProfile.
diff --git a/doc/user-stories.md b/doc/user-stories.md
index ee07e251f..7ec34d72f 100644
--- a/doc/user-stories.md
+++ b/doc/user-stories.md
@@ -113,6 +113,18 @@ Open Questions:
 
 * Does this only impact Profiles created through SPO (i.e. can a user just use `runtime/default`)?
 
+
+### As an infrastructure SRE, Kirsti wants to be able to easily correlate audit log entries related to security profiles to specific containers/pods.
+
+Details:
+
+* The different security mechanisms (i.e. AppArmor, Seccomp, SElinux) may be configured 
+  to generate audit logs in the host's system/audit logs. The logs do not provide any 
+  Kubernetes specific information, making it difficult to link back a log entry to 
+  specific containers.
+  The problem becomes even harder when considering short-lived containers and at scale.
+
+
 Terminology
 ===========
 
diff --git a/examples/baseprofile-crun.yaml b/examples/baseprofile-crun.yaml
index dc1aedb74..a26df164b 100644
--- a/examples/baseprofile-crun.yaml
+++ b/examples/baseprofile-crun.yaml
@@ -5,7 +5,6 @@ metadata:
   name: crun-v0.17
 spec:
   defaultAction: SCMP_ACT_ERRNO
-  targetWorkload: base
   architectures:
   - SCMP_ARCH_X86_64
   syscalls:
diff --git a/examples/baseprofile-runc.yaml b/examples/baseprofile-runc.yaml
index a43dcec1a..de4e2fdf2 100644
--- a/examples/baseprofile-runc.yaml
+++ b/examples/baseprofile-runc.yaml
@@ -5,7 +5,6 @@ metadata:
   name: runc-v1.0.0-rc92
 spec:
   defaultAction: SCMP_ACT_ERRNO
-  targetWorkload: base
   architectures:
   - SCMP_ARCH_X86_64
   syscalls:
diff --git a/examples/pod.yaml b/examples/pod.yaml
index dca54741e..080a80c63 100644
--- a/examples/pod.yaml
+++ b/examples/pod.yaml
@@ -4,11 +4,11 @@ metadata:
   name: test-pod
   annotations:
     # Use the default nginx profile
-    seccomp.security.alpha.kubernetes.io/pod: 'localhost/operator/security-profiles-operator/default-profiles/nginx-1.19.1.json'
+    seccomp.security.alpha.kubernetes.io/pod: 'localhost/operator/security-profiles-operator/nginx-1.19.1.json'
     # Or one example within this directory
     # Please note the syntax:
-    # `localhost/operator/{namespace}/{configmap-name}/{profile-name}`
-    # seccomp.security.alpha.kubernetes.io/pod: 'localhost/operator/default/generic/profile-allow-unsafe.json'
+    # `localhost/operator/{namespace}/{profile-name}`
+    # seccomp.security.alpha.kubernetes.io/pod: 'localhost/operator/default/profile-allow-unsafe.json'
 spec:
   containers:
   - name: test-container
@@ -16,5 +16,5 @@ spec:
     # securityContext:
       # seccompProfile:
         # type: Localhost
-        # localhostProfile: operator/security-profiles-operator/default-profiles/nginx-1.19.1.json
+        # localhostProfile: operator/security-profiles-operator/nginx-1.19.1.json
     image: nginx:1.19.1
diff --git a/examples/seccompprofile.yaml b/examples/seccompprofile.yaml
index a0b583477..1a6c9c920 100644
--- a/examples/seccompprofile.yaml
+++ b/examples/seccompprofile.yaml
@@ -7,7 +7,6 @@ metadata:
     description: "Blocks all syscalls."
 spec:
   defaultAction: "SCMP_ACT_ERRNO"
-  targetWorkload: "generic"
 ---
 apiVersion: security-profiles-operator.x-k8s.io/v1alpha1
 kind: SeccompProfile
@@ -17,7 +16,6 @@ metadata:
     description: "UNSAFE: Allows all syscalls whilst logging their use. Similar to running as unconfined in terms of enforcement."
 spec:
   defaultAction: "SCMP_ACT_LOG"
-  targetWorkload: "generic"
 ---
 apiVersion: security-profiles-operator.x-k8s.io/v1alpha1
 kind: SeccompProfile
@@ -27,7 +25,6 @@ metadata:
     description: "UNSAFE: Allows all syscalls. Similar to running as unconfined as it provides no enforcement."
 spec:
   defaultAction: "SCMP_ACT_ALLOW"
-  targetWorkload: "generic"
 ---
 apiVersion: security-profiles-operator.x-k8s.io/v1alpha1
 kind: SeccompProfile
@@ -37,7 +34,6 @@ metadata:
     description: "Enables complain mode whilst blocking high-risk syscalls. Some essential syscalls are allowed to decrease log noise."
 spec:
   defaultAction: SCMP_ACT_LOG
-  targetWorkload: "generic"
   architectures:
   - SCMP_ARCH_X86_64
   syscalls:
diff --git a/installation-usage.md b/installation-usage.md
index 74c0b97da..46dbf1f6a 100644
--- a/installation-usage.md
+++ b/installation-usage.md
@@ -39,7 +39,6 @@ metadata:
   name: profile1
 spec:
   defaultAction: SCMP_ACT_LOG
-  targetWorkload: custom-profiles
 ```
 
 This seccomp profile will be saved at the path:
@@ -135,7 +134,6 @@ metadata:
   name: profile1
 spec:
   defaultAction: SCMP_ACT_ERRNO
-  targetWorkload: custom-profiles
   baseProfileName: runc-v1.0.0-rc92
   syscalls:
     - action: SCMP_ACT_ALLOW
@@ -272,10 +270,9 @@ Spec:
       …[other syscalls]…
       mkdir
       …[other syscalls]…
-  Target Workload: my-pod
 Status:
-  Localhost Profile:  operator/security-profiles-operator/my-pod/test-recording-my-pod.json
-  Path:               /var/lib/kubelet/seccomp/operator/security-profiles-operator/my-pod/test-recording-my-pod.json
+  Localhost Profile:  operator/security-profiles-operator/test-recording-my-pod.json
+  Path:               /var/lib/kubelet/seccomp/operator/security-profiles-operator/test-recording-my-pod.json
   Status:             Active
 Events:
   Type    Reason                 Age                From             Message
@@ -333,8 +330,8 @@ two seccomp profiles for each container:
 ```
 > kubectl get sp -o wide
 NAME              STATUS   AGE   LOCALHOSTPROFILE
-recording-nginx   Active   32s   operator/default/my-pod/recording-nginx.json
-recording-redis   Active   32s   operator/default/my-pod/recording-redis.json
+recording-nginx   Active   32s   operator/default/recording-nginx.json
+recording-redis   Active   32s   operator/default/recording-redis.json
 ```
 
 Please note that we encourage you to only use this recording approach for
@@ -366,7 +363,7 @@ I1019 19:34:14.942464       1 main.go:90] setup "msg"="starting security-profile
 I1019 19:34:15.348389       1 listener.go:44] controller-runtime/metrics "msg"="metrics server is starting to listen"  "addr"=":8080"
 I1019 19:34:15.349076       1 main.go:126] setup "msg"="starting manager"
 I1019 19:34:15.349449       1 internal.go:391] controller-runtime/manager "msg"="starting metrics server"  "path"="/metrics"
-I1019 19:34:15.350201       1 controller.go:142] controller "msg"="Starting EventSource" "controller"="profile" "reconcilerGroup"="security-profiles-operator.x-k8s.io" "reconcilerKind"="SeccompProfile" "source"={"Type":{"metadata":{"creationTimestamp":null},"spec":{"targetWorkload":"","defaultAction":""}}}
+I1019 19:34:15.350201       1 controller.go:142] controller "msg"="Starting EventSource" "controller"="profile" "reconcilerGroup"="security-profiles-operator.x-k8s.io" "reconcilerKind"="SeccompProfile" "source"={"Type":{"metadata":{"creationTimestamp":null},"spec":{"defaultAction":""}}}
 I1019 19:34:15.450674       1 controller.go:149] controller "msg"="Starting Controller" "controller"="profile" "reconcilerGroup"="security-profiles-operator.x-k8s.io" "reconcilerKind"="SeccompProfile"
 I1019 19:34:15.450757       1 controller.go:176] controller "msg"="Starting workers" "controller"="profile" "reconcilerGroup"="security-profiles-operator.x-k8s.io" "reconcilerKind"="SeccompProfile" "worker count"=1
 I1019 19:34:15.453102       1 profile.go:148] profile "msg"="Reconciled profile from SeccompProfile" "namespace"="security-profiles-operator" "profile"="nginx-1.19.1" "name"="nginx-1.19.1" "resource version"="728"
diff --git a/internal/pkg/daemon/profilerecorder/profilerecorder.go b/internal/pkg/daemon/profilerecorder/profilerecorder.go
index 029c14b31..5e9c09cb2 100644
--- a/internal/pkg/daemon/profilerecorder/profilerecorder.go
+++ b/internal/pkg/daemon/profilerecorder/profilerecorder.go
@@ -224,9 +224,6 @@ func (r *RecorderReconciler) collectProfile(ctx context.Context, name types.Name
 				Name:      profileName,
 				Namespace: name.Namespace,
 			},
-			Spec: v1alpha1.SeccompProfileSpec{
-				TargetWorkload: name.Name,
-			},
 		}
 		res, err := controllerutil.CreateOrUpdate(ctx, r.client, profile,
 			func() error {
diff --git a/internal/pkg/daemon/seccompprofile/seccompprofile.go b/internal/pkg/daemon/seccompprofile/seccompprofile.go
index bffae2b8e..9788cf7f5 100644
--- a/internal/pkg/daemon/seccompprofile/seccompprofile.go
+++ b/internal/pkg/daemon/seccompprofile/seccompprofile.go
@@ -273,7 +273,7 @@ func (r *Reconciler) reconcileSeccompProfile(
 		return reconcile.Result{RequeueAfter: wait}, nil
 	}
 
-	profilePath, err := GetProfilePath(profileName, sp.ObjectMeta.Namespace, sp.Spec.TargetWorkload)
+	profilePath, err := GetProfilePath(profileName, sp.ObjectMeta.Namespace)
 	if err != nil {
 		l.Error(err, "cannot get profile path")
 		r.record.Event(sp, event.Warning(reasonCannotGetProfilePath, err))
@@ -393,7 +393,7 @@ func (r *PodReconciler) Reconcile(_ context.Context, req reconcile.Request) (rec
 	for _, profileIndex := range getSeccompProfilesFromPod(pod) {
 		profileElements := strings.Split(profileIndex, "/")
 		profileNamespace := profileElements[1]
-		profileName := strings.TrimSuffix(profileElements[3], ".json")
+		profileName := strings.TrimSuffix(profileElements[2], ".json")
 		seccompProfile := &v1alpha1.SeccompProfile{}
 		if err := r.client.Get(ctx, namespacedName(profileName, profileNamespace), seccompProfile); err != nil {
 			logger.Error(err, "could not get seccomp profile for pod")
@@ -411,7 +411,7 @@ func (r *PodReconciler) Reconcile(_ context.Context, req reconcile.Request) (rec
 // it has a finalizer indicating it is in use to prevent it from being deleted.
 func (r *PodReconciler) updatePodReferences(ctx context.Context, sp *v1alpha1.SeccompProfile) error {
 	linkedPods := &corev1.PodList{}
-	profileReference := fmt.Sprintf("operator/%s/%s/%s.json", sp.GetNamespace(), sp.Spec.TargetWorkload, sp.GetName())
+	profileReference := fmt.Sprintf("operator/%s/%s.json", sp.GetNamespace(), sp.GetName())
 	err := r.client.List(ctx, linkedPods, client.MatchingFields{spOwnerKey: profileReference})
 	if ignoreNotFound(err) != nil {
 		return errors.Wrap(err, "listing pods to update seccompProfile")
@@ -485,7 +485,7 @@ func getSeccompProfilesFromPod(pod *corev1.Pod) []string {
 
 // isOperatorSeccompProfile checks whether a corev1.SeccompProfile object belongs to the operator.
 // SeccompProfiles controlled by the operator are of type "Localhost" and have a path of the form
-// "operator/namespace/workload-group/profile-name.json".
+// "operator/namespace/profile-name.json".
 func isOperatorSeccompProfile(sp *corev1.SeccompProfile) bool {
 	if sp == nil || sp.Type != "Localhost" {
 		return false
@@ -496,7 +496,7 @@ func isOperatorSeccompProfile(sp *corev1.SeccompProfile) bool {
 	if !strings.HasSuffix(*sp.LocalhostProfile, ".json") {
 		return false
 	}
-	pathParts := 4
+	const pathParts = 3
 	return len(strings.Split(*sp.LocalhostProfile, "/")) == pathParts
 }
 
@@ -543,7 +543,7 @@ func removeFinalizer(ctx context.Context, c client.Client, sp *v1alpha1.SeccompP
 }
 
 func handleDeletion(sp *v1alpha1.SeccompProfile, l logr.Logger) error {
-	profilePath, err := GetProfilePath(sp.GetName(), sp.GetNamespace(), sp.Spec.TargetWorkload)
+	profilePath, err := GetProfilePath(sp.GetName(), sp.GetNamespace())
 	if err != nil {
 		return err
 	}
@@ -570,14 +570,13 @@ func saveProfileOnDisk(fileName string, contents []byte) error {
 }
 
 // GetProfilePath returns the full path for the provided profile name and config.
-func GetProfilePath(profileName, namespace, subdir string) (string, error) {
+func GetProfilePath(profileName, namespace string) (string, error) {
 	if filepath.Ext(profileName) != extJSON {
 		profileName += extJSON
 	}
 	return path.Join(
 		config.ProfilesRootPath,
 		filepath.Base(namespace),
-		filepath.Base(subdir),
 		filepath.Base(profileName),
 	), nil
 }
diff --git a/internal/pkg/manager/spod/bindata/default_profiles.go b/internal/pkg/manager/spod/bindata/default_profiles.go
index df6abf378..3f26afb86 100644
--- a/internal/pkg/manager/spod/bindata/default_profiles.go
+++ b/internal/pkg/manager/spod/bindata/default_profiles.go
@@ -42,9 +42,8 @@ func DefaultProfiles() []*v1alpha1.SeccompProfile {
 				},
 			},
 			Spec: v1alpha1.SeccompProfileSpec{
-				TargetWorkload: "default-profiles",
-				DefaultAction:  seccomp.ActErrno,
-				Architectures:  []*v1alpha1.Arch{&archX8664, &archX86, &archX32},
+				DefaultAction: seccomp.ActErrno,
+				Architectures: []*v1alpha1.Arch{&archX8664, &archX86, &archX32},
 				Syscalls: []*v1alpha1.Syscall{
 					{
 						Action: seccomp.ActAllow,


Test patch:
diff --git a/internal/pkg/daemon/seccompprofile/seccompprofile_test.go b/internal/pkg/daemon/seccompprofile/seccompprofile_test.go
index 23af8d904..2a89ca53c 100644
--- a/internal/pkg/daemon/seccompprofile/seccompprofile_test.go
+++ b/internal/pkg/daemon/seccompprofile/seccompprofile_test.go
@@ -145,7 +145,7 @@ func TestSaveProfileOnDisk(t *testing.T) {
 	}{
 		{
 			name:        "CreateDirsAndWriteFile",
-			fileName:    path.Join(dir, "/seccomp/operator/namespace/sp/filename.json"),
+			fileName:    path.Join(dir, "/seccomp/operator/namespace/filename.json"),
 			contents:    "some content",
 			fileCreated: true,
 		},
@@ -209,67 +209,52 @@ func TestGetProfilePath(t *testing.T) {
 	}{
 		{
 			name: "AppendNamespaceAndProfile",
-			want: path.Join(config.ProfilesRootPath, "config-namespace", "config-target", "file.json"),
+			want: path.Join(config.ProfilesRootPath, "config-namespace", "file.json"),
 			sp: &v1alpha1.SeccompProfile{
 				ObjectMeta: metav1.ObjectMeta{
 					Name:      "file.json",
 					Namespace: "config-namespace",
 				},
-				Spec: v1alpha1.SeccompProfileSpec{
-					TargetWorkload: "config-target",
-				},
 			},
 		},
 		{
 			name: "BlockTraversalAtProfileName",
-			want: path.Join(config.ProfilesRootPath, "ns", "config-target", "file.json"),
+			want: path.Join(config.ProfilesRootPath, "ns", "file.json"),
 			sp: &v1alpha1.SeccompProfile{
 				ObjectMeta: metav1.ObjectMeta{
 					Name:      "../../../../../file.json",
 					Namespace: "ns",
 				},
-				Spec: v1alpha1.SeccompProfileSpec{
-					TargetWorkload: "config-target",
-				},
 			},
 		},
 		{
 			name: "BlockTraversalAtTargetName",
-			want: path.Join(config.ProfilesRootPath, "ns", "config-target", "file.json"),
+			want: path.Join(config.ProfilesRootPath, "ns", "file.json"),
 			sp: &v1alpha1.SeccompProfile{
 				ObjectMeta: metav1.ObjectMeta{
 					Name:      "file.json",
 					Namespace: "ns",
 				},
-				Spec: v1alpha1.SeccompProfileSpec{
-					TargetWorkload: "../../../../../config-target",
-				},
 			},
 		},
 		{
 			name: "BlockTraversalAtSPNamespace",
-			want: path.Join(config.ProfilesRootPath, "ns", "config-target", "file.json"),
+			want: path.Join(config.ProfilesRootPath, "ns", "file.json"),
 			sp: &v1alpha1.SeccompProfile{
 				ObjectMeta: metav1.ObjectMeta{
 					Name:      "file.json",
 					Namespace: "../../../../../ns",
 				},
-				Spec: v1alpha1.SeccompProfileSpec{
-					TargetWorkload: "config-target",
-				},
 			},
 		},
 		{
 			name: "AppendExtension",
-			want: path.Join(config.ProfilesRootPath, "config-namespace", "config-target", "file.json"),
+			want: path.Join(config.ProfilesRootPath, "config-namespace", "file.json"),
 			sp: &v1alpha1.SeccompProfile{
 				ObjectMeta: metav1.ObjectMeta{
 					Name:      "file",
 					Namespace: "config-namespace",
 				},
-				Spec: v1alpha1.SeccompProfileSpec{
-					TargetWorkload: "config-target",
-				},
 			},
 		},
 	}
@@ -279,7 +264,7 @@ func TestGetProfilePath(t *testing.T) {
 		t.Run(tc.name, func(t *testing.T) {
 			t.Parallel()
 
-			got, gotErr := GetProfilePath(tc.sp.ObjectMeta.Name, tc.sp.ObjectMeta.Namespace, tc.sp.Spec.TargetWorkload)
+			got, gotErr := GetProfilePath(tc.sp.ObjectMeta.Name, tc.sp.ObjectMeta.Namespace)
 			if tc.wantErr == "" {
 				require.NoError(t, gotErr)
 			} else {
@@ -472,8 +457,8 @@ func TestUnionSyscalls(t *testing.T) {
 func TestGetSeccompProfilesFromPod(t *testing.T) {
 	t.Parallel()
 
-	profilePath := "operator/default/example-profiles/test.json"
-	profilePath2 := "operator/default/example-profiles/test2.json"
+	profilePath := "operator/default/test.json"
+	profilePath2 := "operator/default/test2.json"
 	cases := []struct {
 		name string
 		pod  corev1.Pod
@@ -616,11 +601,11 @@ func TestGetSeccompProfilesFromPod(t *testing.T) {
 	}{
 		{
 			name:    "NoSuffix",
-			profile: "operator/default/example-profiles/test",
+			profile: "operator/default/test",
 		},
 		{
 			name:    "BadSuffix",
-			profile: "operator/default/example-profiles/test.js",
+			profile: "operator/default/test.js",
 		},
 		{
 			name:    "WrongPath",
diff --git a/test/tc_base_profiles_test.go b/test/tc_base_profiles_test.go
index 7ef8dfebd..3b977b50f 100644
--- a/test/tc_base_profiles_test.go
+++ b/test/tc_base_profiles_test.go
@@ -39,7 +39,6 @@ metadata:
   name: hello
 spec:
   defaultAction: SCMP_ACT_ERRNO
-  targetWorkload: hello
   baseProfileName: %s
   syscalls:
   - action: SCMP_ACT_ALLOW
@@ -62,7 +61,7 @@ spec:
   securityContext:
     seccompProfile:
       type: Localhost
-      localhostProfile: operator/%s/hello/hello.json
+      localhostProfile: operator/%s/hello.json
   restartPolicy: Never
 `
 	e.kubectl("create", "-f", baseProfilePath)
diff --git a/test/tc_default_profiles_test.go b/test/tc_default_profiles_test.go
index 81c993fd8..78e73dd0e 100644
--- a/test/tc_default_profiles_test.go
+++ b/test/tc_default_profiles_test.go
@@ -87,7 +87,7 @@ func (e *e2e) verifyBaseProfileContent(node string, cm *v1.ConfigMap) {
 func (e *e2e) verifyCRDProfileContent(node string, sp *v1alpha1.SeccompProfile) {
 	e.logf("Verifying %s profile on node %s", sp.Name, node)
 	name := sp.Name
-	profilePath, err := seccompprofile.GetProfilePath(name, sp.ObjectMeta.Namespace, sp.Spec.TargetWorkload)
+	profilePath, err := seccompprofile.GetProfilePath(name, sp.ObjectMeta.Namespace)
 	e.Nil(err)
 	catOutput := e.execNode(node, "cat", profilePath)
 	output := seccompprofile.OutputProfile{}
diff --git a/test/tc_delete_profiles_test.go b/test/tc_delete_profiles_test.go
index 92cce8bc1..3fa5ba4b3 100644
--- a/test/tc_delete_profiles_test.go
+++ b/test/tc_delete_profiles_test.go
@@ -33,7 +33,6 @@ metadata:
   name: delete-me
 spec:
   defaultAction: "SCMP_ACT_ALLOW"
-  targetWorkload: "example-profiles"
 `
 		deleteProfileName = "delete-me"
 		deletePod         = `
@@ -48,7 +47,7 @@ spec:
   securityContext:
     seccompProfile:
       type: Localhost
-      localhostProfile: operator/%s/example-profiles/delete-me.json
+      localhostProfile: operator/%s/delete-me.json
 `
 		deletePodSecurityContextInContainer = `
 apiVersion: v1
@@ -62,7 +61,7 @@ spec:
     securityContext:
       seccompProfile:
         type: Localhost
-        localhostProfile: operator/%s/example-profiles/delete-me.json
+        localhostProfile: operator/%s/delete-me.json
 `
 		deletePodSecurityContextInInitContainer = `
 apiVersion: v1
@@ -76,7 +75,7 @@ spec:
     securityContext:
       seccompProfile:
         type: Localhost
-        localhostProfile: operator/%s/example-profiles/delete-me.json
+        localhostProfile: operator/%s/delete-me.json
   containers:
   - name: test-container
     image: quay.io/security-profiles-operator/test-nginx:1.19.1
@@ -87,7 +86,7 @@ kind: Pod
 metadata:
   name: test-pod
   annotations:
-    seccomp.security.alpha.kubernetes.io/pod: 'localhost/operator/%s/example-profiles/delete-me.json'
+    seccomp.security.alpha.kubernetes.io/pod: 'localhost/operator/%s/delete-me.json'
 spec:
   containers:
   - name: test-container
@@ -101,7 +100,7 @@ spec:
 
 	namespace := e.getCurrentContextNamespace(defaultNamespace)
 	sp := e.getSeccompProfile(deleteProfileName, namespace)
-	path, err := seccompprofile.GetProfilePath(deleteProfileName, sp.ObjectMeta.Namespace, sp.Spec.TargetWorkload)
+	path, err := seccompprofile.GetProfilePath(deleteProfileName, sp.ObjectMeta.Namespace)
 	e.Nil(err)
 
 	e.logf("Verifying profile exists")
diff --git a/test/tc_profilebindings_test.go b/test/tc_profilebindings_test.go
index 3d3b2d3e9..6174d2307 100644
--- a/test/tc_profilebindings_test.go
+++ b/test/tc_profilebindings_test.go
@@ -99,7 +99,7 @@ spec:
 		"get", "pod", "hello",
 		"--output", "jsonpath={.spec.containers[0].securityContext.seccompProfile.localhostProfile}",
 	)
-	e.Equal(fmt.Sprintf("operator/%s/generic/profile-allow-unsafe.json", namespace), output)
+	e.Equal(fmt.Sprintf("operator/%s/profile-allow-unsafe.json", namespace), output)
 
 	e.logf("Testing that profile binding has pod reference")
 	output = e.kubectl("get", "profilebinding", "hello-binding", "--output", "jsonpath={.status.activeWorkloads[0]}")