From 98c7a11b904def633fa3871d3997bd404e40c5eb Mon Sep 17 00:00:00 2001 From: Pranita Turrey <64246126+pranitaT@users.noreply.github.com> Date: Fri, 8 Nov 2024 18:34:22 +0530 Subject: [PATCH] MULTIARCH-4654: Enabled the Security Profiles Operator for ppc64le, added fixes for seccomp and SELinux profiles, and verified functionality with logenricher. --- Dockerfile.ubi | 6 +- ...rofiles-operator-profile_v1_configmap.yaml | 1 + ...operator-profile_v1_configmap_ppc64le.yaml | 169 +++ ...perator.clusterserviceversion_ppc64le.yaml | 993 ++++++++++++++++++ deploy/base/clusterserviceversion.yaml | 1 + .../profiles/security-profiles-operator.json | 4 +- deploy/helm/templates/static-resources.yaml | 4 +- deploy/namespace-operator.yaml | 4 +- deploy/openshift-dev.yaml | 4 +- deploy/openshift-downstream.yaml | 4 +- deploy/operator.yaml | 4 +- deploy/webhook-operator.yaml | 4 +- hack/image-cross.sh | 2 +- .../pkg/daemon/bpfrecorder/bpfrecorder_alt.go | 20 + .../bpfrecorder/bpfrecorder_linux_common.go | 20 + .../daemon/bpfrecorder/bpfrecorder_stub.go | 32 + .../daemon/bpfrecorder/bpfrecorder_utils.go | 42 + .../daemon/seccompprofile/seccompprofile.go | 23 +- 18 files changed, 1322 insertions(+), 15 deletions(-) create mode 100644 bundle/manifests/security-profiles-operator-profile_v1_configmap_ppc64le.yaml create mode 100644 bundle/manifests/security-profiles-operator.clusterserviceversion_ppc64le.yaml create mode 100644 internal/pkg/daemon/bpfrecorder/bpfrecorder_alt.go create mode 100644 internal/pkg/daemon/bpfrecorder/bpfrecorder_linux_common.go create mode 100644 internal/pkg/daemon/bpfrecorder/bpfrecorder_stub.go create mode 100644 internal/pkg/daemon/bpfrecorder/bpfrecorder_utils.go diff --git a/Dockerfile.ubi b/Dockerfile.ubi index aeb9b057a0..f2695d85cc 100644 --- a/Dockerfile.ubi +++ b/Dockerfile.ubi @@ -23,7 +23,8 @@ USER root WORKDIR /work RUN dnf install -y \ - libseccomp-devel + libseccomp-devel \ + libbpf ADD . /work RUN mkdir -p build @@ -42,7 +43,8 @@ ARG version USER root RUN microdnf install -y \ - libseccomp + libseccomp\ + libbpf LABEL name="Security Profiles Operator" \ version=$version \ diff --git a/bundle/manifests/security-profiles-operator-profile_v1_configmap.yaml b/bundle/manifests/security-profiles-operator-profile_v1_configmap.yaml index b2b90ca831..60a4bff60d 100644 --- a/bundle/manifests/security-profiles-operator-profile_v1_configmap.yaml +++ b/bundle/manifests/security-profiles-operator-profile_v1_configmap.yaml @@ -91,6 +91,7 @@ data: "setuid", "sigaltstack", "socket", + "stat", # Adding 'stat' to support mkdirall functionality "statfs", "tgkill", "time", diff --git a/bundle/manifests/security-profiles-operator-profile_v1_configmap_ppc64le.yaml b/bundle/manifests/security-profiles-operator-profile_v1_configmap_ppc64le.yaml new file mode 100644 index 0000000000..666d129551 --- /dev/null +++ b/bundle/manifests/security-profiles-operator-profile_v1_configmap_ppc64le.yaml @@ -0,0 +1,169 @@ +apiVersion: v1 +data: + security-profiles-operator.json: | + { + "defaultAction": "SCMP_ACT_LOG", + "architectures": [ + "SCMP_ARCH_PPC64LE" + ], + "syscalls": [ + { + "names": [ + "accept4", + "access", + "arch_prctl", + "bind", + "brk", + "bpf", + "capget", + "capset", + "chdir", + "clock_gettime", + "clone", + "clone3", + "close", + "connect", + "epoll_create1", + "epoll_ctl", + "epoll_pwait", + "epoll_wait", + "execve", + "exit", + "exit_group", + "fchown", + "fcntl", + "flock", + "fstat", + "fstatfs", + "fsync", + "futex", + "getcwd", + "getdents64", + "getgid", + "getpeername", + "getpgrp", + "getpid", + "getppid", + "getrandom", + "getrlimit", + "getsockname", + "getsockopt", + "gettid", + "getuid", + "inotify_add_watch", + "inotify_init1", + "listen", + "lseek", + "madvise", + "membarrier", + "mkdirat", + "mlock", + "mmap", + "mprotect", + "munmap", + "nanosleep", + "newfstatat", + "open", + "openat", + "pipe2", + "prctl", + "pread64", + "prlimit64", + "read", + "readlink", + "readlinkat", + "renameat", + "rseq", + "rt_sigaction", + "rt_sigprocmask", + "rt_sigreturn", + "sched_getaffinity", + "sched_yield", + "set_robust_list", + "set_tid_address", + "setgid", + "setgroups", + "setsockopt", + "setuid", + "sigaltstack", + "socket", + "stat", # Adding 'stat' to support mkdirall functionality + "tgkill", + "time", + "uname", + "unlinkat", + "write" + ], + "action": "SCMP_ACT_ALLOW" + } + ] + } + selinuxd-image-mapping.json: | + [ + { + "regex":"(.*)(CoreOS).*([\\d+])\\.8[\\d+]\\.(.*)", + "imageFromVar":"RELATED_IMAGE_SELINUXD_EL8" + }, + { + "regex":"(.*)(CoreOS).*([\\d+])\\.9[\\d+]\\.(.*)", + "imageFromVar":"RELATED_IMAGE_SELINUXD_EL9" + }, + { + "regex":"Fedora \\d+", + "imageFromVar":"RELATED_IMAGE_SELINUXD_FEDORA" + } + ] + selinuxd.cil: | + (block selinuxd + (blockinherit container) + (allow process process ( capability ( dac_override dac_read_search lease audit_write audit_control ))) + + (allow process default_context_t ( dir ( add_name create getattr ioctl lock open read remove_name rmdir search setattr write ))) + (allow process default_context_t ( fifo_file ( getattr read write append ioctl lock open ))) + (allow process default_context_t ( file ( append create getattr ioctl lock map open read rename setattr unlink write ))) + (allow process default_context_t ( sock_file ( append getattr open read write ))) + (allow process etc_t ( dir ( add_name create getattr ioctl lock open read remove_name rmdir search setattr write watch ))) + (allow process etc_t ( fifo_file ( getattr read write append ioctl lock open ))) + (allow process etc_t ( file ( append create getattr ioctl lock map open read rename setattr unlink write ))) + (allow process etc_t ( sock_file ( append getattr open read write ))) + (allow process file_context_t ( dir ( add_name create getattr ioctl lock open read remove_name rmdir search setattr write ))) + (allow process file_context_t ( fifo_file ( getattr read write append ioctl lock open ))) + (allow process file_context_t ( file ( append create getattr ioctl lock map open read rename setattr unlink write ))) + (allow process file_context_t ( sock_file ( append getattr open read write ))) + (allow process security_t ( file ( append create getattr ioctl lock map open read rename setattr unlink write ))) + (allow process security_t ( security ( load_policy ))) + (allow process selinux_config_t ( dir ( add_name create getattr ioctl lock open read remove_name rename rmdir search setattr write ))) + (allow process selinux_config_t ( fifo_file ( getattr read write append ioctl lock open ))) + (allow process selinux_config_t ( file ( append create getattr ioctl lock map open read rename setattr unlink write ))) + (allow process selinux_config_t ( sock_file ( append getattr open read write ))) + (allow process selinux_login_config_t ( dir ( add_name create getattr ioctl lock open read remove_name rmdir search setattr write ))) + (allow process selinux_login_config_t ( fifo_file ( getattr read write append ioctl lock open ))) + (allow process selinux_login_config_t ( file ( append create getattr ioctl lock map open read rename setattr unlink write ))) + (allow process selinux_login_config_t ( sock_file ( append getattr open read write ))) + (allow process semanage_read_lock_t ( dir ( add_name create getattr ioctl lock open read remove_name rmdir search setattr write ))) + (allow process semanage_read_lock_t ( fifo_file ( getattr read write append ioctl lock open ))) + (allow process semanage_read_lock_t ( file ( append create getattr ioctl lock map open read rename setattr unlink write ))) + (allow process semanage_read_lock_t ( sock_file ( append getattr open read write ))) + (allow process semanage_store_t ( dir ( add_name create getattr ioctl lock open read rename remove_name rmdir search setattr write ))) + (allow process semanage_store_t ( fifo_file ( getattr read write append ioctl lock open ))) + (allow process semanage_store_t ( file ( append create getattr ioctl lock map open read rename setattr unlink write ))) + (allow process semanage_store_t ( sock_file ( append getattr open read write ))) + (allow process semanage_trans_lock_t ( dir ( add_name create getattr ioctl lock open read remove_name rmdir search setattr write ))) + (allow process semanage_trans_lock_t ( fifo_file ( getattr read write append ioctl lock open ))) + (allow process semanage_trans_lock_t ( file ( append create getattr ioctl lock map open read rename setattr unlink write ))) + (allow process semanage_trans_lock_t ( sock_file ( append getattr open read write ))) + (allow process sysfs_t ( dir ( add_name create getattr ioctl lock open read remove_name rmdir search setattr write ))) + (allow process sysfs_t ( fifo_file ( getattr read write append ioctl lock open ))) + (allow process sysfs_t ( file ( append create getattr ioctl lock map open read rename setattr unlink write ))) + (allow process sysfs_t ( sock_file ( append getattr open read write ))) + ) + selinuxrecording.cil: | + (block selinuxrecording + (blockinherit container) + (typepermissive process) + ) +kind: ConfigMap +metadata: + labels: + app: security-profiles-operator + name: security-profiles-operator-profile diff --git a/bundle/manifests/security-profiles-operator.clusterserviceversion_ppc64le.yaml b/bundle/manifests/security-profiles-operator.clusterserviceversion_ppc64le.yaml new file mode 100644 index 0000000000..1b55134ab5 --- /dev/null +++ b/bundle/manifests/security-profiles-operator.clusterserviceversion_ppc64le.yaml @@ -0,0 +1,993 @@ +apiVersion: operators.coreos.com/v1alpha1 +kind: ClusterServiceVersion +metadata: + annotations: + alm-examples: |- + [ + { + "apiVersion": "security-profiles-operator.x-k8s.io/v1alpha1", + "kind": "AppArmorProfile", + "metadata": { + "annotations": { + "description": "Block writing to any files in the disk." + }, + "name": "test-profile" + }, + "spec": { + "policy": "#include \u003ctunables/global\u003e\n\nprofile test-profile flags=(attach_disconnected) {\n #include \u003cabstractions/base\u003e\n\n file,\n\n # Deny all file writes.\n deny /** w,\n}\n" + } + }, + { + "apiVersion": "security-profiles-operator.x-k8s.io/v1alpha1", + "kind": "SecurityProfilesOperatorDaemon", + "metadata": { + "name": "spod", + "namespace": "security-profiles-operator" + }, + "spec": { + "enableAppArmor": false, + "enableLogEnricher": false, + "enableSelinux": false + } + }, + { + "apiVersion": "security-profiles-operator.x-k8s.io/v1alpha1", + "kind": "ProfileRecording", + "metadata": { + "name": "test-recording" + }, + "spec": { + "kind": "SeccompProfile", + "podSelector": { + "matchLabels": { + "app": "alpine" + } + }, + "recorder": "bpf" + } + }, + { + "apiVersion": "security-profiles-operator.x-k8s.io/v1alpha1", + "kind": "ProfileBinding", + "metadata": { + "name": "profile-binding" + }, + "spec": { + "image": "nginx:1.19.1", + "profileRef": { + "kind": "SeccompProfile", + "name": "profile-allow-unsafe" + } + } + }, + { + "apiVersion": "security-profiles-operator.x-k8s.io/v1alpha2", + "kind": "RawSelinuxProfile", + "metadata": { + "name": "errorlogger" + }, + "spec": { + "policy": "(blockinherit container)\n(allow process var_log_t ( dir ( open read getattr lock search ioctl add_name remove_name write ))) \n(allow process var_log_t ( file ( getattr read write append ioctl lock map open create ))) \n(allow process var_log_t ( sock_file ( getattr read write append open ))) \n" + } + }, + { + "apiVersion": "security-profiles-operator.x-k8s.io/v1beta1", + "kind": "SeccompProfile", + "metadata": { + "annotations": { + "description": "Blocks all syscalls." + }, + "name": "profile-block-all" + }, + "spec": { + "defaultAction": "SCMP_ACT_LOG" + } + }, + { + "apiVersion": "security-profiles-operator.x-k8s.io/v1beta1", + "kind": "SeccompProfile", + "metadata": { + "annotations": { + "description": "UNSAFE: Allows all syscalls whilst logging their use. Similar to running as unconfined in terms of enforcement." + }, + "name": "profile-complain-unsafe" + }, + "spec": { + "defaultAction": "SCMP_ACT_LOG" + } + }, + { + "apiVersion": "security-profiles-operator.x-k8s.io/v1beta1", + "kind": "SeccompProfile", + "metadata": { + "annotations": { + "description": "UNSAFE: Allows all syscalls. Similar to running as unconfined as it provides no enforcement." + }, + "name": "profile-allow-unsafe" + }, + "spec": { + "defaultAction": "SCMP_ACT_ALLOW" + } + }, + { + "apiVersion": "security-profiles-operator.x-k8s.io/v1beta1", + "kind": "SeccompProfile", + "metadata": { + "annotations": { + "description": "Enables complain mode whilst blocking high-risk syscalls. Some essential syscalls are allowed to decrease log noise." + }, + "name": "profile-complain-block-high-risk" + }, + "spec": { + "architectures": [ + "SCMP_ARCH_PPC64LE" + ], + "defaultAction": "SCMP_ACT_LOG", + "syscalls": [ + { + "action": "SCMP_ACT_ALLOW", + "names": [ + "exit", + "exit_group", + "futex", + "nanosleep" + ] + }, + { + "action": "SCMP_ACT_LOG", + "names": [ + "acct", + "add_key", + "bpf", + "clock_adjtime", + "clock_settime", + "create_module", + "delete_module", + "finit_module", + "get_kernel_syms", + "get_mempolicy", + "init_module", + "ioperm", + "iopl", + "kcmp", + "kexec_file_load", + "kexec_load", + "keyctl", + "lookup_dcookie", + "mbind", + "mount", + "move_pages", + "name_to_handle_at", + "nfsservctl", + "open_by_handle_at", + "perf_event_open", + "personality", + "pivot_root", + "process_vm_readv", + "process_vm_writev", + "ptrace", + "query_module", + "quotactl", + "reboot", + "request_key", + "set_mempolicy", + "setns", + "settimeofday", + "stime", + "swapoff", + "swapon", + "_sysctl", + "sysfs", + "umount2", + "umount", + "unshare", + "uselib", + "userfaultfd", + "ustat", + "vm86old", + "vm86" + ] + } + ] + } + }, + { + "apiVersion": "security-profiles-operator.x-k8s.io/v1alpha2", + "kind": "SelinuxProfile", + "metadata": { + "name": "errorlogger" + }, + "spec": { + "allow": { + "var_log_t": { + "dir": [ + "open", + "read", + "getattr", + "lock", + "search", + "ioctl", + "add_name", + "remove_name", + "write" + ], + "file": [ + "getattr", + "read", + "write", + "append", + "ioctl", + "lock", + "map", + "open", + "create" + ], + "sock_file": [ + "getattr", + "read", + "write", + "append", + "open" + ] + } + }, + "inherit": [ + { + "name": "container" + } + ] + } + } + ] + capabilities: Basic Install + categories: Security + containerImage: registry.k8s.io/security-profiles-operator/security-profiles-operator:v0.8.4 + olm.skipRange: '>=0.4.1 <0.8.5-dev' + operatorframework.io/cluster-monitoring: "true" + operatorframework.io/suggested-namespace: security-profiles-operator + operators.openshift.io/valid-subscription: '["OpenShift Kubernetes Engine", "OpenShift + Container Platform", "OpenShift Platform Plus"]' + operators.operatorframework.io/builder: operator-sdk-v1.25.0 + operators.operatorframework.io/project_layout: go.kubebuilder.io/v3 + name: security-profiles-operator.v0.8.5-dev + namespace: placeholder +spec: + apiservicedefinitions: {} + customresourcedefinitions: + owned: + - description: ProfileBinding is the Schema for the profilebindings API. + displayName: Profile Binding + kind: ProfileBinding + name: profilebindings.security-profiles-operator.x-k8s.io + version: v1alpha1 + - description: ProfileRecording is the Schema for the profilerecordings API. + displayName: Profile Recording + kind: ProfileRecording + name: profilerecordings.security-profiles-operator.x-k8s.io + version: v1alpha1 + - description: SeccompProfile is a cluster level specification for a seccomp profile. + See https://github.com/opencontainers/runtime-spec/blob/master/config-linux.md#seccomp + displayName: Seccomp Profile + kind: SeccompProfile + name: seccompprofiles.security-profiles-operator.x-k8s.io + version: v1beta1 + - description: SecurityProfileNodeStatus is a per-node status of a security profile + displayName: Security Profile Node Status + kind: SecurityProfileNodeStatus + name: securityprofilenodestatuses.security-profiles-operator.x-k8s.io + version: v1alpha1 + - description: SecurityProfilesOperatorDaemon is the Schema to configure the spod + deployment. + displayName: Security Profiles Operator Daemon + kind: SecurityProfilesOperatorDaemon + name: securityprofilesoperatordaemons.security-profiles-operator.x-k8s.io + version: v1alpha1 + - kind: RawSelinuxProfile + name: rawselinuxprofiles.security-profiles-operator.x-k8s.io + version: v1alpha2 + - description: SelinuxProfile is the Schema for the selinuxprofiles API. + displayName: Selinux Profile + kind: SelinuxProfile + name: selinuxprofiles.security-profiles-operator.x-k8s.io + version: v1alpha2 + - description: AppArmorProfile is a cluster level specification for an AppArmor + profile. + displayName: App Armor Profile + kind: AppArmorProfile + name: apparmorprofiles.security-profiles-operator.x-k8s.io + version: v1alpha1 + description: SPO is an operator which aims to make it easier for users to use SELinux, + seccomp and AppArmor in Kubernetes clusters + displayName: Security Profiles Operator + icon: + - base64data: PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTguNTEgMjU4LjUxIj48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6I2QxZDFkMTt9LmNscy0ye2ZpbGw6IzhkOGQ4Zjt9PC9zdHlsZT48L2RlZnM+PHRpdGxlPkFzc2V0IDQ8L3RpdGxlPjxnIGlkPSJMYXllcl8yIiBkYXRhLW5hbWU9IkxheWVyIDIiPjxnIGlkPSJMYXllcl8xLTIiIGRhdGEtbmFtZT0iTGF5ZXIgMSI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNMTI5LjI1LDIwQTEwOS4xLDEwOS4xLDAsMCwxLDIwNi40LDIwNi40LDEwOS4xLDEwOS4xLDAsMSwxLDUyLjExLDUyLjExLDEwOC40NSwxMDguNDUsMCwwLDEsMTI5LjI1LDIwbTAtMjBoMEM1OC4xNiwwLDAsNTguMTYsMCwxMjkuMjVIMGMwLDcxLjA5LDU4LjE2LDEyOS4yNiwxMjkuMjUsMTI5LjI2aDBjNzEuMDksMCwxMjkuMjYtNTguMTcsMTI5LjI2LTEyOS4yNmgwQzI1OC41MSw1OC4xNiwyMDAuMzQsMCwxMjkuMjUsMFoiLz48cGF0aCBjbGFzcz0iY2xzLTIiIGQ9Ik0xNzcuNTQsMTAzLjQxSDE0MS42NkwxNTQuOSw2NS43NmMxLjI1LTQuNC0yLjMzLTguNzYtNy4yMS04Ljc2SDEwMi45M2E3LjMyLDcuMzIsMCwwLDAtNy40LDZsLTEwLDY5LjYxYy0uNTksNC4xNywyLjg5LDcuODksNy40LDcuODloMzYuOUwxMTUuNTUsMTk3Yy0xLjEyLDQuNDEsMi40OCw4LjU1LDcuMjQsOC41NWE3LjU4LDcuNTgsMCwwLDAsNi40Ny0zLjQ4TDE4NCwxMTMuODVDMTg2Ljg2LDEwOS4yNCwxODMuMjksMTAzLjQxLDE3Ny41NCwxMDMuNDFaIi8+PC9nPjwvZz48L3N2Zz4= + mediatype: image/svg+xml + install: + spec: + clusterPermissions: + - rules: + - apiGroups: + - "" + resourceNames: + - security-profiles-operator-profile + resources: + - configmaps + verbs: + - get + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - services + verbs: + - create + - get + - list + - patch + - update + - watch + - apiGroups: + - admissionregistration.k8s.io + resources: + - mutatingwebhookconfigurations + verbs: + - create + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - daemonsets + - deployments + verbs: + - create + - get + - list + - patch + - update + - watch + - apiGroups: + - apps + resources: + - daemonsets/finalizers + - deployments + verbs: + - delete + - get + - patch + - update + - apiGroups: + - apps + resources: + - deployments + verbs: + - get + - list + - watch + - apiGroups: + - cert-manager.io + resources: + - certificates + - issuers + verbs: + - create + - get + - list + - patch + - update + - watch + - apiGroups: + - config.openshift.io + resources: + - clusteroperators + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - events + verbs: + - create + - apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch + - apiGroups: + - monitoring.coreos.com + resources: + - servicemonitors + verbs: + - create + - get + - list + - patch + - update + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - profilerecordings + verbs: + - get + - list + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - profilerecordings/finalizers + verbs: + - get + - list + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - rawselinuxprofiles + verbs: + - create + - get + - list + - patch + - update + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - rawselinuxprofiles/finalizers + verbs: + - delete + - get + - patch + - update + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - rawselinuxprofiles/status + verbs: + - get + - patch + - update + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - seccompprofiles + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - seccompprofiles/finalizers + verbs: + - delete + - get + - patch + - update + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - seccompprofiles/status + verbs: + - get + - patch + - update + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - securityprofilenodestatuses + verbs: + - delete + - get + - list + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - securityprofilesoperatordaemons + verbs: + - create + - get + - list + - update + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - securityprofilesoperatordaemons/finalizers + verbs: + - delete + - get + - patch + - update + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - securityprofilesoperatordaemons/status + verbs: + - get + - patch + - update + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - selinuxprofiles + verbs: + - create + - delete + - deletecollection + - get + - list + - patch + - update + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - selinuxprofiles/finalizers + verbs: + - delete + - get + - patch + - update + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - selinuxprofiles/status + verbs: + - get + - patch + - update + serviceAccountName: security-profiles-operator + - rules: + - apiGroups: + - "" + resources: + - events + verbs: + - create + - apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - profilebindings + verbs: + - create + - get + - list + - patch + - update + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - profilebindings/finalizers + verbs: + - delete + - get + - patch + - update + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - profilebindings/status + verbs: + - get + - patch + - update + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - profilerecordings + verbs: + - create + - get + - list + - patch + - update + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - profilerecordings/finalizers + verbs: + - delete + - get + - patch + - update + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - profilerecordings/status + verbs: + - get + - patch + - update + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - seccompprofiles + verbs: + - get + - list + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - selinuxprofiles + verbs: + - get + - list + - watch + serviceAccountName: spo-webhook + - rules: + - apiGroups: + - authentication.k8s.io + resources: + - subjectaccessreviews + - tokenreviews + verbs: + - create + - apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create + - apiGroups: + - "" + resources: + - events + verbs: + - create + - get + - patch + - update + - apiGroups: + - "" + resources: + - nodes + verbs: + - get + - list + - watch + - apiGroups: + - "" + resources: + - pods + verbs: + - get + - list + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - apparmorprofiles + verbs: + - create + - get + - list + - patch + - update + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - apparmorprofiles/finalizers + verbs: + - delete + - get + - patch + - update + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - apparmorprofiles/status + verbs: + - get + - patch + - update + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - profilerecordings + verbs: + - get + - list + - patch + - update + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - rawselinuxprofiles + verbs: + - create + - get + - list + - patch + - update + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - rawselinuxprofiles/finalizers + verbs: + - delete + - get + - patch + - update + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - rawselinuxprofiles/status + verbs: + - get + - patch + - update + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - seccompprofiles + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - seccompprofiles/finalizers + verbs: + - delete + - get + - patch + - update + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - seccompprofiles/status + verbs: + - get + - patch + - update + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - securityprofilenodestatuses + verbs: + - create + - delete + - get + - list + - patch + - update + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - securityprofilesoperatordaemons + verbs: + - get + - list + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - selinuxprofiles + verbs: + - create + - get + - list + - patch + - update + - watch + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - selinuxprofiles/finalizers + verbs: + - delete + - get + - patch + - update + - apiGroups: + - security-profiles-operator.x-k8s.io + resources: + - selinuxprofiles/status + verbs: + - get + - patch + - update + serviceAccountName: spod + deployments: + - label: + app: security-profiles-operator + name: security-profiles-operator + spec: + replicas: 3 + selector: + matchLabels: + app: security-profiles-operator + name: security-profiles-operator + strategy: {} + template: + metadata: + labels: + app: security-profiles-operator + name: security-profiles-operator + spec: + containers: + - args: + - manager + env: + - name: RELATED_IMAGE_RBAC_PROXY + value: gcr.io/kubebuilder/kube-rbac-proxy:v0.15.0 + - name: RELATED_IMAGE_SELINUXD + value: quay.io/pturrey/v1-security-profiles-operator/selinuxd:latest + - name: RELATED_IMAGE_SELINUXD_EL8 + value: quay.io/security-profiles-operator/selinuxd-el8:latest + - name: RELATED_IMAGE_SELINUXD_EL9 + value: quay.io/pturrey/v1-security-profiles-operator/selinuxd-el9:latest + - name: RELATED_IMAGE_SELINUXD_FEDORA + value: quay.io/security-profiles-operator/selinuxd-fedora:latest + - name: OPERATOR_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: WATCH_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.annotations['olm.targetNamespaces'] + - name: NODE_NAME + valueFrom: + fieldRef: + fieldPath: spec.nodeName + - name: KUBELET_DIR + value: /var/lib/kubelet + image: quay.io/pturrey/v1-security-profiles-operator:ppc64le + imagePullPolicy: Always + name: security-profiles-operator + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 250m + memory: 50Mi + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + securityContext: + seccompProfile: + type: RuntimeDefault + serviceAccountName: security-profiles-operator + tolerations: + - effect: NoSchedule + key: node-role.kubernetes.io/master + operator: Exists + - effect: NoSchedule + key: node-role.kubernetes.io/control-plane + operator: Exists + - effect: NoExecute + key: node.kubernetes.io/not-ready + operator: Exists + permissions: + - rules: + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - get + - update + - apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + verbs: + - use + serviceAccountName: security-profiles-operator + - rules: + - apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - create + - apiGroups: + - coordination.k8s.io + resourceNames: + - security-profiles-operator-webhook-lock + resources: + - leases + verbs: + - get + - patch + - update + - apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + verbs: + - use + serviceAccountName: spo-webhook + - rules: + - apiGroups: + - security.openshift.io + resources: + - securitycontextconstraints + verbs: + - use + serviceAccountName: spod + strategy: deployment + installModes: + - supported: true + type: OwnNamespace + - supported: true + type: SingleNamespace + - supported: true + type: MultiNamespace + - supported: true + type: AllNamespaces + keywords: + - security + - selinux + - seccomp + - apparmor + - ebpf + links: + - name: Security Profiles Operator + url: https://github.com/kubernetes-sigs/security-profiles-operator + maintainers: + - email: dev@kubernetes.io + name: Kubernetes upstream + maturity: alpha + provider: + name: Kubernetes SIGs + url: https://github.com/kubernetes-sigs + relatedImages: + - image: gcr.io/kubebuilder/kube-rbac-proxy:v0.15.0 + name: rbac-proxy + - image: quay.io/pturrey/v1-security-profiles-operator/selinuxd:latest + name: selinuxd + - image: quay.io/security-profiles-operator/selinuxd-el8:latest + name: selinuxd-el8 + - image: quay.io/pturrey/v1-security-profiles-operator/selinuxd-el9:latest + name: selinuxd-el9 + - image: quay.io/security-profiles-operator/selinuxd-fedora:latest + name: selinuxd-fedora + replaces: security-profiles-operator.v0.8.3 + version: 0.8.5-dev diff --git a/deploy/base/clusterserviceversion.yaml b/deploy/base/clusterserviceversion.yaml index 92779d5613..8bd3feed50 100644 --- a/deploy/base/clusterserviceversion.yaml +++ b/deploy/base/clusterserviceversion.yaml @@ -11,6 +11,7 @@ metadata: operatorframework.io/suggested-namespace: security-profiles-operator operators.openshift.io/valid-subscription: '["OpenShift Kubernetes Engine", "OpenShift Container Platform", "OpenShift Platform Plus"]' operatorframework.io/cluster-monitoring: "true" + operatorframework.io/os.linux: supported name: security-profiles-operator.v0.0.0 namespace: placeholder spec: diff --git a/deploy/base/profiles/security-profiles-operator.json b/deploy/base/profiles/security-profiles-operator.json index dd93a209f6..1b09d0d70c 100644 --- a/deploy/base/profiles/security-profiles-operator.json +++ b/deploy/base/profiles/security-profiles-operator.json @@ -4,7 +4,9 @@ "SCMP_ARCH_X86_64", "SCMP_ARCH_X86", "SCMP_ARCH_X32", - "SCMP_ARCH_AARCH64" + "SCMP_ARCH_AARCH64", + "SCMP_ARCH_PPC64LE", + "SCMP_ARCH_S390X" ], "syscalls": [ { diff --git a/deploy/helm/templates/static-resources.yaml b/deploy/helm/templates/static-resources.yaml index 0597bdaaea..6c03f1b4fe 100644 --- a/deploy/helm/templates/static-resources.yaml +++ b/deploy/helm/templates/static-resources.yaml @@ -693,7 +693,9 @@ data: "SCMP_ARCH_X86_64", "SCMP_ARCH_X86", "SCMP_ARCH_X32", - "SCMP_ARCH_AARCH64" + "SCMP_ARCH_AARCH64", + "SCMP_ARCH_PPC64LE", + "SCMP_ARCH_S390X" ], "syscalls": [ { diff --git a/deploy/namespace-operator.yaml b/deploy/namespace-operator.yaml index 216471abe1..6b1989b37c 100644 --- a/deploy/namespace-operator.yaml +++ b/deploy/namespace-operator.yaml @@ -2951,7 +2951,9 @@ data: "SCMP_ARCH_X86_64", "SCMP_ARCH_X86", "SCMP_ARCH_X32", - "SCMP_ARCH_AARCH64" + "SCMP_ARCH_AARCH64", + "SCMP_ARCH_PPC64LE", + "SCMP_ARCH_S390X" ], "syscalls": [ { diff --git a/deploy/openshift-dev.yaml b/deploy/openshift-dev.yaml index fdb29ca6a0..bf2061a346 100644 --- a/deploy/openshift-dev.yaml +++ b/deploy/openshift-dev.yaml @@ -2933,7 +2933,9 @@ data: "SCMP_ARCH_X86_64", "SCMP_ARCH_X86", "SCMP_ARCH_X32", - "SCMP_ARCH_AARCH64" + "SCMP_ARCH_AARCH64", + "SCMP_ARCH_PPC64LE", + "SCMP_ARCH_S390X" ], "syscalls": [ { diff --git a/deploy/openshift-downstream.yaml b/deploy/openshift-downstream.yaml index 91f7f456a8..40def90373 100644 --- a/deploy/openshift-downstream.yaml +++ b/deploy/openshift-downstream.yaml @@ -2964,7 +2964,9 @@ data: "SCMP_ARCH_X86_64", "SCMP_ARCH_X86", "SCMP_ARCH_X32", - "SCMP_ARCH_AARCH64" + "SCMP_ARCH_AARCH64", + "SCMP_ARCH_PPC64LE", + "SCMP_ARCH_S390X" ], "syscalls": [ { diff --git a/deploy/operator.yaml b/deploy/operator.yaml index acdd13ca96..e3e766a871 100644 --- a/deploy/operator.yaml +++ b/deploy/operator.yaml @@ -2951,7 +2951,9 @@ data: "SCMP_ARCH_X86_64", "SCMP_ARCH_X86", "SCMP_ARCH_X32", - "SCMP_ARCH_AARCH64" + "SCMP_ARCH_AARCH64", + "SCMP_ARCH_PPC64LE", + "SCMP_ARCH_S390X" ], "syscalls": [ { diff --git a/deploy/webhook-operator.yaml b/deploy/webhook-operator.yaml index 6587b25efc..7e887fab30 100644 --- a/deploy/webhook-operator.yaml +++ b/deploy/webhook-operator.yaml @@ -2922,7 +2922,9 @@ data: "SCMP_ARCH_X86_64", "SCMP_ARCH_X86", "SCMP_ARCH_X32", - "SCMP_ARCH_AARCH64" + "SCMP_ARCH_AARCH64", + "SCMP_ARCH_PPC64LE", + "SCMP_ARCH_S390X" ], "syscalls": [ { diff --git a/hack/image-cross.sh b/hack/image-cross.sh index c754396a05..25b446c111 100755 --- a/hack/image-cross.sh +++ b/hack/image-cross.sh @@ -22,7 +22,7 @@ REGISTRY=gcr.io/k8s-staging-sp-operator IMAGE=$REGISTRY/security-profiles-operator TAG=${TAG:-$(git describe --tags --always --dirty)} -ARCHES=(amd64 arm64) +ARCHES=(amd64 arm64 ppc64le s390x) VERSION=v$(cat VERSION) TAGS=("$TAG" "$VERSION" latest) diff --git a/internal/pkg/daemon/bpfrecorder/bpfrecorder_alt.go b/internal/pkg/daemon/bpfrecorder/bpfrecorder_alt.go new file mode 100644 index 0000000000..5f0b28ff3e --- /dev/null +++ b/internal/pkg/daemon/bpfrecorder/bpfrecorder_alt.go @@ -0,0 +1,20 @@ +//go:build (s390x || ppc64le) && linux +// +build s390x ppc64le,linux + +/* +Copyright 2024 The Kubernetes Authors. +*/ + +package bpfrecorder + +import "syscall" + +// UnameMachineToString converts uname.Machine to a string for s390x/ppc64le. +func UnameMachineToString(uname syscall.Utsname) string { + return toStringUint8(uname.Machine) +} + +// UnameReleaseToString converts uname.Release to a string for s390x/ppc64le. +func UnameReleaseToString(uname syscall.Utsname) string { + return toStringUint8(uname.Release) +} diff --git a/internal/pkg/daemon/bpfrecorder/bpfrecorder_linux_common.go b/internal/pkg/daemon/bpfrecorder/bpfrecorder_linux_common.go new file mode 100644 index 0000000000..33b283e1d9 --- /dev/null +++ b/internal/pkg/daemon/bpfrecorder/bpfrecorder_linux_common.go @@ -0,0 +1,20 @@ +//go:build (amd64 || arm64) && linux +// +build amd64 arm64,linux + +/* +Copyright 2024 The Kubernetes Authors. +*/ + +package bpfrecorder + +import "syscall" + +// UnameMachineToString converts uname.Machine to a string for arm64. +func UnameMachineToString(uname syscall.Utsname) string { + return toStringInt8(uname.Machine) +} + +// UnameReleaseToString converts uname.Release to a string for arm64. +func UnameReleaseToString(uname syscall.Utsname) string { + return toStringInt8(uname.Release) +} diff --git a/internal/pkg/daemon/bpfrecorder/bpfrecorder_stub.go b/internal/pkg/daemon/bpfrecorder/bpfrecorder_stub.go new file mode 100644 index 0000000000..60ae45b2a0 --- /dev/null +++ b/internal/pkg/daemon/bpfrecorder/bpfrecorder_stub.go @@ -0,0 +1,32 @@ +//go:build !ppc64le && !s390x && !amd64 && !arm64 && !linux +// +build !ppc64le,!s390x,!amd64,!arm64,!linux + +/* +Copyright 2024 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 bpfrecorder + +import "syscall" + +// UnameMachineToString provides a stub implementation for unsupported architectures. +func UnameMachineToString(uname syscall.Utsname) string { + return "" +} + +// UnameReleaseToString provides a stub implementation for unsupported architectures. +func UnameReleaseToString(uname syscall.Utsname) string { + return "" +} diff --git a/internal/pkg/daemon/bpfrecorder/bpfrecorder_utils.go b/internal/pkg/daemon/bpfrecorder/bpfrecorder_utils.go new file mode 100644 index 0000000000..38f863eaaf --- /dev/null +++ b/internal/pkg/daemon/bpfrecorder/bpfrecorder_utils.go @@ -0,0 +1,42 @@ +//go:build linux +// +build linux + +/* +Copyright 2024 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. +*/ + +package bpfrecorder + +// Helper function to convert [65]int8 to string. +func toStringInt8(array [65]int8) string { + n := 0 + for i, v := range array { + if v == 0 { + n = i + break + } + } + return string(array[:n]) +} + +// Helper function to convert [65]uint8 to string. +func toStringUint8(array [65]uint8) string { + n := 0 + for i, v := range array { + if v == 0 { + n = i + break + } + } + return string(array[:n]) +} diff --git a/internal/pkg/daemon/seccompprofile/seccompprofile.go b/internal/pkg/daemon/seccompprofile/seccompprofile.go index b22b42ab93..3a9c08e916 100644 --- a/internal/pkg/daemon/seccompprofile/seccompprofile.go +++ b/internal/pkg/daemon/seccompprofile/seccompprofile.go @@ -24,7 +24,7 @@ import ( "fmt" "net/http" "os" - "path" + "path/filepath" "runtime" "strings" "time" @@ -70,11 +70,14 @@ const ( errForbiddenProfile = "seccomp profile not allowed" errForbiddenAction = "seccomp action not allowed" - filePermissionMode os.FileMode = 0o644 + // filePermissionMode os.FileMode = 0o644 // MkdirAll won't create a directory if it does not have the execute bit. // https://github.com/golang/go/issues/22323#issuecomment-340568811 - dirPermissionMode os.FileMode = 0o744 + // dirPermissionMode os.FileMode = 0o744 + + dirPermissionMode os.FileMode = 0755 + filePermissionMode os.FileMode = 0644 reasonSeccompNotSupported string = "SeccompNotSupportedOnNode" reasonInvalidSeccompProfile string = "InvalidSeccompProfile" @@ -610,13 +613,23 @@ func (r *Reconciler) validateProfile(ctx context.Context, profile *seccompprofil } func saveProfileOnDisk(fileName string, content []byte) (updated bool, err error) { - if err := os.MkdirAll(path.Dir(fileName), dirPermissionMode); err != nil { - return false, fmt.Errorf("%s: %w", errCreatingOperatorDir, err) + // Split the full path into directory and filename + mainDirPath := filepath.Dir(fileName) + + // Check if the main directory exists, create it if it does not + if _, err := os.Stat(mainDirPath); os.IsNotExist(err) { + if err := os.MkdirAll(mainDirPath, dirPermissionMode); err != nil { + return false, err + } + } else if err != nil { + return false, err } existingContent, err := os.ReadFile(fileName) if err == nil && bytes.Equal(existingContent, content) { return false, nil + } else if err != nil && !os.IsNotExist(err) { + return false, fmt.Errorf("ReadFile err: %s\n", err) } if err := os.WriteFile(fileName, content, filePermissionMode); err != nil {