Skip to content

Commit

Permalink
Seccomp: Use provided profile
Browse files Browse the repository at this point in the history
Enable kubevirt profile by default in testing

Signed-off-by: L. Pivarc <[email protected]>
  • Loading branch information
xpivarc committed Jan 21, 2023
1 parent 9f1bdd7 commit abfdd7e
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 33 deletions.
40 changes: 27 additions & 13 deletions pkg/virt-controller/services/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,12 @@ func (t *templateService) RenderMigrationManifest(vmi *v1.VirtualMachineInstance
// PostCopy needs the userfaultfd syscall which can be restricted in the RuntimeDefault seccomp profile
if migrationConfiguration.AllowPostCopy != nil && *migrationConfiguration.AllowPostCopy &&
!t.clusterConfig.PSASeccompAllowsUserfaultfd() {
if podManifest.Spec.SecurityContext == nil {
podManifest.Spec.SecurityContext = &k8sv1.PodSecurityContext{}
}
if podManifest.Spec.SecurityContext.SeccompProfile == nil {
podManifest.Spec.SecurityContext.SeccompProfile = &k8sv1.SeccompProfile{}
}
podManifest.Spec.SecurityContext.SeccompProfile.Type = k8sv1.SeccompProfileTypeUnconfined
}
return podManifest, err
Expand All @@ -288,30 +294,20 @@ func generateQemuTimeoutWithJitter(qemuTimeoutBaseSeconds int) string {
return fmt.Sprintf("%ds", timeout)
}

func computeSecurityContext(vmi *v1.VirtualMachineInstance) *k8sv1.PodSecurityContext {
func computePodSecurityContext(vmi *v1.VirtualMachineInstance, seccomp *k8sv1.SeccompProfile) *k8sv1.PodSecurityContext {
psc := &k8sv1.PodSecurityContext{}

if util.IsNonRootVMI(vmi) {
nonRootUser := int64(util.NonRootUID)
psc.RunAsUser = &nonRootUser
psc.RunAsGroup = &nonRootUser
psc.RunAsNonRoot = pointer.Bool(true)
psc.SeccompProfile = &k8sv1.SeccompProfile{
Type: k8sv1.SeccompProfileTypeRuntimeDefault,
}
} else {
rootUser := int64(util.RootUser)
psc.RunAsUser = &rootUser
psc.SeccompProfile = &k8sv1.SeccompProfile{
Type: k8sv1.SeccompProfileTypeUnconfined,
}
}
psc.SeccompProfile = seccomp

if util.IsPasstVMI(vmi) || util.IsVMIVirtiofsEnabled(vmi) {
psc.SeccompProfile = &k8sv1.SeccompProfile{
Type: k8sv1.SeccompProfileTypeUnconfined,
}
}
return psc
}

Expand Down Expand Up @@ -506,6 +502,24 @@ func (t *templateService) renderLaunchManifest(vmi *v1.VirtualMachineInstance, i

hostName := dns.SanitizeHostname(vmi)
enableServiceLinks := false

var podSeccompProfile *k8sv1.SeccompProfile = nil
if seccompConf := t.clusterConfig.GetConfig().SeccompConfiguration; seccompConf != nil && seccompConf.VirtualMachineInstanceProfile != nil {
vmProfile := seccompConf.VirtualMachineInstanceProfile
if customProfile := vmProfile.CustomProfile; customProfile != nil {
if customProfile.LocalhostProfile != nil {
podSeccompProfile = &k8sv1.SeccompProfile{
Type: k8sv1.SeccompProfileTypeLocalhost,
LocalhostProfile: customProfile.LocalhostProfile,
}
} else if customProfile.RuntimeDefaultProfile {
podSeccompProfile = &k8sv1.SeccompProfile{
Type: k8sv1.SeccompProfileTypeRuntimeDefault,
}
}
}

}
pod := k8sv1.Pod{
ObjectMeta: metav1.ObjectMeta{
GenerateName: "virt-launcher-" + domain + "-",
Expand All @@ -518,7 +532,7 @@ func (t *templateService) renderLaunchManifest(vmi *v1.VirtualMachineInstance, i
Spec: k8sv1.PodSpec{
Hostname: hostName,
Subdomain: vmi.Spec.Subdomain,
SecurityContext: computeSecurityContext(vmi),
SecurityContext: computePodSecurityContext(vmi, podSeccompProfile),
TerminationGracePeriodSeconds: &gracePeriodKillAfter,
RestartPolicy: k8sv1.RestartPolicyNever,
Containers: containers,
Expand Down
53 changes: 34 additions & 19 deletions pkg/virt-controller/services/template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,36 @@ var _ = Describe("Template", func() {

return vmi
}
It("should not set seccomp profile by default", func() {
_, kvInformer, svc = configFactory(defaultArch)
pod, err := svc.RenderLaunchManifest(newMinimalWithContainerDisk("random"))
Expect(err).NotTo(HaveOccurred())

Expect(pod.Spec.SecurityContext.SeccompProfile).To(BeNil())
})

It("should set seccomp profile when configured", func() {
expectedProfile := &kubev1.SeccompProfile{
Type: kubev1.SeccompProfileTypeLocalhost,
LocalhostProfile: pointer.String("kubevirt/kubevirt.json"),
}
_, kvInformer, svc = configFactory(defaultArch)
kvConfig := kv.DeepCopy()
kvConfig.Spec.Configuration.SeccompConfiguration = &v1.SeccompConfiguration{
VirtualMachineInstanceProfile: &v1.VirtualMachineInstanceProfile{
CustomProfile: &v1.CustomProfile{
LocalhostProfile: pointer.String("kubevirt/kubevirt.json"),
},
},
}
testutils.UpdateFakeKubeVirtClusterConfig(kvInformer, kvConfig)

pod, err := svc.RenderLaunchManifest(newMinimalWithContainerDisk("random"))
Expect(err).NotTo(HaveOccurred())

Expect(pod.Spec.SecurityContext.SeccompProfile).To(BeEquivalentTo(expectedProfile))

})

Context("with NonRoot feature-gate", func() {
var vmi *v1.VirtualMachineInstance
Expand Down Expand Up @@ -3467,9 +3497,6 @@ var _ = Describe("Template", func() {
return api.NewMinimalVMI("fake-vmi")
}, &kubev1.PodSecurityContext{
RunAsUser: new(int64),
SeccompProfile: &kubev1.SeccompProfile{
Type: kubev1.SeccompProfileTypeUnconfined,
},
}),
Entry("on a non-root virt-launcher", func() *v1.VirtualMachineInstance {
vmi := api.NewMinimalVMI("fake-vmi")
Expand All @@ -3479,9 +3506,6 @@ var _ = Describe("Template", func() {
RunAsUser: &nonRootUser,
RunAsGroup: &nonRootUser,
RunAsNonRoot: pointer.Bool(true),
SeccompProfile: &kubev1.SeccompProfile{
Type: kubev1.SeccompProfileTypeRuntimeDefault,
},
}),
Entry("on a passt vmi", func() *v1.VirtualMachineInstance {
nonRootUser := util.NonRootUID
Expand All @@ -3497,9 +3521,6 @@ var _ = Describe("Template", func() {
RunAsUser: &nonRootUser,
RunAsGroup: &nonRootUser,
RunAsNonRoot: pointer.Bool(true),
SeccompProfile: &kubev1.SeccompProfile{
Type: kubev1.SeccompProfileTypeUnconfined,
},
SELinuxOptions: &kubev1.SELinuxOptions{
Type: "virt_launcher.process",
},
Expand All @@ -3516,28 +3537,22 @@ var _ = Describe("Template", func() {
RunAsUser: &nonRootUser,
RunAsGroup: &nonRootUser,
RunAsNonRoot: pointer.Bool(true),
SeccompProfile: &kubev1.SeccompProfile{
Type: kubev1.SeccompProfileTypeUnconfined,
},
}),
)

DescribeTable("should compute the correct security context when migrating and postcopy is", func(postCopyEnabled bool, expectedSeccompProfile kubev1.SeccompProfileType) {
It("should compute the correct security context when migrating and postcopy is enabled and PSASeccompAllowsUserfaultfd is disabled", func() {
vmi := api.NewMinimalVMI("fake-vmi")
vmi.Status.RuntimeUser = uint64(nonRootUser)
pod, err := svc.RenderLaunchManifest(vmi)
Expect(err).ToNot(HaveOccurred())

migrationConfig := &v1.MigrationConfiguration{
AllowPostCopy: pointer.Bool(postCopyEnabled),
AllowPostCopy: pointer.Bool(true),
}
pod, err = svc.RenderMigrationManifest(vmi, pod, migrationConfig)
Expect(err).ToNot(HaveOccurred())
Expect(pod.Spec.SecurityContext.SeccompProfile.Type).To(Equal(expectedSeccompProfile))
},
Entry("enabled", true, kubev1.SeccompProfileTypeUnconfined),
Entry("disabled", false, kubev1.SeccompProfileTypeRuntimeDefault),
)
Expect(pod.Spec.SecurityContext.SeccompProfile.Type).To(Equal(kubev1.SeccompProfileTypeUnconfined))
})

It("should compute the correct security context when rendering hotplug attachment pods", func() {
vmi := api.NewMinimalVMI("fake-vmi")
Expand Down
34 changes: 33 additions & 1 deletion tests/operator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ import (
. "kubevirt.io/kubevirt/tests/framework/matcher"
"kubevirt.io/kubevirt/tests/libnode"
"kubevirt.io/kubevirt/tests/libstorage"
"kubevirt.io/kubevirt/tests/libvmi"
"kubevirt.io/kubevirt/tests/libwait"
"kubevirt.io/kubevirt/tests/testsuite"
util2 "kubevirt.io/kubevirt/tests/util"
Expand Down Expand Up @@ -2964,7 +2965,7 @@ spec:

Context("[Serial] Seccomp configuration", Serial, func() {

Context("Kubevirt policy", func() {
Context("Kubevirt profile", func() {
var nodeName string

const expectedSeccompProfilePath = "/proc/1/root/var/lib/kubelet/seccomp/kubevirt/kubevirt.json"
Expand Down Expand Up @@ -3023,6 +3024,37 @@ spec:
})
})

Context("VirtualMachineInstance Profile", func() {
DescribeTable("with VirtualMachineInstance Profile set to", func(virtualMachineProfile *v1.VirtualMachineInstanceProfile, expectedProfile *k8sv1.SeccompProfile) {
By("Configuring VirtualMachineInstance Profile")
kv := util2.GetCurrentKv(virtClient)
if kv.Spec.Configuration.SeccompConfiguration == nil {
kv.Spec.Configuration.SeccompConfiguration = &v1.SeccompConfiguration{}
}
kv.Spec.Configuration.SeccompConfiguration.VirtualMachineInstanceProfile = virtualMachineProfile
tests.UpdateKubeVirtConfigValueAndWait(kv.Spec.Configuration)

By("Checking launcher seccomp policy")
vmi := libvmi.NewCirros()
vmi = tests.RunVMIAndExpectScheduling(vmi, 60)
pod, err := libvmi.GetPodByVirtualMachineInstance(vmi, vmi.Namespace)
Expect(err).NotTo(HaveOccurred())
var podProfile *k8sv1.SeccompProfile
if pod.Spec.SecurityContext != nil {
podProfile = pod.Spec.SecurityContext.SeccompProfile
}

Expect(podProfile).To(Equal(expectedProfile))
},
Entry("default should not set profile", nil, nil),
Entry("custom should use localhost", &v1.VirtualMachineInstanceProfile{
CustomProfile: &v1.CustomProfile{
LocalhostProfile: pointer.String("kubevirt/kubevirt.json"),
},
},
&k8sv1.SeccompProfile{Type: k8sv1.SeccompProfileTypeLocalhost, LocalhostProfile: pointer.String("kubevirt/kubevirt.json")}),
)
})
})
})

Expand Down
1 change: 1 addition & 0 deletions tests/testsuite/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,6 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/yaml:go_default_library",
"//vendor/k8s.io/klog/v2:go_default_library",
"//vendor/k8s.io/utils/pointer:go_default_library",
],
)
10 changes: 10 additions & 0 deletions tests/testsuite/kubevirtresource.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/strategicpatch"
"k8s.io/utils/pointer"

v1 "kubevirt.io/api/core/v1"
"kubevirt.io/client-go/kubecli"
Expand Down Expand Up @@ -81,6 +82,14 @@ func AdjustKubeVirtResource() {
if kv.Spec.Configuration.DeveloperConfiguration.FeatureGates == nil {
kv.Spec.Configuration.DeveloperConfiguration.FeatureGates = []string{}
}

kv.Spec.Configuration.SeccompConfiguration = &v1.SeccompConfiguration{
VirtualMachineInstanceProfile: &v1.VirtualMachineInstanceProfile{
CustomProfile: &v1.CustomProfile{
LocalhostProfile: pointer.String("kubevirt/kubevirt.json"),
},
},
}
kv.Spec.Configuration.DeveloperConfiguration.FeatureGates = append(kv.Spec.Configuration.DeveloperConfiguration.FeatureGates,
virtconfig.CPUManager,
virtconfig.IgnitionGate,
Expand All @@ -97,6 +106,7 @@ func AdjustKubeVirtResource() {
virtconfig.WorkloadEncryptionSEV,
virtconfig.VMExportGate,
virtconfig.VSOCKGate,
virtconfig.KubevirtSeccompProfile,
)

if kv.Spec.Configuration.NetworkConfiguration == nil {
Expand Down

0 comments on commit abfdd7e

Please sign in to comment.