Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OCP: SELinux: make custom policy opt-in and off by default #311

Merged
merged 2 commits into from
Aug 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pkg/assets/selinux/consts.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ package selinux

const (
RTEPolicyFileName = "/etc/selinux/rte.cil"
RTEContextType = "rte.process"
RTEContextType = "container_device_plugin_t"
RTEContextTypeLegacy = "rte.process"
RTEContextLevel = "s0"
RTEPolicyInstallServiceName = "rte-selinux-policy-install.service"
)
11 changes: 6 additions & 5 deletions pkg/commands/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -141,11 +141,12 @@ func makeUpdaterObjects(commonOpts *options.Options) ([]client.Object, string, e
}

opts := options.Updater{
PlatformVersion: commonOpts.UserPlatformVersion,
Platform: commonOpts.UserPlatform,
RTEConfigData: commonOpts.RTEConfigData,
DaemonSet: options.ForDaemonSet(commonOpts),
EnableCRIHooks: commonOpts.UpdaterCRIHooksEnable,
PlatformVersion: commonOpts.UserPlatformVersion,
Platform: commonOpts.UserPlatform,
RTEConfigData: commonOpts.RTEConfigData,
DaemonSet: options.ForDaemonSet(commonOpts),
EnableCRIHooks: commonOpts.UpdaterCRIHooksEnable,
CustomSELinuxPolicy: commonOpts.UpdaterCustomSELinuxPolicy,
}
objs, err := updaters.GetObjects(opts, commonOpts.UpdaterType, namespace)
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions pkg/deployer/updaters/objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import (

func GetObjects(opts options.Updater, updaterType, namespace string) ([]client.Object, error) {
if updaterType == RTE {
mf, err := rtemanifests.GetManifests(opts.Platform, opts.PlatformVersion, namespace, opts.EnableCRIHooks)
mf, err := rtemanifests.GetManifests(opts.Platform, opts.PlatformVersion, namespace, opts.EnableCRIHooks, opts.CustomSELinuxPolicy)
if err != nil {
return nil, err
}
Expand All @@ -58,7 +58,7 @@ func GetObjects(opts options.Updater, updaterType, namespace string) ([]client.O

func getCreatableObjects(env *deployer.Environment, opts options.Updater, updaterType, namespace string) ([]objectwait.WaitableObject, error) {
if updaterType == RTE {
mf, err := rtemanifests.GetManifests(opts.Platform, opts.PlatformVersion, namespace, opts.EnableCRIHooks)
mf, err := rtemanifests.GetManifests(opts.Platform, opts.PlatformVersion, namespace, opts.EnableCRIHooks, opts.CustomSELinuxPolicy)
if err != nil {
return nil, err
}
Expand All @@ -84,7 +84,7 @@ func getCreatableObjects(env *deployer.Environment, opts options.Updater, update

func getDeletableObjects(env *deployer.Environment, opts options.Updater, updaterType, namespace string) ([]objectwait.WaitableObject, error) {
if updaterType == RTE {
mf, err := rtemanifests.GetManifests(opts.Platform, opts.PlatformVersion, namespace, opts.EnableCRIHooks)
mf, err := rtemanifests.GetManifests(opts.Platform, opts.PlatformVersion, namespace, opts.EnableCRIHooks, opts.CustomSELinuxPolicy)
if err != nil {
return nil, err
}
Expand Down
5 changes: 4 additions & 1 deletion pkg/manifests/manifests.go
Original file line number Diff line number Diff line change
Expand Up @@ -436,7 +436,7 @@ func getTemplateContent(templateContent []byte, templateArgs map[string]string)
return fileContent.Bytes(), nil
}

func SecurityContextConstraint(component string) (*securityv1.SecurityContextConstraints, error) {
func SecurityContextConstraint(component string, withCustomSELinuxPolicy bool) (*securityv1.SecurityContextConstraints, error) {
if component != ComponentResourceTopologyExporter {
return nil, fmt.Errorf("component %q is not an %q component", component, ComponentResourceTopologyExporter)
}
Expand All @@ -458,6 +458,9 @@ func SecurityContextConstraint(component string) (*securityv1.SecurityContextCon
Level: selinuxassets.RTEContextLevel,
},
}
if withCustomSELinuxPolicy {
scc.SELinuxContext.SELinuxOptions.Type = selinuxassets.RTEContextTypeLegacy
}

return scc, nil
}
Expand Down
36 changes: 36 additions & 0 deletions pkg/manifests/manifests_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package manifests

import (
"encoding/json"
selinuxassets "github.com/k8stopologyawareschedwg/deployer/pkg/assets/selinux"
"testing"

igntypes "github.com/coreos/ignition/v2/config/v3_2/types"
Expand Down Expand Up @@ -526,3 +527,38 @@ func TestMachineConfig(t *testing.T) {
})
}
}

func TestSecurityContextConstraint(t *testing.T) {
testCases := []struct {
description string
withCustomSELinuxPolicy bool
selinuxContextType string
}{
{
description: "with custom (legacy) policy",
withCustomSELinuxPolicy: true,
selinuxContextType: selinuxassets.RTEContextTypeLegacy,
},
{
description: "with built-in policy",
withCustomSELinuxPolicy: false,
selinuxContextType: selinuxassets.RTEContextType,
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
scc, err := SecurityContextConstraint(ComponentResourceTopologyExporter, tc.withCustomSELinuxPolicy)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if scc == nil {
t.Fatalf("nil security context constraint")
}
// shortcut
scType := scc.SELinuxContext.SELinuxOptions.Type
if scType != tc.selinuxContextType {
t.Fatalf("wrong selinux context type; got=%s want=%s", scType, tc.selinuxContextType)
}
})
}
}
36 changes: 23 additions & 13 deletions pkg/manifests/rte/rte.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package rte

import (
selinuxassets "github.com/k8stopologyawareschedwg/deployer/pkg/assets/selinux"
securityv1 "github.com/openshift/api/security/v1"
machineconfigv1 "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1"
appsv1 "k8s.io/api/apps/v1"
Expand Down Expand Up @@ -68,7 +69,10 @@ func (mf Manifests) Clone() Manifests {
}

if mf.plat == platform.OpenShift {
ret.MachineConfig = mf.MachineConfig.DeepCopy()
// MachineConfig is obsolete starting from OCP v4.18
if mf.MachineConfig != nil {
ret.MachineConfig = mf.MachineConfig.DeepCopy()
}
ret.SecurityContextConstraint = mf.SecurityContextConstraint.DeepCopy()
}

Expand Down Expand Up @@ -108,14 +112,18 @@ func (mf Manifests) Render(opts options.UpdaterDaemon) (Manifests, error) {
rteupdate.DaemonSet(ret.DaemonSet, mf.plat, rteConfigMapName, opts.DaemonSet)

if mf.plat == platform.OpenShift {
rteupdate.SecurityContext(ret.DaemonSet)

if opts.Name != "" {
ret.MachineConfig.Name = ocpupdate.MakeMachineConfigName(opts.Name)
}
if opts.MachineConfigPoolSelector != nil {
ret.MachineConfig.Labels = opts.MachineConfigPoolSelector.MatchLabels
selinuxType := selinuxassets.RTEContextType
if mf.MachineConfig != nil {
if opts.Name != "" {
ret.MachineConfig.Name = ocpupdate.MakeMachineConfigName(opts.Name)
}
if opts.MachineConfigPoolSelector != nil {
ret.MachineConfig.Labels = opts.MachineConfigPoolSelector.MatchLabels
}
// the MachineConfig installs this custom policy which is obsolete starting from OCP v4.18
selinuxType = selinuxassets.RTEContextTypeLegacy
}
rteupdate.SecurityContext(ret.DaemonSet, selinuxType)
ocpupdate.SecurityContextConstraint(ret.SecurityContextConstraint, ret.ServiceAccount)
}

Expand Down Expand Up @@ -173,17 +181,19 @@ func New(plat platform.Platform) Manifests {
return mf
}

func GetManifests(plat platform.Platform, version platform.Version, namespace string, withCRIHooks bool) (Manifests, error) {
func GetManifests(plat platform.Platform, version platform.Version, namespace string, withCRIHooks, withCustomSELinuxPolicy bool) (Manifests, error) {
var err error
mf := New(plat)

if plat == platform.OpenShift {
mf.MachineConfig, err = manifests.MachineConfig(manifests.ComponentResourceTopologyExporter, version, withCRIHooks)
if err != nil {
return mf, err
if withCustomSELinuxPolicy {
mf.MachineConfig, err = manifests.MachineConfig(manifests.ComponentResourceTopologyExporter, version, withCRIHooks)
if err != nil {
return mf, err
}
}

mf.SecurityContextConstraint, err = manifests.SecurityContextConstraint(manifests.ComponentResourceTopologyExporter)
mf.SecurityContextConstraint, err = manifests.SecurityContextConstraint(manifests.ComponentResourceTopologyExporter, withCustomSELinuxPolicy)
if err != nil {
return mf, err
}
Expand Down
37 changes: 24 additions & 13 deletions pkg/manifests/rte/rte_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func TestClone(t *testing.T) {
}

for _, tc := range testCases {
tc.mf, _ = GetManifests(tc.plat, tc.platVersion, "", true)
tc.mf, _ = GetManifests(tc.plat, tc.platVersion, "", true, true)
cMf := tc.mf.Clone()

if &cMf == &tc.mf {
Expand Down Expand Up @@ -97,7 +97,7 @@ func TestRender(t *testing.T) {
}

for _, tc := range testCases {
tc.mf, _ = GetManifests(tc.plat, tc.platVersion, "", true)
tc.mf, _ = GetManifests(tc.plat, tc.platVersion, "", true, true)
mfBeforeRender := tc.mf.Clone()
uMf, err := tc.mf.Render(options.UpdaterDaemon{})
if err != nil {
Expand All @@ -115,26 +115,33 @@ func TestRender(t *testing.T) {

func TestGetManifestsOpenShift(t *testing.T) {
type testCase struct {
name string
// mf Manifests
plat platform.Platform
platVersion platform.Version
name string
plat platform.Platform
platVersion platform.Version
withCustomSELinuxPolicy bool
}

testCases := []testCase{
{
name: "openshift manifests 4.10",
plat: platform.OpenShift,
platVersion: platform.Version("v4.10"),
name: "openshift manifests 4.10",
plat: platform.OpenShift,
platVersion: platform.Version("v4.10"),
withCustomSELinuxPolicy: true,
},
{
name: "openshift manifests 4.11",
name: "openshift manifests 4.11",
plat: platform.OpenShift,
platVersion: platform.Version("v4.11"),
withCustomSELinuxPolicy: true,
},
{
name: "openshift manifests 4.18",
plat: platform.OpenShift,
platVersion: platform.Version("v4.11"),
platVersion: platform.Version("v4.18"),
},
}
for _, tc := range testCases {
mf, err := GetManifests(tc.plat, tc.platVersion, "test", true)
mf, err := GetManifests(tc.plat, tc.platVersion, "test", true, tc.withCustomSELinuxPolicy)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
Expand All @@ -143,10 +150,14 @@ func TestGetManifestsOpenShift(t *testing.T) {
t.Fatalf("no security context constraint is generated for the OpenShift platform")
}

if mf.MachineConfig == nil {
if tc.withCustomSELinuxPolicy && mf.MachineConfig == nil {
t.Fatalf("no machine config is generated for the OpenShift platform")
}

if !tc.withCustomSELinuxPolicy && mf.MachineConfig != nil {
t.Fatalf("machine config should not be generated for the OpenShift platform")
}

if mf.DaemonSet == nil {
t.Fatalf("no daemon set is generated for the OpenShift platform")
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/objectupdate/rte/rte.go
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ func MetricsPort(ds *appsv1.DaemonSet, pNum int) {
cntSpec.Ports = cp
}

func SecurityContext(ds *appsv1.DaemonSet) {
func SecurityContext(ds *appsv1.DaemonSet, selinuxContextType string) {
cntSpec := objectupdate.FindContainerByName(ds.Spec.Template.Spec.Containers, manifests.ContainerNameRTE)
if cntSpec == nil {
return
Expand All @@ -186,7 +186,7 @@ func SecurityContext(ds *appsv1.DaemonSet) {
cntSpec.SecurityContext = &corev1.SecurityContext{}
}
cntSpec.SecurityContext.SELinuxOptions = &corev1.SELinuxOptions{
Type: selinuxassets.RTEContextType,
Type: selinuxContextType,
Tal-or marked this conversation as resolved.
Show resolved Hide resolved
Level: selinuxassets.RTEContextLevel,
}
}
Expand Down
36 changes: 36 additions & 0 deletions pkg/objectupdate/rte/rte_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ package rte

import (
"fmt"
selinuxassets "github.com/k8stopologyawareschedwg/deployer/pkg/assets/selinux"
"github.com/k8stopologyawareschedwg/deployer/pkg/objectupdate"
"strings"
"testing"
"time"
Expand Down Expand Up @@ -313,3 +315,37 @@ func TestDaemonSet(t *testing.T) {
})
}
}

func TestSecurityContext(t *testing.T) {
testCases := []struct {
description string
selinuxContextType string
}{
{
description: "custom policy",
selinuxContextType: selinuxassets.RTEContextTypeLegacy,
},
{
description: "built-in policy",
selinuxContextType: selinuxassets.RTEContextType,
},
}
for _, tc := range testCases {
t.Run(tc.description, func(t *testing.T) {
ds, err := manifests.DaemonSet(manifests.ComponentResourceTopologyExporter, "", "test")
if err != nil {
t.Fatalf("unexpected error getting the manifests: %v", err)
}
DaemonSet(ds, platform.OpenShift, "", options.DaemonSet{})
SecurityContext(ds, tc.selinuxContextType)
cntSpec := objectupdate.FindContainerByName(ds.Spec.Template.Spec.Containers, manifests.ContainerNameRTE)
sc := cntSpec.SecurityContext
if sc == nil {
t.Fatalf("the security context for container %q does not exist", cntSpec.Name)
}
if sc.SELinuxOptions.Type != tc.selinuxContextType {
t.Fatalf("wrong security context for container %q; want=%s got=%s", cntSpec.Name, tc.selinuxContextType, sc.SELinuxOptions.Type)
}
})
}
}
14 changes: 8 additions & 6 deletions pkg/options/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ type Options struct {
UpdaterPFPEnable bool
UpdaterNotifEnable bool
UpdaterCRIHooksEnable bool
UpdaterCustomSELinuxPolicy bool
UpdaterSyncPeriod time.Duration
UpdaterVerbose int
SchedProfileName string
Expand Down Expand Up @@ -88,12 +89,13 @@ type UpdaterDaemon struct {
}

type Updater struct {
Platform platform.Platform
PlatformVersion platform.Version
WaitCompletion bool
RTEConfigData string
DaemonSet DaemonSet
EnableCRIHooks bool
Platform platform.Platform
PlatformVersion platform.Version
WaitCompletion bool
RTEConfigData string
DaemonSet DaemonSet
EnableCRIHooks bool
CustomSELinuxPolicy bool
}

func ForDaemonSet(commonOpts *Options) DaemonSet {
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ func dumpResourceTopologyExporterPods(ctx context.Context, cli client.Client) {
gomega.Expect(err).ToNot(gomega.HaveOccurred())

// TODO: autodetect the platform
mfs, err := rte.GetManifests(platform.Kubernetes, platform.Version("1.23"), ns.Name, true)
mfs, err := rte.GetManifests(platform.Kubernetes, platform.Version("1.23"), ns.Name, true, true)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
mfs, err = mfs.Render(options.UpdaterDaemon{
Namespace: ns.Name,
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/manifests.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ var _ = ginkgo.Describe("[ManifestFlow] Deployer rendering", ginkgo.Label("manif
gomega.Expect(err).ToNot(gomega.HaveOccurred())

enableCRIHooks := true
mf, err := rte.GetManifests(platform.Kubernetes, platform.Version("1.23"), ns.Name, enableCRIHooks)
mf, err := rte.GetManifests(platform.Kubernetes, platform.Version("1.23"), ns.Name, enableCRIHooks, true)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
mf, err = mf.Render(options.UpdaterDaemon{
Namespace: ns.Name,
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/negative.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ var _ = ginkgo.Describe("[NegativeFlow] Deployer execution with PFP disabled", g
gomega.Expect(err).ToNot(gomega.HaveOccurred())

enableCRIHooks := true
mf, err := rte.GetManifests(platform.Kubernetes, platform.Version("1.23"), ns.Name, enableCRIHooks)
mf, err := rte.GetManifests(platform.Kubernetes, platform.Version("1.23"), ns.Name, enableCRIHooks, true)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
mf, err = mf.Render(options.UpdaterDaemon{
Namespace: ns.Name,
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/positive.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ var _ = ginkgo.Describe("[PositiveFlow] Deployer execution", ginkgo.Label("posit
gomega.Expect(err).ToNot(gomega.HaveOccurred())

enableCRIHooks := true
mf, err := rte.GetManifests(platform.Kubernetes, platform.Version("1.23"), ns.Name, enableCRIHooks)
mf, err := rte.GetManifests(platform.Kubernetes, platform.Version("1.23"), ns.Name, enableCRIHooks, true)
gomega.Expect(err).ToNot(gomega.HaveOccurred())
mf, err = mf.Render(options.UpdaterDaemon{
Namespace: ns.Name,
Expand Down
Loading