55 "context"
66 "errors"
77 "fmt"
8+ "io"
89 "io/fs"
910 "maps"
1011 "slices"
@@ -26,6 +27,7 @@ import (
2627 helmclient "github.com/operator-framework/helm-operator-plugins/pkg/client"
2728
2829 ocv1 "github.com/operator-framework/operator-controller/api/v1"
30+ "github.com/operator-framework/operator-controller/internal/operator-controller/authorization"
2931 "github.com/operator-framework/operator-controller/internal/operator-controller/labels"
3032 "github.com/operator-framework/operator-controller/internal/shared/util/cache"
3133)
@@ -274,23 +276,14 @@ type Boxcutter struct {
274276 Scheme * runtime.Scheme
275277 RevisionGenerator ClusterExtensionRevisionGenerator
276278 Preflights []Preflight
279+ PreAuthorizer authorization.PreAuthorizer
277280 FieldOwner string
278281}
279282
280283func (bc * Boxcutter ) Apply (ctx context.Context , contentFS fs.FS , ext * ocv1.ClusterExtension , objectLabels , revisionAnnotations map [string ]string ) (bool , string , error ) {
281284 return bc .apply (ctx , contentFS , ext , objectLabels , revisionAnnotations )
282285}
283286
284- func (bc * Boxcutter ) getObjects (rev * ocv1.ClusterExtensionRevision ) []client.Object {
285- var objs []client.Object
286- for _ , phase := range rev .Spec .Phases {
287- for _ , phaseObject := range phase .Objects {
288- objs = append (objs , & phaseObject .Object )
289- }
290- }
291- return objs
292- }
293-
294287func (bc * Boxcutter ) createOrUpdate (ctx context.Context , obj client.Object ) error {
295288 if obj .GetObjectKind ().GroupVersionKind ().Empty () {
296289 gvk , err := apiutil .GVKForObject (obj , bc .Scheme )
@@ -309,6 +302,11 @@ func (bc *Boxcutter) apply(ctx context.Context, contentFS fs.FS, ext *ocv1.Clust
309302 return false , "" , err
310303 }
311304
305+ // Run auth preflight checks
306+ if err := bc .runPreAuthorizationChecks (ctx , ext , desiredRevision ); err != nil {
307+ return false , "" , err
308+ }
309+
312310 if err := controllerutil .SetControllerReference (ext , desiredRevision , bc .Scheme ); err != nil {
313311 return false , "" , fmt .Errorf ("set ownerref: %w" , err )
314312 }
@@ -343,7 +341,7 @@ func (bc *Boxcutter) apply(ctx context.Context, contentFS fs.FS, ext *ocv1.Clust
343341 }
344342
345343 // Preflights
346- plainObjs := bc . getObjects (desiredRevision )
344+ plainObjs := getObjects (desiredRevision )
347345 for _ , preflight := range bc .Preflights {
348346 if shouldSkipPreflight (ctx , preflight , ext , state ) {
349347 continue
@@ -405,6 +403,18 @@ func (bc *Boxcutter) apply(ctx context.Context, contentFS fs.FS, ext *ocv1.Clust
405403 return true , "" , nil
406404}
407405
406+ func (bc * Boxcutter ) runPreAuthorizationChecks (ctx context.Context , ext * ocv1.ClusterExtension , rev * ocv1.ClusterExtensionRevision ) error {
407+ if bc .PreAuthorizer == nil {
408+ return nil
409+ }
410+
411+ manifestReader , err := revisionManifestReader (rev )
412+ if err != nil {
413+ return err
414+ }
415+ return formatPreAuthorizerOutput (bc .PreAuthorizer .PreAuthorize (ctx , ext , manifestReader ))
416+ }
417+
408418// garbageCollectOldRevisions deletes archived revisions beyond ClusterExtensionRevisionRetentionLimit.
409419// Active revisions are never deleted. revisionList must be sorted oldest to newest.
410420func (bc * Boxcutter ) garbageCollectOldRevisions (ctx context.Context , revisionList []ocv1.ClusterExtensionRevision ) error {
@@ -463,3 +473,27 @@ func splitManifestDocuments(file string) []string {
463473 }
464474 return docs
465475}
476+
477+ func getObjects (rev * ocv1.ClusterExtensionRevision ) []client.Object {
478+ var objs []client.Object
479+ for _ , phase := range rev .Spec .Phases {
480+ for _ , phaseObject := range phase .Objects {
481+ objs = append (objs , & phaseObject .Object )
482+ }
483+ }
484+ return objs
485+ }
486+
487+ func revisionManifestReader (rev * ocv1.ClusterExtensionRevision ) (io.Reader , error ) {
488+ var manifestBuilder strings.Builder
489+ for _ , obj := range getObjects (rev ) {
490+ objBytes , err := yaml .Marshal (obj )
491+ if err != nil {
492+ return nil , fmt .Errorf ("error generating revision manifest: %w" , err )
493+ }
494+ manifestBuilder .WriteString ("---\n " )
495+ manifestBuilder .WriteString (string (objBytes ))
496+ manifestBuilder .WriteString ("\n " )
497+ }
498+ return strings .NewReader (manifestBuilder .String ()), nil
499+ }
0 commit comments