-
Notifications
You must be signed in to change notification settings - Fork 213
Refactor the verify package to not have dependencies on CVO #279
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9bbf366
527b126
a82639c
abd6802
2ba18d8
1d13e88
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -12,9 +12,11 @@ import ( | |
|
|
||
| "github.com/blang/semver" | ||
| "github.com/google/uuid" | ||
| "github.com/pkg/errors" | ||
| corev1 "k8s.io/api/core/v1" | ||
| apierrors "k8s.io/apimachinery/pkg/api/errors" | ||
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
| "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" | ||
| utilruntime "k8s.io/apimachinery/pkg/util/runtime" | ||
| "k8s.io/apimachinery/pkg/util/wait" | ||
| informerscorev1 "k8s.io/client-go/informers/core/v1" | ||
|
|
@@ -44,6 +46,7 @@ import ( | |
| "github.com/openshift/cluster-version-operator/pkg/payload/precondition" | ||
| preconditioncv "github.com/openshift/cluster-version-operator/pkg/payload/precondition/clusterversion" | ||
| "github.com/openshift/cluster-version-operator/pkg/verify" | ||
| "github.com/openshift/cluster-version-operator/pkg/verify/verifyconfigmap" | ||
| ) | ||
|
|
||
| const ( | ||
|
|
@@ -134,6 +137,9 @@ type Operator struct { | |
| // verifier, if provided, will be used to check an update before it is executed. | ||
| // Any error will prevent an update payload from being accessed. | ||
| verifier verify.Interface | ||
| // signatureStore, if set, will be used to periodically persist signatures to | ||
| // the cluster as a config map | ||
| signatureStore *verify.StorePersister | ||
|
|
||
| configSync ConfigSyncWorker | ||
| // statusInterval is how often the configSync worker is allowed to retrigger | ||
|
|
@@ -236,17 +242,21 @@ func (optr *Operator) InitializeFromPayload(restConfig *rest.Config, burstRestCo | |
| } | ||
| // XXX: set this to the cincinnati version in preference | ||
| if _, err := semver.Parse(update.ImageRef.Name); err != nil { | ||
| return fmt.Errorf("The local release contents name %q is not a valid semantic version - no current version will be reported: %v", update.ImageRef.Name, err) | ||
| return fmt.Errorf("the local release contents name %q is not a valid semantic version - no current version will be reported: %v", update.ImageRef.Name, err) | ||
| } | ||
|
|
||
| optr.releaseCreated = update.ImageRef.CreationTimestamp.Time | ||
| optr.releaseVersion = update.ImageRef.Name | ||
|
|
||
| // Wraps operator's HTTPClient method to allow releaseVerifier to create http client with up-to-date config. | ||
| clientBuilder := &verifyClientBuilder{builder: optr.HTTPClient} | ||
| configClient, err := coreclientsetv1.NewForConfig(restConfig) | ||
| if err != nil { | ||
| return fmt.Errorf("unable to create a configuration client: %v", err) | ||
| } | ||
|
|
||
| // attempt to load a verifier as defined in the payload | ||
| verifier, err := verify.LoadFromPayload(update, clientBuilder) | ||
| verifier, signatureStore, err := loadConfigMapVerifierDataFromUpdate(update, clientBuilder, configClient) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
@@ -257,6 +267,7 @@ func (optr *Operator) InitializeFromPayload(restConfig *rest.Config, burstRestCo | |
| verifier = verify.Reject | ||
| } | ||
| optr.verifier = verifier | ||
| optr.signatureStore = signatureStore | ||
|
|
||
| // after the verifier has been loaded, initialize the sync worker with a payload retriever | ||
| // which will consume the verifier | ||
|
|
@@ -276,6 +287,39 @@ func (optr *Operator) InitializeFromPayload(restConfig *rest.Config, burstRestCo | |
| return nil | ||
| } | ||
|
|
||
| // loadConfigMapVerifierDataFromUpdate fetches the first config map in the payload with the correct annotation. | ||
| // It returns an error if the data is not valid, or no verifier if no config map is found. See the verify | ||
| // package for more details on the algorithm for verification. If the annotation is set, a verifier or error | ||
| // is always returned. | ||
| func loadConfigMapVerifierDataFromUpdate(update *payload.Update, clientBuilder verify.ClientBuilder, configMapClient coreclientsetv1.ConfigMapsGetter) (verify.Interface, *verify.StorePersister, error) { | ||
| configMapGVK := corev1.SchemeGroupVersion.WithKind("ConfigMap") | ||
| for _, manifest := range update.Manifests { | ||
| if manifest.GVK != configMapGVK { | ||
| continue | ||
| } | ||
| if _, ok := manifest.Obj.GetAnnotations()[verify.ReleaseAnnotationConfigMapVerifier]; !ok { | ||
| continue | ||
| } | ||
| src := fmt.Sprintf("the config map %s/%s", manifest.Obj.GetNamespace(), manifest.Obj.GetName()) | ||
| data, _, err := unstructured.NestedStringMap(manifest.Obj.Object, "data") | ||
| if err != nil { | ||
| return nil, nil, errors.Wrapf(err, "%s is not valid: %v", src, err) | ||
| } | ||
| verifier, err := verify.NewFromConfigMapData(src, data, clientBuilder) | ||
| if err != nil { | ||
| return nil, nil, err | ||
| } | ||
|
|
||
| // allow the verifier to consult the cluster for signature data, and also configure | ||
| // a process that writes signatures back to that store | ||
| signatureStore := verifyconfigmap.NewStore(configMapClient, nil) | ||
| verifier = verifier.WithStores(signatureStore) | ||
| persister := verify.NewSignatureStorePersister(signatureStore, verifier) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Having |
||
| return verifier, persister, nil | ||
| } | ||
| return nil, nil, nil | ||
| } | ||
|
|
||
| // Run runs the cluster version operator until stopCh is completed. Workers is ignored for now. | ||
| func (optr *Operator) Run(ctx context.Context, workers int) { | ||
| defer utilruntime.HandleCrash() | ||
|
|
@@ -310,6 +354,9 @@ func (optr *Operator) Run(ctx context.Context, workers int) { | |
| utilruntime.HandleError(fmt.Errorf("unable to perform final sync: %v", err)) | ||
| } | ||
| }, time.Second, stopCh) | ||
| if optr.signatureStore != nil { | ||
| go optr.signatureStore.Run(ctx, optr.minimumUpdateCheckInterval*2) | ||
| } | ||
|
|
||
| <-stopCh | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR is epic. Can we pull things like this and the collector pointer bit out into separate pull requests so they can land while the API refactor and feature extension stuff gets hashed out?