-
Notifications
You must be signed in to change notification settings - Fork 83
Manage Build Controller Additional Trusted CA #32
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
Conversation
2c25dbf to
cc8c976
Compare
adambkaplan
left a comment
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.
/assign @bparees
pkg/operator/observe_config.go
Outdated
| func observeBuildAdditionalCAIsSet(listers Listers, observedConfig map[string]interface{}) (map[string]interface{}, error) { | ||
| // observed state of the build controller's Additional CA bundle is stored in a ConfigMap within the operator namespace | ||
| // this observes if there is data in this ConfigMap, and if the ca bundle exists | ||
| caMap, err := listers.configmapLister.ConfigMaps(operatorNamespaceName).Get("openshift-build-additional-ca") |
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.
Note - the "observed CA" ConfigMap will be added in a later PR.
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.
Added to what?
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.
(what is the "observed CA" configmap?)
| } | ||
|
|
||
| func manageBuildAdditionalCAConfigMap(client coreclientv1.ConfigMapsGetter) (*corev1.ConfigMap, bool, error) { | ||
| caMap := resourceread.ReadConfigMapV1OrDie(v311_00_assets.MustAsset("v3.11.0/openshift-controller-manager/build-additional-ca-cm.yaml")) |
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 syncs the observed CA bundle into the controller-manager's additional-ca configMap.
|
/retest |
pkg/operator/observe_config.go
Outdated
| kubeInformersForOpenshiftCoreOperators.Core().V1().Namespaces().Informer().AddEventHandler(c.eventHandler()) | ||
| configInformer.Config().V1().Images().Informer().AddEventHandler(c.eventHandler()) | ||
| // Watch for changes to configMaps within the core operator's namespace | ||
| kubeInformersForOpenshiftCoreOperators.Core().V1().ConfigMaps().Informer().AddEventHandler(c.eventHandler()) |
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.
You need to get the buildCA configmap's namespace from the BuildConfig object's ConfigMapReference. You can't assume it's in the operator's namespace.
This also means that if the BuildConfig's ConfigMapReference changes, you have to detect that and, at a minimum, panic/exit the operator (it will then restart, read the new reference, and setup the watch for the new namespace/configmap to be watched).
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.
You should also only be watching exactly the configmap that the ConfigMapReference points to (@deads2k says he can help point you to how to setup a single resource watch).
pkg/operator/observe_config.go
Outdated
| } | ||
|
|
||
| // observeBuildAdditionalCAPath observes the data in the controller's generated | ||
| func observeBuildAdditionalCAIsSet(listers Listers, observedConfig map[string]interface{}) (map[string]interface{}, error) { |
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.
godoc + function name not aligned
pkg/operator/observe_config.go
Outdated
| func observeBuildAdditionalCAIsSet(listers Listers, observedConfig map[string]interface{}) (map[string]interface{}, error) { | ||
| // observed state of the build controller's Additional CA bundle is stored in a ConfigMap within the operator namespace | ||
| // this observes if there is data in this ConfigMap, and if the ca bundle exists | ||
| caMap, err := listers.configmapLister.ConfigMaps(operatorNamespaceName).Get("openshift-build-additional-ca") |
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.
Added to what?
pkg/operator/observe_config.go
Outdated
| func observeBuildAdditionalCAIsSet(listers Listers, observedConfig map[string]interface{}) (map[string]interface{}, error) { | ||
| // observed state of the build controller's Additional CA bundle is stored in a ConfigMap within the operator namespace | ||
| // this observes if there is data in this ConfigMap, and if the ca bundle exists | ||
| caMap, err := listers.configmapLister.ConfigMaps(operatorNamespaceName).Get("openshift-build-additional-ca") |
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.
(what is the "observed CA" configmap?)
|
Maybe i've misunderstood what you're doing here... is this PR starting from the assumption that the referenced ConfigMap has already been copied into the controller-manager's namespace? (note that that is not the same as the operator's namespace....) Are we now going to have 3 copies of the configmap?
It seems like (2) should not be needed. |
|
(I also likely have an insufficient understanding of the existing operator behavior, especially around how it handles mounted resources) |
Yes, but (2) is not an exact copy. The operator will read the first user-provided configmap, merge the content (verifying proper encoding in the process), and then copy into the second configmap as the canonical "observed" CA. Hence why in this PR we are watching the configmaps in the core operators namespace. This approach gives us two main advantages:
However, I agree the additional configMap is a big minus and may not be necessary. Worth exploring storing hashes in the operator status. |
|
(I also say will because I plan to add the logic to watch the build CRD and associated ConfigMap in a separate PR) |
|
This is hard to think through(for me) but i think if you get rid of the intermediary configmap, you save some work on reconciling that all the right pieces are in place. I think the flow can be: every time we observe cluster-configmap: if hash(cluster-configmap)!=operator.status.hash By doing it in that order, we ensure that if we fail to update the controller deployment, next time we reconcile we'll go through all the steps again (because operator.status.hash still won't match the hash(cluster-configmap)) @deads2k am i missing something? |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: adambkaplan If they are not already assigned, you can assign the PR to them by writing The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
0edcb25 to
6ffa353
Compare
* Controller manager mounts additional CA bundle from ConfigMap * Operator watches build CRD and configmaps in openshift-config for changes * Operator validates additional CA data, merges into a single PEM block * Observed additional CA recorded in operator config spec, including sha1 hash * Primary sync loop merges additional CA data into a bundle mounted and read by the openshift-controller-manager
6ffa353 to
f2db4e5
Compare
adambkaplan
left a comment
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.
| ObservedConfig runtime.RawExtension `json:"observedConfig"` | ||
|
|
||
| // additionalTrustedCA references the additional trusted certificate authorities that operator should attempt to configure for the build controller. | ||
| AdditionalTrustedCA *AdditionalTrustedCA `json:"additionalTrustedCA,omitempty"` |
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 breaks the "no pointers" rule for API, but results in much cleaner code.
This will likely go away when certs are split out by hostname.
@deads2k do we need protobuf as well as json?
| SHA1Hash string `json:"sha1Hash,omitempty" protobuf:"bytes,1,opt,name=sha1Hash"` | ||
|
|
||
| // configMapName is the name of the ConfigMap in the openshift-config namespace containing the additional trusted CAs for the build controller. | ||
| ConfigMapName string `json:"configMap,omitempty" protobuf:"bytes,2,opt,name=configMap"` |
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.
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.
SHA probably belongs only in status, not spec, as it is not something the user gets to set.
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.
I did this for consistency, though we can probably get away without it.
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.
if we don't need it, let's get rid of it. just a source of confusion otherwise.
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.
Now I remember...I do this so we can capture that the cluster admin updated the data in the referenced ConfigMap. I want to avoid races due to having an informer for openshift-config here and in the main operator controller.
| imageConfigLister: configInformer.Config().V1().Images().Lister(), | ||
| coreOperatorsConfigMapLister: kubeInformersForOpenshiftCoreOperators.Core().V1().ConfigMaps().Lister(), | ||
| buildConfigLister: configInformer.Config().V1().Builds().Lister(), | ||
| clusterConfigConfigMapLister: openshiftConfigInformer.Core().V1().ConfigMaps().Lister(), |
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.
Lister for ConfigMaps in the openshift-config namespace.
|
|
||
| c.operatorConfigSynced = operatorConfigInformer.Informer().HasSynced | ||
| c.configmapSynced = kubeInformersForOpenshiftCoreOperators.Core().V1().ConfigMaps().Informer().HasSynced | ||
| c.coreOperatorsConfigSynced = kubeInformersForOpenshiftCoreOperators.Core().V1().ConfigMaps().Informer().HasSynced |
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.
Do we still need to watch the openshift-core-operators namespace?
| if err != nil { | ||
| return err | ||
| } | ||
| currentCASpec := operatorConfig.Spec.AdditionalTrustedCA.DeepCopy() |
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.
Fetch operator config first, which can be mutated by the observer functions.
Deep copy the current CA spec so we can exit early if no updates are needed.
| caMap.Data = nil | ||
| _, modified, err := resourceapply.ApplyConfigMap(client, caMap) | ||
| operatorConfig.Status.AdditionalTrustedCA = nil | ||
| return "", modified, err |
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.
If no build CRD, clear the data in the controller manager's ConfigMap and nil the status for AdditionalTrustedCA
| caMap.Data = nil | ||
| _, modified, err := resourceapply.ApplyConfigMap(client, caMap) | ||
| operatorConfig.Status.AdditionalTrustedCA = nil | ||
| return "", modified, err |
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.
Handle case of empty data in referenced ConfigMap
| if operatorConfig.Status.AdditionalTrustedCA != nil && | ||
| operatorConfig.Status.AdditionalTrustedCA.SHA1Hash == caHash { | ||
| return caHash, false, nil | ||
| } |
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.
If hashes are equivalent, no updates needed.
| } | ||
| caMap.Data["additional-ca.crt"] = string(caData) | ||
| _, modified, err := resourceapply.ApplyConfigMap(client, caMap) | ||
| return caHash, modified, err |
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.
If updates are happening, copy the merged data into the ConfigMap, which is then mounted into the build controller
| } | ||
| data = rest | ||
| } | ||
| } |
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.
mergePEMData ensures that the provided map contains valid PEM-encoded data for every key. This code may live on even if we are not merging CAs, as IMO the operator should validate that the provided certificates have valid encoding.
|
/retest |
|
/hold Will never merge, but leaving this up for teams with similar requirements. |
|
@adambkaplan: PR needs rebase. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. |
|
@adambkaplan: The following tests failed, say
Full PR test history. Your PR dashboard. Please help us cut down on flakes by linking to an open issue when you hit one in your PR. DetailsInstructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes/test-infra repository. I understand the commands that are listed here. |
|
This functionality was added in openshift/origin#21614 |
…ft-4.7-ose-cluster-kube-storage-version-migrator-operator Updating ose-cluster-kube-storage-version-migrator-operator builder & base images to be consistent with ART
Uh oh!
There was an error while loading. Please reload this page.