Skip to content

Commit

Permalink
(catsrc) allow catalogsource to be run as root
Browse files Browse the repository at this point in the history
This PR exposes a spec.runAsRoot field, so that cluster admins can
indicate that they want to run the catalogsource container as root
user.

This, along with the Pod Admission Controller enforce level `privileged`
allows cluster admins to run catalogsources that are built with a version
of opm that is less than v1.23.2 (i.e a version of opm that does not contain
[this commit](operator-framework/operator-registry#974)

Signed-off-by: Anik Bhattacharjee <anikbhattacharya93@gmail.com>
  • Loading branch information
anik120 committed Sep 8, 2022
1 parent bd97e32 commit 88322df
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 25 deletions.
6 changes: 3 additions & 3 deletions deploy/chart/crds/0000_50_olm_00-catalogsources.crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ spec:
type: object
additionalProperties:
type: string
requirePrivilegedAccess:
description: RequirePrivilegeAccess when set to true, allows the containers in the pod to run in privileged mode. This should only be set to true when using older catalog images which could be run in restricted mode, and requires privileged access.
type: boolean
priorityClassName:
description: If specified, indicates the pod's priority. If not specified, the pod priority will be default or zero if there is no default.
type: string
Expand Down Expand Up @@ -120,9 +123,6 @@ spec:
type: integer
publisher:
type: string
runAsRoot:
description: RunAsRoot allows admins to indicate that they wish to run the CatalogSource pod in a privileged pod as root. This should only be enabled when running older catalog images which could not be run as non-root.
type: boolean
secrets:
description: Secrets represent set of secrets that can be used to access the contents of the catalog. It is best to keep this list small, since each will need to be tried for every catalog entry.
type: array
Expand Down
29 changes: 16 additions & 13 deletions pkg/controller/registry/reconciler/reconciler.go
Original file line number Diff line number Diff line change
Expand Up @@ -182,11 +182,7 @@ func Pod(source *operatorsv1alpha1.CatalogSource, name string, image string, saN
},
},
SecurityContext: &corev1.SecurityContext{
ReadOnlyRootFilesystem: pointer.Bool(false),
AllowPrivilegeEscalation: pointer.Bool(false),
Capabilities: &corev1.Capabilities{
Drop: []corev1.Capability{"ALL"},
},
ReadOnlyRootFilesystem: pointer.Bool(false),
},
ImagePullPolicy: pullPolicy,
TerminationMessagePolicy: corev1.TerminationMessageFallbackToLogsOnError,
Expand All @@ -195,19 +191,26 @@ func Pod(source *operatorsv1alpha1.CatalogSource, name string, image string, saN
NodeSelector: map[string]string{
"kubernetes.io/os": "linux",
},
SecurityContext: &corev1.PodSecurityContext{
SeccompProfile: &corev1.SeccompProfile{
Type: corev1.SeccompProfileTypeRuntimeDefault,
},
},
ServiceAccountName: saName,
},
}

if runAsUser > 0 {
pod.Spec.SecurityContext.RunAsUser = &runAsUser
pod.Spec.SecurityContext.RunAsNonRoot = pointer.Bool(true)
if source.Spec.GrpcPodConfig == nil || !source.Spec.GrpcPodConfig.RequirePrivilegedAccess {
pod.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation = pointer.Bool(false)
pod.Spec.Containers[0].SecurityContext.Capabilities = &corev1.Capabilities{
Drop: []corev1.Capability{"ALL"},
}
pod.Spec.SecurityContext = &corev1.PodSecurityContext{
SeccompProfile: &corev1.SeccompProfile{
Type: corev1.SeccompProfileTypeRuntimeDefault,
},
}
if runAsUser > 0 {
pod.Spec.SecurityContext.RunAsUser = &runAsUser
pod.Spec.SecurityContext.RunAsNonRoot = pointer.Bool(true)
}
}

// Override scheduling options if specified
if source.Spec.GrpcPodConfig != nil {
grpcPodConfig := source.Spec.GrpcPodConfig
Expand Down
140 changes: 140 additions & 0 deletions test/e2e/catalog_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1396,7 +1396,147 @@ var _ = Describe("Starting CatalogSource e2e tests", func() {
})
})
})
When("The namespace is labled as Pod Security Admission policy enforce:restricted", func() {
BeforeEach(func() {
var err error
testNS := &corev1.Namespace{}
Eventually(func() error {
testNS, err = c.KubernetesInterface().CoreV1().Namespaces().Get(context.TODO(), ns.GetName(), metav1.GetOptions{})
if err != nil {
return err
}
return nil
}).Should(BeNil())

testNS.ObjectMeta.Labels = map[string]string{
"pod-security.kubernetes.io/enforce": "restricted",
"pod-security.kubernetes.io/enforce-version": "latest",
}

Eventually(func() error {
_, err := c.KubernetesInterface().CoreV1().Namespaces().Update(context.TODO(), testNS, metav1.UpdateOptions{})
if err != nil {
return err
}
return nil
}).Should(BeNil())
})
When("A CatalogSource built with opm v1.21.0 (<v1.23.2)is created without spec.GrpcPodConfig.RequirePrivilegedAccess set to true", func() {
var sourceName string
BeforeEach(func() {
sourceName = genName("catalog-")
source := &v1alpha1.CatalogSource{
TypeMeta: metav1.TypeMeta{
Kind: v1alpha1.CatalogSourceKind,
APIVersion: v1alpha1.CatalogSourceCRDAPIVersion,
},
ObjectMeta: metav1.ObjectMeta{
Name: sourceName,
Namespace: ns.GetName(),
Labels: map[string]string{"olm.catalogSource": sourceName},
},
Spec: v1alpha1.CatalogSourceSpec{
SourceType: v1alpha1.SourceTypeGrpc,
Image: "quay.io/olmtest/old-opm-catsrc:v1.21.0",
},
}

Eventually(func() error {
_, err := crc.OperatorsV1alpha1().CatalogSources(source.GetNamespace()).Create(context.Background(), source, metav1.CreateOptions{})
return err
}).Should(Succeed())
})
It("The registry pod fails to become come up because of lack of permission", func() {
Eventually(func() (bool, error) {
podList, err := c.KubernetesInterface().CoreV1().Pods(ns.GetName()).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return false, err
}
for _, pod := range podList.Items {
if pod.ObjectMeta.OwnerReferences != nil && pod.ObjectMeta.OwnerReferences[0].Name == sourceName {
if pod.Status.ContainerStatuses != nil && pod.Status.ContainerStatuses[0].State.Terminated != nil {
return true, nil
}
}
}
return false, nil
}).Should(BeTrue())
})
})
})
When("The namespace is labled as Pod Security Admission policy enforce:privileged", func() {
BeforeEach(func() {
var err error
testNS := &corev1.Namespace{}
Eventually(func() error {
testNS, err = c.KubernetesInterface().CoreV1().Namespaces().Get(context.TODO(), ns.GetName(), metav1.GetOptions{})
if err != nil {
return err
}
return nil
}).Should(BeNil())

testNS.ObjectMeta.Labels = map[string]string{
"pod-security.kubernetes.io/enforce": "privileged",
"pod-security.kubernetes.io/enforce-version": "latest",
}

Eventually(func() error {
_, err := c.KubernetesInterface().CoreV1().Namespaces().Update(context.TODO(), testNS, metav1.UpdateOptions{})
if err != nil {
return err
}
return nil
}).Should(BeNil())
})
When("A CatalogSource built with opm v1.21.0 (<v1.23.2)is created with spec.GrpcPodConfig.RequirePrivilegedAccess set to true", func() {
var sourceName string
BeforeEach(func() {
sourceName = genName("catalog-")
source := &v1alpha1.CatalogSource{
TypeMeta: metav1.TypeMeta{
Kind: v1alpha1.CatalogSourceKind,
APIVersion: v1alpha1.CatalogSourceCRDAPIVersion,
},
ObjectMeta: metav1.ObjectMeta{
Name: sourceName,
Namespace: ns.GetName(),
Labels: map[string]string{"olm.catalogSource": sourceName},
},
Spec: v1alpha1.CatalogSourceSpec{
GrpcPodConfig: &v1alpha1.GrpcPodConfig{
RequirePrivilegedAccess: true,
},
SourceType: v1alpha1.SourceTypeGrpc,
Image: "quay.io/olmtest/old-opm-catsrc:v1.21.0",
},
}

Eventually(func() error {
_, err := crc.OperatorsV1alpha1().CatalogSources(source.GetNamespace()).Create(context.Background(), source, metav1.CreateOptions{})
return err
}).Should(Succeed())
})
It("The registry pod comes up successfully", func() {
Eventually(func() (bool, error) {
podList, err := c.KubernetesInterface().CoreV1().Pods(ns.GetName()).List(context.TODO(), metav1.ListOptions{})
if err != nil {
return false, err
}
for _, pod := range podList.Items {
if pod.ObjectMeta.OwnerReferences != nil && pod.ObjectMeta.OwnerReferences[0].Name == sourceName {
if pod.Status.ContainerStatuses != nil {
if *pod.Status.ContainerStatuses[0].Started == true {
return true, nil
}
}
}
}
return false, nil
}).Should(BeTrue())
})
})
})
})

func getOperatorDeployment(c operatorclient.ClientInterface, namespace string, operatorLabels labels.Set) (*appsv1.Deployment, error) {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 88322df

Please sign in to comment.