Skip to content

Commit 0b763cd

Browse files
[v1.24.x] OCPBUGS-1666: Expose flag to enable/disable PodSecurity (#6080)
* OCPBUGS-1666: Expose flag to enable/disable PodSecurity Added --security-context-config flag to enable seccompprofile. It defaults to enabled to support k8s 1.25. You can disable it with --security-context-config=legacy Signed-off-by: jesus m. rodriguez <[email protected]> * fix test-sanity: update docs & fix test. * Ignoring error from Set call in test * Update .cncf maintainers * Update run bundle(-upgrade) CLI docs * Add allowed values to the security-context-config flag. * Default to Restricted, and add the default value in the help text. * Update changelog to indicate that we're updating run bundle subcommand Signed-off-by: jesus m. rodriguez <[email protected]> * Fix typo in changelog * Removed the "default: restricted" from the help text. This was being duplicated because we had it in the text but were not setting the value to a default value. Once we set the value to the default cobra realized this and would output "(default: restricted)". So removing the manually entered text fixes the duplicate. Signed-off-by: jesus m. rodriguez <[email protected]>
1 parent de6a14d commit 0b763cd

File tree

7 files changed

+228
-41
lines changed

7 files changed

+228
-41
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# entries is a list of entries to include in
2+
# release notes and/or the migration guide
3+
entries:
4+
- description: >
5+
For operator-sdk run bundle and bundle-upgrade subcommands: Added --security-context-config
6+
flag to enable seccompprofile. It defaults to restricted to support k8s 1.25. You can disable it
7+
with --security-context-config=legacy
8+
9+
# kind is one of:
10+
# - addition
11+
# - change
12+
# - deprecation
13+
# - removal
14+
# - bugfix
15+
kind: "bugfix"
16+
17+
# Is this a breaking change?
18+
breaking: false

internal/olm/operator/registry/fbcindex/fbc_registry_pod.go

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,10 @@ type FBCRegistryPod struct { //nolint:maligned
7272
// This directory has the File-Based Catalog representation of a catalog index.
7373
FBCIndexRootDir string
7474

75+
// SecurityContext defines the security context which will enable the
76+
// SecurityContext on the Pod
77+
SecurityContext string
78+
7579
cfg *operator.Configuration
7680
}
7781

@@ -115,6 +119,15 @@ func (f *FBCRegistryPod) Create(ctx context.Context, cfg *operator.Configuration
115119
return nil, fmt.Errorf("error setting owner reference: %w", err)
116120
}
117121

122+
// Add security context if the user passed in the --security-context-config flag
123+
if f.SecurityContext == "restricted" {
124+
f.pod.Spec.SecurityContext = &corev1.PodSecurityContext{
125+
SeccompProfile: &corev1.SeccompProfile{
126+
Type: corev1.SeccompProfileTypeRuntimeDefault,
127+
},
128+
}
129+
}
130+
118131
if err := f.cfg.Client.Create(ctx, f.pod); err != nil {
119132
return nil, fmt.Errorf("error creating pod: %w", err)
120133
}
@@ -230,11 +243,19 @@ func (f *FBCRegistryPod) podForBundleRegistry(cs *v1alpha1.CatalogSource) (*core
230243
// TODO: remove when OpenShift 4.10 and Kubernetes 1.19 be no longer supported
231244
// Why not set SeccompProfile?
232245
// This option can only work in OCP versions >= 4.11 and Kubernetes versions >= 19.
233-
//SecurityContext: &corev1.PodSecurityContext{
234-
// SeccompProfile: &corev1.SeccompProfile{
235-
// Type: corev1.SeccompProfileTypeRuntimeDefault,
236-
// },
237-
//},
246+
//
247+
// 2022-09-27 (jesusr): We added a --security-context-config flag to run bundle
248+
// that will add the following stanza to the pod. This will allow
249+
// users to selectively enable this stanza. Once this context
250+
// becomes the default, we should uncomment this code and remove the
251+
// --security-context-config flag.
252+
// ---- end of update comment
253+
//
254+
// SecurityContext: &corev1.PodSecurityContext{
255+
// SeccompProfile: &corev1.SeccompProfile{
256+
// Type: corev1.SeccompProfileTypeRuntimeDefault,
257+
// },
258+
// },
238259
Volumes: []corev1.Volume{
239260
{
240261
Name: k8sutil.TrimDNS1123Label(cm.Name + "-volume"),

internal/olm/operator/registry/index/registry_pod.go

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ type SQLiteRegistryPod struct { //nolint:maligned
8484
// UseHTTP uses plain HTTP for container image registries while pulling bundles.
8585
UseHTTP bool `json:"UseHTTP"`
8686

87+
// SecurityContext defines the security context which will enable the
88+
// SecurityContext on the Pod
89+
SecurityContext string
90+
8791
// pod represents a kubernetes *corev1.pod that will be created on a cluster using an index image
8892
pod *corev1.Pod
8993

@@ -128,6 +132,15 @@ func (rp *SQLiteRegistryPod) Create(ctx context.Context, cfg *operator.Configura
128132
return nil, fmt.Errorf("error setting owner reference: %w", err)
129133
}
130134

135+
// Add security context if the user passed in the --security-context-config flag
136+
if rp.SecurityContext == "restricted" {
137+
rp.pod.Spec.SecurityContext = &corev1.PodSecurityContext{
138+
SeccompProfile: &corev1.SeccompProfile{
139+
Type: corev1.SeccompProfileTypeRuntimeDefault,
140+
},
141+
}
142+
}
143+
131144
if err := rp.cfg.Client.Create(ctx, rp.pod); err != nil {
132145
return nil, fmt.Errorf("error creating pod: %w", err)
133146
}
@@ -239,11 +252,19 @@ func (rp *SQLiteRegistryPod) podForBundleRegistry() (*corev1.Pod, error) {
239252
// TODO: remove when OpenShift 4.10 and Kubernetes 1.19 be no longer supported
240253
// Why not set SeccompProfile?
241254
// This option can only work in OCP versions >= 4.11 and Kubernetes versions >= 19.
242-
//SecurityContext: &corev1.PodSecurityContext{
243-
// SeccompProfile: &corev1.SeccompProfile{
244-
// Type: corev1.SeccompProfileTypeRuntimeDefault,
245-
// },
246-
//},
255+
//
256+
// 2022-09-27 (jesusr): We added a --security-context-config flag to run bundle
257+
// that will add the following stanza to the pod. This will allow
258+
// users to selectively enable this stanza. Once this context
259+
// becomes the default, we should uncomment this code and remove the
260+
// --security-context-config flag.
261+
// ---- end of update comment
262+
//
263+
// SecurityContext: &corev1.PodSecurityContext{
264+
// SeccompProfile: &corev1.SeccompProfile{
265+
// Type: corev1.SeccompProfileTypeRuntimeDefault,
266+
// },
267+
// },
247268
Containers: []corev1.Container{
248269
{
249270
Name: defaultContainerName,

internal/olm/operator/registry/index_image.go

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,44 @@ const (
5252
registryPodNameAnnotation = operatorFrameworkGroup + "/registry-pod-name"
5353
)
5454

55+
// TODO: Change this to use the values in operator-framework/api
56+
// once the release containing the enums is pulled into SDK
57+
type SecurityContextType string
58+
59+
const (
60+
Legacy SecurityContextType = "legacy"
61+
Restricted SecurityContextType = "restricted"
62+
)
63+
64+
// SecurityContext represents the enum from the CatalogSource API
65+
// It is also being used by the binding flags to allow validation of the enum
66+
// values
67+
type SecurityContext struct {
68+
ContextType SecurityContextType
69+
}
70+
71+
func (sc *SecurityContext) String() string {
72+
return string(sc.ContextType)
73+
}
74+
75+
func (sc *SecurityContext) Set(value string) error {
76+
switch value {
77+
case "legacy", "restricted":
78+
sc.ContextType = SecurityContextType(value)
79+
return nil
80+
default:
81+
return fmt.Errorf("must be one of \"legacy\", or \"restricted\"")
82+
}
83+
}
84+
85+
func (sc *SecurityContext) IsEmpty() bool {
86+
return sc.ContextType == ""
87+
}
88+
89+
func (sc *SecurityContext) Type() string {
90+
return "SecurityContext"
91+
}
92+
5593
type IndexImageCatalogCreator struct {
5694
SkipTLS bool
5795
SkipTLSVerify bool
@@ -67,6 +105,7 @@ type IndexImageCatalogCreator struct {
67105
PreviousBundles []string
68106
cfg *operator.Configuration
69107
ChannelName string
108+
SecurityContext SecurityContext
70109
}
71110

72111
var _ CatalogCreator = &IndexImageCatalogCreator{}
@@ -98,6 +137,10 @@ func (c *IndexImageCatalogCreator) BindFlags(fs *pflag.FlagSet) {
98137
"while pulling bundles")
99138
fs.BoolVar(&c.UseHTTP, "use-http", false, "use plain HTTP for container image registries "+
100139
"while pulling bundles")
140+
141+
// default to Restricted
142+
c.SecurityContext = SecurityContext{ContextType: Restricted}
143+
fs.Var(&c.SecurityContext, "security-context-config", "specifies the security context to use for the catalog pod. allowed: 'restricted', 'legacy'.")
101144
}
102145

103146
func (c IndexImageCatalogCreator) CreateCatalog(ctx context.Context, name string) (*v1alpha1.CatalogSource, error) {
@@ -478,9 +521,10 @@ func (c IndexImageCatalogCreator) createAnnotatedRegistry(ctx context.Context, c
478521
if c.HasFBCLabel {
479522
// Initialize and create the FBC registry pod.
480523
fbcRegistryPod := fbcindex.FBCRegistryPod{
481-
BundleItems: items,
482-
IndexImage: c.IndexImage,
483-
FBCContent: c.FBCContent,
524+
BundleItems: items,
525+
IndexImage: c.IndexImage,
526+
FBCContent: c.FBCContent,
527+
SecurityContext: c.SecurityContext.String(),
484528
}
485529

486530
pod, err = fbcRegistryPod.Create(ctx, c.cfg, cs)
@@ -491,12 +535,13 @@ func (c IndexImageCatalogCreator) createAnnotatedRegistry(ctx context.Context, c
491535
} else {
492536
// Initialize and create registry pod
493537
registryPod := index.SQLiteRegistryPod{
494-
BundleItems: items,
495-
IndexImage: c.IndexImage,
496-
SecretName: c.SecretName,
497-
CASecretName: c.CASecretName,
498-
SkipTLSVerify: c.SkipTLSVerify,
499-
UseHTTP: c.UseHTTP,
538+
BundleItems: items,
539+
IndexImage: c.IndexImage,
540+
SecretName: c.SecretName,
541+
CASecretName: c.CASecretName,
542+
SkipTLSVerify: c.SkipTLSVerify,
543+
UseHTTP: c.UseHTTP,
544+
SecurityContext: c.SecurityContext.String(),
500545
}
501546

502547
if registryPod.DBPath, err = c.getDBPath(ctx); err != nil {
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// Copyright 2020 The Operator-SDK Authors
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package registry
16+
17+
import (
18+
. "github.com/onsi/ginkgo"
19+
. "github.com/onsi/gomega"
20+
)
21+
22+
var _ = Describe("IndexImage", func() {
23+
Context("SecurityContext", func() {
24+
Describe("String", func() {
25+
It("should return a string value of the enum", func() {
26+
sc := SecurityContext{}
27+
Expect(sc.String()).To(Equal(""))
28+
sc = SecurityContext{ContextType: Legacy}
29+
Expect(sc.String()).To(Equal("legacy"))
30+
})
31+
})
32+
Describe("Set", func() {
33+
var sc SecurityContext
34+
BeforeEach(func() {
35+
sc = SecurityContext{}
36+
Expect(sc.String()).To(Equal(""))
37+
})
38+
It("should not error with valid values", func() {
39+
err := sc.Set("legacy")
40+
Expect(sc.String()).To(Equal("legacy"))
41+
Expect(err).ToNot(HaveOccurred())
42+
err = sc.Set("restricted")
43+
Expect(sc.String()).To(Equal("restricted"))
44+
Expect(err).ToNot(HaveOccurred())
45+
})
46+
It("should return an error with unsupported values", func() {
47+
err := sc.Set("fake")
48+
Expect(err).To(HaveOccurred())
49+
Expect(err.Error()).To(Equal("must be one of \"legacy\", or \"restricted\""))
50+
51+
err = sc.Set("")
52+
Expect(err).To(HaveOccurred())
53+
Expect(err.Error()).To(Equal("must be one of \"legacy\", or \"restricted\""))
54+
})
55+
})
56+
Describe("IsEmpty", func() {
57+
var sc SecurityContext
58+
BeforeEach(func() {
59+
sc = SecurityContext{}
60+
Expect(sc.String()).To(Equal(""))
61+
})
62+
It("should return true default instantiation", func() {
63+
Expect(sc.IsEmpty()).To(BeTrue())
64+
})
65+
It("should return false if set a value", func() {
66+
_ = sc.Set("legacy")
67+
Expect(sc.IsEmpty()).To(BeFalse())
68+
69+
_ = sc.Set("restricted")
70+
Expect(sc.IsEmpty()).To(BeFalse())
71+
})
72+
})
73+
Describe("Type", func() {
74+
It("should return SecurityContext", func() {
75+
sc := SecurityContext{}
76+
Expect(sc.Type()).To(Equal("SecurityContext"))
77+
})
78+
})
79+
})
80+
})

website/content/en/docs/cli/operator-sdk_run_bundle-upgrade.md

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,16 +19,17 @@ operator-sdk run bundle-upgrade <bundle-image> [flags]
1919
### Options
2020

2121
```
22-
--ca-secret-name string Name of a generic secret containing a PEM root certificate file required to pull bundle images. This secret *must* be in the namespace that this command is configured to run in, and the file *must* be encoded under the key "cert.pem"
23-
-h, --help help for bundle-upgrade
24-
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
25-
-n, --namespace string If present, namespace scope for this CLI request
26-
--pull-secret-name string Name of image pull secret ("type: kubernetes.io/dockerconfigjson") required to pull bundle images. This secret *must* be both in the namespace and an imagePullSecret of the service account that this command is configured to run in
27-
--service-account string Service account name to bind registry objects to. If unset, the default service account is used. This value does not override the operator's service account
28-
--skip-tls skip authentication of image registry TLS certificate when pulling a bundle image in-cluster
29-
--skip-tls-verify skip TLS certificate verification for container image registries while pulling bundles
30-
--timeout duration Duration to wait for the command to complete before failing (default 2m0s)
31-
--use-http use plain HTTP for container image registries while pulling bundles
22+
--ca-secret-name string Name of a generic secret containing a PEM root certificate file required to pull bundle images. This secret *must* be in the namespace that this command is configured to run in, and the file *must* be encoded under the key "cert.pem"
23+
-h, --help help for bundle-upgrade
24+
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
25+
-n, --namespace string If present, namespace scope for this CLI request
26+
--pull-secret-name string Name of image pull secret ("type: kubernetes.io/dockerconfigjson") required to pull bundle images. This secret *must* be both in the namespace and an imagePullSecret of the service account that this command is configured to run in
27+
--security-context-config SecurityContext specifies the security context to use for the catalog pod. allowed: 'restricted', 'legacy'. (default restricted)
28+
--service-account string Service account name to bind registry objects to. If unset, the default service account is used. This value does not override the operator's service account
29+
--skip-tls skip authentication of image registry TLS certificate when pulling a bundle image in-cluster
30+
--skip-tls-verify skip TLS certificate verification for container image registries while pulling bundles
31+
--timeout duration Duration to wait for the command to complete before failing (default 2m0s)
32+
--use-http use plain HTTP for container image registries while pulling bundles
3233
```
3334

3435
### Options inherited from parent commands

website/content/en/docs/cli/operator-sdk_run_bundle.md

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,19 @@ operator-sdk run bundle <bundle-image> [flags]
2828
### Options
2929

3030
```
31-
--ca-secret-name string Name of a generic secret containing a PEM root certificate file required to pull bundle images. This secret *must* be in the namespace that this command is configured to run in, and the file *must* be encoded under the key "cert.pem"
32-
-h, --help help for bundle
33-
--index-image string index image in which to inject bundle (default "quay.io/operator-framework/opm:latest")
34-
--install-mode InstallModeValue install mode
35-
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
36-
-n, --namespace string If present, namespace scope for this CLI request
37-
--pull-secret-name string Name of image pull secret ("type: kubernetes.io/dockerconfigjson") required to pull bundle images. This secret *must* be both in the namespace and an imagePullSecret of the service account that this command is configured to run in
38-
--service-account string Service account name to bind registry objects to. If unset, the default service account is used. This value does not override the operator's service account
39-
--skip-tls skip authentication of image registry TLS certificate when pulling a bundle image in-cluster
40-
--skip-tls-verify skip TLS certificate verification for container image registries while pulling bundles
41-
--timeout duration Duration to wait for the command to complete before failing (default 2m0s)
42-
--use-http use plain HTTP for container image registries while pulling bundles
31+
--ca-secret-name string Name of a generic secret containing a PEM root certificate file required to pull bundle images. This secret *must* be in the namespace that this command is configured to run in, and the file *must* be encoded under the key "cert.pem"
32+
-h, --help help for bundle
33+
--index-image string index image in which to inject bundle (default "quay.io/operator-framework/opm:latest")
34+
--install-mode InstallModeValue install mode
35+
--kubeconfig string Path to the kubeconfig file to use for CLI requests.
36+
-n, --namespace string If present, namespace scope for this CLI request
37+
--pull-secret-name string Name of image pull secret ("type: kubernetes.io/dockerconfigjson") required to pull bundle images. This secret *must* be both in the namespace and an imagePullSecret of the service account that this command is configured to run in
38+
--security-context-config SecurityContext specifies the security context to use for the catalog pod. allowed: 'restricted', 'legacy'. (default restricted)
39+
--service-account string Service account name to bind registry objects to. If unset, the default service account is used. This value does not override the operator's service account
40+
--skip-tls skip authentication of image registry TLS certificate when pulling a bundle image in-cluster
41+
--skip-tls-verify skip TLS certificate verification for container image registries while pulling bundles
42+
--timeout duration Duration to wait for the command to complete before failing (default 2m0s)
43+
--use-http use plain HTTP for container image registries while pulling bundles
4344
```
4445

4546
### Options inherited from parent commands

0 commit comments

Comments
 (0)