Skip to content

Commit 6bab0fc

Browse files
committed
wip on making service account optional; need to add synthetic auth back in
Signed-off-by: Joe Lanford <[email protected]>
1 parent a6027b8 commit 6bab0fc

File tree

12 files changed

+86
-34
lines changed

12 files changed

+86
-34
lines changed

api/v1/clusterextension_types.go

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,20 @@ type ClusterExtensionSpec struct {
7070
// serviceAccount is a reference to a ServiceAccount used to perform all interactions
7171
// with the cluster that are required to manage the extension.
7272
// Appropriate RBAC must be configured to grant the necessary permissions to the ServiceAccount.
73+
//
74+
// <opcon:standard:description>
7375
// serviceAccount is required.
76+
// </opcon:standard:description>
7477
//
75-
// +kubebuilder:validation:Required
76-
ServiceAccount ServiceAccountReference `json:"serviceAccount"`
78+
// <opcon:experimental:description>
79+
// If not set, operator-controller will authenticate as:
80+
// - User: "olmv1:clusterextension:<clusterExtensionName>"
81+
// - Group: "olmv1:clusterextensions"
82+
// </opcon:experimental:description>
83+
//
84+
// <opcon:standard:validation:Required>
85+
// <opcon:experimental:validation:Optional>
86+
ServiceAccount *ServiceAccountReference `json:"serviceAccount,omitempty"`
7787

7888
// source is a required field which selects the installation source of content
7989
// for this ClusterExtension. Selection is performed by setting the sourceType.
@@ -373,7 +383,7 @@ type CatalogFilter struct {
373383
UpgradeConstraintPolicy UpgradeConstraintPolicy `json:"upgradeConstraintPolicy,omitempty"`
374384
}
375385

376-
// ServiceAccountReference identifies the serviceAccount name used for managing a ClusterExtension.
386+
// ServiceAccountReference identifies the serviceAccount name used to manage a ClusterExtension.
377387
type ServiceAccountReference struct {
378388
// name is a required, immutable reference to the name of the ServiceAccount
379389
// to be used for installation and management of the content for the package

config/samples/olm_v1_clusterextension.yaml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,8 +282,6 @@ metadata:
282282
name: argocd
283283
spec:
284284
namespace: argocd
285-
serviceAccount:
286-
name: argocd-installer
287285
source:
288286
sourceType: Catalog
289287
catalog:

docs/api-reference/olmv1-api-reference.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -340,7 +340,7 @@ _Appears in:_
340340
| Field | Description | Default | Validation |
341341
| --- | --- | --- | --- |
342342
| `namespace` _string_ | namespace is a reference to a Kubernetes namespace.<br />This designates the default namespace where namespace-scoped resources<br />for the extension are applied to the cluster.<br />Some extensions may contain namespace-scoped resources to be applied in other namespaces.<br />This namespace must exist.<br />namespace is required, immutable, and follows the DNS label standard<br />as defined in [RFC 1123]. It must contain only lowercase alphanumeric characters or hyphens (-),<br />start and end with an alphanumeric character, and be no longer than 63 characters<br />[RFC 1123]: https://tools.ietf.org/html/rfc1123 | | MaxLength: 63 <br />Required: \{\} <br /> |
343-
| `serviceAccount` _[ServiceAccountReference](#serviceaccountreference)_ | serviceAccount is a reference to a ServiceAccount used to perform all interactions<br />with the cluster that are required to manage the extension.<br />Appropriate RBAC must be configured to grant the necessary permissions to the ServiceAccount.<br />serviceAccount is required. | | Required: \{\} <br /> |
343+
| `serviceAccount` _[ServiceAccountReference](#serviceaccountreference)_ | serviceAccount is an optional field that references a ServiceAccount used to<br />perform all interactions with the cluster that are required to manage the extension.<br />If not set, operator-controller will use its own ServiceAccount for extension management.<br />Appropriate RBAC must be configured to grant the necessary permissions to the ServiceAccount. | | |
344344
| `source` _[SourceConfig](#sourceconfig)_ | source is a required field which selects the installation source of content<br />for this ClusterExtension. Selection is performed by setting the sourceType.<br />Catalog is currently the only implemented sourceType, and setting the<br />sourcetype to "Catalog" requires the catalog field to also be defined.<br />Below is a minimal example of a source definition (in yaml):<br />source:<br /> sourceType: Catalog<br /> catalog:<br /> packageName: example-package | | Required: \{\} <br /> |
345345
| `install` _[ClusterExtensionInstallConfig](#clusterextensioninstallconfig)_ | install is an optional field used to configure the installation options<br />for the ClusterExtension such as the pre-flight check configuration. | | |
346346
| `config` _[ClusterExtensionConfig](#clusterextensionconfig)_ | config is an optional field used to specify bundle specific configuration<br />used to configure the bundle. Configuration is bundle specific and a bundle may provide<br />a configuration schema. When not specified, the default configuration of the resolved bundle will be used.<br />config is validated against a configuration schema provided by the resolved bundle. If the bundle does not provide<br />a configuration schema the final manifests will be derived on a best-effort basis. More information on how<br />to configure the bundle should be found in its end-user documentation.<br /><opcon:experimental> | | |
@@ -439,7 +439,7 @@ _Appears in:_
439439

440440

441441

442-
ServiceAccountReference identifies the serviceAccount name used for managing a ClusterExtension.
442+
ServiceAccountReference identifies the serviceAccount name used to manage a ClusterExtension.
443443

444444

445445

@@ -448,7 +448,7 @@ _Appears in:_
448448

449449
| Field | Description | Default | Validation |
450450
| --- | --- | --- | --- |
451-
| `name` _string_ | name is a required, immutable reference to the name of the ServiceAccount<br />to be used for installation and management of the content for the package<br />specified in the packageName field.<br />name follows the DNS subdomain standard as defined in [RFC 1123].<br />It must contain only lowercase alphanumeric characters,<br />hyphens (-) or periods (.), start and end with an alphanumeric character,<br />and be no longer than 253 characters.<br />Some examples of valid values are:<br /> - some-serviceaccount<br /> - 123-serviceaccount<br /> - 1-serviceaccount-2<br /> - someserviceaccount<br /> - some.serviceaccount<br />Some examples of invalid values are:<br /> - -some-serviceaccount<br /> - some-serviceaccount-<br />[RFC 1123]: https://tools.ietf.org/html/rfc1123 | | MaxLength: 253 <br />Required: \{\} <br /> |
451+
| `name` _string_ | name is a required, immutable reference to the name of the ServiceAccount<br />to be used for installation and management of the content for the package<br />specified in the packageName field.<br />name follows the DNS subdomain standard as defined in [RFC 1123].<br />It must contain only lowercase alphanumeric characters,<br />hyphens (-) or periods (.), start and end with an alphanumeric character,<br />and be no longer than 253 characters.<br />Some examples of valid values are:<br /> - some-serviceaccount<br /> - 123-serviceaccount<br /> - 1-serviceaccount-2<br /> - someserviceaccount<br /> - some.serviceaccount<br />Some examples of invalid values are:<br /> - -some-serviceaccount<br /> - some-serviceaccount-<br />[RFC 1123]: https://tools.ietf.org/html/rfc1123 | | MaxLength: 253 <br /> |
452452

453453

454454
#### SourceConfig

hack/tools/crd-generator/main.go

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"log"
2424
"os"
2525
"regexp"
26+
"slices"
2627
"strings"
2728

2829
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
@@ -136,7 +137,7 @@ func runGenerator(args ...string) {
136137
if channel == StandardChannel && strings.Contains(version.Name, "alpha") {
137138
channelCrd.Spec.Versions[i].Served = false
138139
}
139-
version.Schema.OpenAPIV3Schema.Properties = opconTweaksMap(channel, version.Schema.OpenAPIV3Schema.Properties)
140+
version.Schema.OpenAPIV3Schema.Properties = opconTweaksMap(channel, version.Schema.OpenAPIV3Schema)
140141
}
141142

142143
conv, err := crd.AsVersion(*channelCrd, apiextensionsv1.SchemeGroupVersion)
@@ -179,10 +180,11 @@ func runGenerator(args ...string) {
179180
}
180181
}
181182

182-
func opconTweaksMap(channel string, props map[string]apiextensionsv1.JSONSchemaProps) map[string]apiextensionsv1.JSONSchemaProps {
183+
func opconTweaksMap(channel string, obj *apiextensionsv1.JSONSchemaProps) map[string]apiextensionsv1.JSONSchemaProps {
184+
props := obj.Properties
183185
for name := range props {
184186
jsonProps := props[name]
185-
p := opconTweaks(channel, name, jsonProps)
187+
p := opconTweaks(channel, name, obj, jsonProps)
186188
if p == nil {
187189
delete(props, name)
188190
} else {
@@ -194,7 +196,7 @@ func opconTweaksMap(channel string, props map[string]apiextensionsv1.JSONSchemaP
194196

195197
// Custom Opcon API Tweaks for tags prefixed with `<opcon:` that get past
196198
// the limitations of Kubebuilder annotations.
197-
func opconTweaks(channel string, name string, jsonProps apiextensionsv1.JSONSchemaProps) *apiextensionsv1.JSONSchemaProps {
199+
func opconTweaks(channel string, name string, parent *apiextensionsv1.JSONSchemaProps, jsonProps apiextensionsv1.JSONSchemaProps) *apiextensionsv1.JSONSchemaProps {
198200
if channel == StandardChannel {
199201
if strings.Contains(jsonProps.Description, "<opcon:experimental>") {
200202
return nil
@@ -210,6 +212,22 @@ func opconTweaks(channel string, name string, jsonProps apiextensionsv1.JSONSche
210212
numExpressions := strings.Count(jsonProps.Description, validationPrefix)
211213
numValid := 0
212214
if numExpressions > 0 {
215+
requiredRe := regexp.MustCompile(validationPrefix + "Required>")
216+
requiredMatches := requiredRe.FindAllStringSubmatch(jsonProps.Description, -1)
217+
for _, _ = range requiredMatches {
218+
numValid += 1
219+
parent.Required = append(parent.Required, name)
220+
slices.Sort(parent.Required)
221+
}
222+
223+
optionalRe := regexp.MustCompile(validationPrefix + "Optional>")
224+
optionalMatches := optionalRe.FindAllStringSubmatch(jsonProps.Description, -1)
225+
for _, _ = range optionalMatches {
226+
numValid += 1
227+
parent.Required = slices.DeleteFunc(parent.Required, func(s string) bool { return s == name })
228+
slices.Sort(parent.Required)
229+
}
230+
213231
enumRe := regexp.MustCompile(validationPrefix + "Enum=([A-Za-z;]*)>")
214232
enumMatches := enumRe.FindAllStringSubmatch(jsonProps.Description, 64)
215233
for _, enumMatch := range enumMatches {
@@ -246,36 +264,51 @@ func opconTweaks(channel string, name string, jsonProps apiextensionsv1.JSONSche
246264
jsonProps.Description = formatDescription(jsonProps.Description, channel, name)
247265

248266
if len(jsonProps.Properties) > 0 {
249-
jsonProps.Properties = opconTweaksMap(channel, jsonProps.Properties)
267+
jsonProps.Properties = opconTweaksMap(channel, &jsonProps)
250268
} else if jsonProps.Items != nil && jsonProps.Items.Schema != nil {
251-
jsonProps.Items.Schema = opconTweaks(channel, name, *jsonProps.Items.Schema)
269+
jsonProps.Items.Schema = opconTweaks(channel, name, &jsonProps, *jsonProps.Items.Schema)
252270
}
253271

254272
return &jsonProps
255273
}
256274

257275
func formatDescription(description string, channel string, name string) string {
258-
startTag := "<opcon:experimental:description>"
259-
endTag := "</opcon:experimental:description>"
260-
if channel == StandardChannel && strings.Contains(description, startTag) {
261-
regexPattern := `\n*` + regexp.QuoteMeta(startTag) + `(?s:(.*?))` + regexp.QuoteMeta(endTag) + `\n*`
276+
startTagStandard := "<opcon:standard:description>"
277+
endTagStandard := "</opcon:standard:description>"
278+
if channel == ExperimentalChannel && strings.Contains(description, startTagStandard) {
279+
regexPattern := `\n*` + regexp.QuoteMeta(startTagStandard) + `(?s:(.*?))` + regexp.QuoteMeta(endTagStandard) + `\n*`
280+
re := regexp.MustCompile(regexPattern)
281+
match := re.FindStringSubmatch(description)
282+
if len(match) != 2 {
283+
log.Fatalf("Invalid <opcon:standard:description> tag for %s", name)
284+
}
285+
description = re.ReplaceAllString(description, "\n\n")
286+
} else {
287+
description = strings.ReplaceAll(description, startTagStandard, "")
288+
description = strings.ReplaceAll(description, endTagStandard, "")
289+
}
290+
291+
startTagExperimental := "<opcon:experimental:description>"
292+
endTagExperimental := "</opcon:experimental:description>"
293+
if channel == StandardChannel && strings.Contains(description, startTagExperimental) {
294+
regexPattern := `\n*` + regexp.QuoteMeta(startTagExperimental) + `(?s:(.*?))` + regexp.QuoteMeta(endTagExperimental) + `\n*`
262295
re := regexp.MustCompile(regexPattern)
263296
match := re.FindStringSubmatch(description)
264297
if len(match) != 2 {
265298
log.Fatalf("Invalid <opcon:experimental:description> tag for %s", name)
266299
}
267300
description = re.ReplaceAllString(description, "\n\n")
268301
} else {
269-
description = strings.ReplaceAll(description, startTag, "")
270-
description = strings.ReplaceAll(description, endTag, "")
302+
description = strings.ReplaceAll(description, startTagExperimental, "")
303+
description = strings.ReplaceAll(description, endTagExperimental, "")
271304
}
272305

273306
// Comments within "opcon:util:excludeFromCRD" tag are not included in the generated CRD and all trailing \n operators before
274307
// and after the tags are removed and replaced with three \n operators.
275-
startTag = "<opcon:util:excludeFromCRD>"
276-
endTag = "</opcon:util:excludeFromCRD>"
277-
if strings.Contains(description, startTag) {
278-
regexPattern := `\n*` + regexp.QuoteMeta(startTag) + `(?s:(.*?))` + regexp.QuoteMeta(endTag) + `\n*`
308+
startTagExclude := "<opcon:util:excludeFromCRD>"
309+
endTagExclude := "</opcon:util:excludeFromCRD>"
310+
if strings.Contains(description, startTagExclude) {
311+
regexPattern := `\n*` + regexp.QuoteMeta(startTagExclude) + `(?s:(.*?))` + regexp.QuoteMeta(endTagExclude) + `\n*`
279312
re := regexp.MustCompile(regexPattern)
280313
match := re.FindStringSubmatch(description)
281314
if len(match) != 2 {

helm/olmv1/base/operator-controller/crd/experimental/olm.operatorframework.io_clusterextensions.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,10 @@ spec:
174174
serviceAccount is a reference to a ServiceAccount used to perform all interactions
175175
with the cluster that are required to manage the extension.
176176
Appropriate RBAC must be configured to grant the necessary permissions to the ServiceAccount.
177-
serviceAccount is required.
177+
178+
If not set, operator-controller will authenticate as:
179+
- User: "olmv1:clusterextension:<clusterExtensionName>"
180+
- Group: "olmv1:clusterextensions"
178181
properties:
179182
name:
180183
description: |-
@@ -495,7 +498,6 @@ spec:
495498
has(self.catalog) : !has(self.catalog)'
496499
required:
497500
- namespace
498-
- serviceAccount
499501
- source
500502
type: object
501503
status:

helm/olmv1/base/operator-controller/crd/standard/olm.operatorframework.io_clusterextensions.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ spec:
135135
serviceAccount is a reference to a ServiceAccount used to perform all interactions
136136
with the cluster that are required to manage the extension.
137137
Appropriate RBAC must be configured to grant the necessary permissions to the ServiceAccount.
138+
138139
serviceAccount is required.
139140
properties:
140141
name:

internal/operator-controller/action/restconfig.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ func ServiceAccountRestConfigMapper() func(ctx context.Context, o client.Object,
2323
return nil, err
2424
}
2525
cc := rest.CopyConfig(c)
26-
cc.Wrap(func(rt http.RoundTripper) http.RoundTripper {
27-
return transport.NewImpersonatingRoundTripper(authentication.ServiceAccountImpersonationConfig(*cExt), rt)
28-
})
26+
if cExt.Spec.ServiceAccount.Name != "" {
27+
cc.Wrap(func(rt http.RoundTripper) http.RoundTripper {
28+
return transport.NewImpersonatingRoundTripper(authentication.ServiceAccountImpersonationConfig(*cExt), rt)
29+
})
30+
}
2931
return cc, nil
3032
}
3133
}

internal/operator-controller/applier/helm.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ func (h *Helm) Apply(ctx context.Context, contentFS fs.FS, ext *ocv1.ClusterExte
113113
labels: objectLabels,
114114
}
115115

116-
if h.PreAuthorizer != nil {
116+
if h.PreAuthorizer != nil && ext.Spec.ServiceAccount.Name != "" {
117117
err := h.runPreAuthorizationChecks(ctx, ext, chrt, values, post)
118118
if err != nil {
119119
// Return the pre-authorization error directly

manifests/experimental-e2e.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -979,7 +979,10 @@ spec:
979979
serviceAccount is a reference to a ServiceAccount used to perform all interactions
980980
with the cluster that are required to manage the extension.
981981
Appropriate RBAC must be configured to grant the necessary permissions to the ServiceAccount.
982-
serviceAccount is required.
982+
983+
If not set, operator-controller will authenticate as:
984+
- User: "olmv1:clusterextension:<clusterExtensionName>"
985+
- Group: "olmv1:clusterextensions"
983986
properties:
984987
name:
985988
description: |-
@@ -1300,7 +1303,6 @@ spec:
13001303
has(self.catalog) : !has(self.catalog)'
13011304
required:
13021305
- namespace
1303-
- serviceAccount
13041306
- source
13051307
type: object
13061308
status:

manifests/experimental.yaml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,10 @@ spec:
944944
serviceAccount is a reference to a ServiceAccount used to perform all interactions
945945
with the cluster that are required to manage the extension.
946946
Appropriate RBAC must be configured to grant the necessary permissions to the ServiceAccount.
947-
serviceAccount is required.
947+
948+
If not set, operator-controller will authenticate as:
949+
- User: "olmv1:clusterextension:<clusterExtensionName>"
950+
- Group: "olmv1:clusterextensions"
948951
properties:
949952
name:
950953
description: |-
@@ -1265,7 +1268,6 @@ spec:
12651268
has(self.catalog) : !has(self.catalog)'
12661269
required:
12671270
- namespace
1268-
- serviceAccount
12691271
- source
12701272
type: object
12711273
status:

0 commit comments

Comments
 (0)