Skip to content

Commit 75b4524

Browse files
Merge pull request #796 from perdasilva/perdasilva/manual-sync-2406
NO-ISSUE: Manual Sync
2 parents 06c943a + b682d7e commit 75b4524

File tree

16 files changed

+426
-101
lines changed

16 files changed

+426
-101
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ e2e/operator-registry: ## Run e2e registry tests
130130
$(MAKE) e2e WHAT=operator-registry
131131

132132
e2e/olm: ## Run e2e olm tests
133-
$(MAKE) e2e WHAT=operator-lifecycle-manager E2E_CATALOG_NS=openshift-marketplace E2E_INSTALL_NS=openshift-operator-lifecycle-manager E2E_TEST_NS=openshift-operators E2E_TIMEOUT=120m KUBECTL=oc
133+
$(MAKE) e2e WHAT=operator-lifecycle-manager E2E_CATALOG_NS=openshift-marketplace E2E_INSTALL_NS=openshift-operator-lifecycle-manager E2E_TEST_NS=openshift-operators E2E_TIMEOUT=135m KUBECTL=oc
134134

135135
.PHONY: vendor
136136
vendor:

staging/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -863,14 +863,26 @@ func sortUnpackJobs(jobs []*batchv1.Job, maxRetainedJobs int) (latest *batchv1.J
863863
// sort jobs so that latest job is first
864864
// with preference for non-failed jobs
865865
sort.Slice(jobs, func(i, j int) bool {
866+
if jobs[i] == nil || jobs[j] == nil {
867+
return jobs[i] != nil
868+
}
866869
condI, failedI := getCondition(jobs[i], batchv1.JobFailed)
867870
condJ, failedJ := getCondition(jobs[j], batchv1.JobFailed)
868871
if failedI != failedJ {
869872
return !failedI // non-failed job goes first
870873
}
871874
return condI.LastTransitionTime.After(condJ.LastTransitionTime.Time)
872875
})
876+
if jobs[0] == nil {
877+
// all nil jobs
878+
return
879+
}
873880
latest = jobs[0]
881+
nilJobsIndex := len(jobs) - 1
882+
for ; nilJobsIndex >= 0 && jobs[nilJobsIndex] == nil; nilJobsIndex-- {
883+
}
884+
885+
jobs = jobs[:nilJobsIndex+1] // exclude nil jobs from list of jobs to delete
874886
if len(jobs) <= maxRetainedJobs {
875887
return
876888
}
@@ -880,7 +892,7 @@ func sortUnpackJobs(jobs []*batchv1.Job, maxRetainedJobs int) (latest *batchv1.J
880892
}
881893

882894
// cleanup old failed jobs, n-1 recent jobs and the oldest job
883-
for i := 0; i < maxRetainedJobs && i+maxRetainedJobs < len(jobs); i++ {
895+
for i := 0; i < maxRetainedJobs && i+maxRetainedJobs < len(jobs)-1; i++ {
884896
toDelete = append(toDelete, jobs[maxRetainedJobs+i])
885897
}
886898

staging/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1997,6 +1997,15 @@ func TestSortUnpackJobs(t *testing.T) {
19971997
},
19981998
}
19991999
}
2000+
nilConditionJob := &batchv1.Job{
2001+
ObjectMeta: metav1.ObjectMeta{
2002+
Name: "nc",
2003+
Labels: map[string]string{install.OLMManagedLabelKey: install.OLMManagedLabelValue, bundleUnpackRefLabel: "test"},
2004+
},
2005+
Status: batchv1.JobStatus{
2006+
Conditions: nil,
2007+
},
2008+
}
20002009
failedJobs := []*batchv1.Job{
20012010
testJob("f-1", true, 1),
20022011
testJob("f-2", true, 2),
@@ -2028,6 +2037,24 @@ func TestSortUnpackJobs(t *testing.T) {
20282037
}, {
20292038
name: "empty job list",
20302039
maxRetained: 1,
2040+
}, {
2041+
name: "nil job in list",
2042+
maxRetained: 1,
2043+
jobs: []*batchv1.Job{
2044+
failedJobs[2],
2045+
nil,
2046+
failedJobs[1],
2047+
},
2048+
expectedLatest: failedJobs[2],
2049+
}, {
2050+
name: "nil condition",
2051+
maxRetained: 3,
2052+
jobs: []*batchv1.Job{
2053+
failedJobs[2],
2054+
nilConditionJob,
2055+
failedJobs[1],
2056+
},
2057+
expectedLatest: nilConditionJob,
20312058
}, {
20322059
name: "retain oldest",
20332060
maxRetained: 1,

staging/operator-lifecycle-manager/pkg/controller/install/certresources.go

Lines changed: 73 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
apierrors "k8s.io/apimachinery/pkg/api/errors"
1313
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1414
"k8s.io/apimachinery/pkg/util/intstr"
15+
"k8s.io/apimachinery/pkg/util/sets"
1516
corev1ac "k8s.io/client-go/applyconfigurations/core/v1"
1617
rbacv1ac "k8s.io/client-go/applyconfigurations/rbac/v1"
1718

@@ -161,6 +162,14 @@ func ServiceName(deploymentName string) string {
161162
return deploymentName + "-service"
162163
}
163164

165+
func HostnamesForService(serviceName, namespace string) []string {
166+
return []string{
167+
fmt.Sprintf("%s.%s", serviceName, namespace),
168+
fmt.Sprintf("%s.%s.svc", serviceName, namespace),
169+
fmt.Sprintf("%s.%s.svc.cluster.local", serviceName, namespace),
170+
}
171+
}
172+
164173
func (i *StrategyDeploymentInstaller) getCertResources() []certResource {
165174
return append(i.apiServiceDescriptions, i.webhookDescriptions...)
166175
}
@@ -227,15 +236,74 @@ func (i *StrategyDeploymentInstaller) CertsRotated() bool {
227236
return i.certificatesRotated
228237
}
229238

230-
func ShouldRotateCerts(csv *v1alpha1.ClusterServiceVersion) bool {
239+
// shouldRotateCerts indicates whether an apiService cert should be rotated due to being
240+
// malformed, invalid, expired, inactive or within a specific freshness interval (DefaultCertMinFresh) before expiry.
241+
func shouldRotateCerts(certSecret *corev1.Secret, hosts []string) bool {
231242
now := metav1.Now()
232-
if !csv.Status.CertsRotateAt.IsZero() && csv.Status.CertsRotateAt.Before(&now) {
243+
caPEM, ok := certSecret.Data[OLMCAPEMKey]
244+
if !ok {
245+
// missing CA cert in secret
246+
return true
247+
}
248+
certPEM, ok := certSecret.Data["tls.crt"]
249+
if !ok {
250+
// missing cert in secret
251+
return true
252+
}
253+
254+
ca, err := certs.PEMToCert(caPEM)
255+
if err != nil {
256+
// malformed CA cert
257+
return true
258+
}
259+
cert, err := certs.PEMToCert(certPEM)
260+
if err != nil {
261+
// malformed cert
233262
return true
234263
}
235264

265+
// check for cert freshness
266+
if !certs.Active(ca) || now.Time.After(CalculateCertRotatesAt(ca.NotAfter)) ||
267+
!certs.Active(cert) || now.Time.After(CalculateCertRotatesAt(cert.NotAfter)) {
268+
return true
269+
}
270+
271+
// Check validity of serving cert and if serving cert is trusted by the CA
272+
for _, host := range hosts {
273+
if err := certs.VerifyCert(ca, cert, host); err != nil {
274+
return true
275+
}
276+
}
236277
return false
237278
}
238279

280+
func (i *StrategyDeploymentInstaller) ShouldRotateCerts(s Strategy) (bool, error) {
281+
strategy, ok := s.(*v1alpha1.StrategyDetailsDeployment)
282+
if !ok {
283+
return false, fmt.Errorf("failed to install %s strategy with deployment installer: unsupported deployment install strategy", strategy.GetStrategyName())
284+
}
285+
286+
hasCerts := sets.New[string]()
287+
for _, c := range i.getCertResources() {
288+
hasCerts.Insert(c.getDeploymentName())
289+
}
290+
for _, sddSpec := range strategy.DeploymentSpecs {
291+
if hasCerts.Has(sddSpec.Name) {
292+
certSecret, err := i.strategyClient.GetOpLister().CoreV1().SecretLister().Secrets(i.owner.GetNamespace()).Get(SecretName(ServiceName(sddSpec.Name)))
293+
if err == nil {
294+
if shouldRotateCerts(certSecret, HostnamesForService(ServiceName(sddSpec.Name), i.owner.GetNamespace())) {
295+
return true, nil
296+
}
297+
} else if apierrors.IsNotFound(err) {
298+
return true, nil
299+
} else {
300+
return false, err
301+
}
302+
}
303+
}
304+
return false, nil
305+
}
306+
239307
func CalculateCertExpiration(startingFrom time.Time) time.Time {
240308
return startingFrom.Add(DefaultCertValidFor)
241309
}
@@ -271,10 +339,7 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
271339
}
272340

273341
// Create signed serving cert
274-
hosts := []string{
275-
fmt.Sprintf("%s.%s", serviceName, i.owner.GetNamespace()),
276-
fmt.Sprintf("%s.%s.svc", serviceName, i.owner.GetNamespace()),
277-
}
342+
hosts := HostnamesForService(serviceName, i.owner.GetNamespace())
278343
servingPair, err := certGenerator.Generate(expiration, Organization, ca, hosts)
279344
if err != nil {
280345
logger.Warnf("could not generate signed certs for hosts %v", hosts)
@@ -323,10 +388,10 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
323388

324389
// Attempt an update
325390
// TODO: Check that the secret was not modified
326-
if existingCAPEM, ok := existingSecret.Data[OLMCAPEMKey]; ok && !ShouldRotateCerts(i.owner.(*v1alpha1.ClusterServiceVersion)) && existingSecret.Annotations[OpenShiftComponent] != "" {
391+
if !shouldRotateCerts(existingSecret, HostnamesForService(serviceName, i.owner.GetNamespace())) {
327392
logger.Warnf("reusing existing cert %s", secret.GetName())
328393
secret = existingSecret
329-
caPEM = existingCAPEM
394+
caPEM = existingSecret.Data[OLMCAPEMKey]
330395
caHash = certs.PEMSHA256(caPEM)
331396
} else {
332397
if _, err := i.strategyClient.GetOpClient().UpdateSecret(secret); err != nil {

staging/operator-lifecycle-manager/pkg/controller/install/resolver.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ type Strategy interface {
2121
type StrategyInstaller interface {
2222
Install(strategy Strategy) error
2323
CheckInstalled(strategy Strategy) (bool, error)
24+
ShouldRotateCerts(strategy Strategy) (bool, error)
2425
CertsRotateAt() time.Time
2526
CertsRotated() bool
2627
}
@@ -79,3 +80,7 @@ func (i *NullStrategyInstaller) CertsRotateAt() time.Time {
7980
func (i *NullStrategyInstaller) CertsRotated() bool {
8081
return false
8182
}
83+
84+
func (i *NullStrategyInstaller) ShouldRotateCerts(s Strategy) (bool, error) {
85+
return false, nil
86+
}

staging/operator-lifecycle-manager/pkg/controller/operators/olm/apiservices.go

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -93,17 +93,12 @@ func (a *Operator) checkAPIServiceResources(csv *v1alpha1.ClusterServiceVersion,
9393

9494
// Check if CA is Active
9595
caBundle := apiService.Spec.CABundle
96-
ca, err := certs.PEMToCert(caBundle)
96+
_, err = certs.PEMToCert(caBundle)
9797
if err != nil {
9898
logger.Warnf("could not convert APIService CA bundle to x509 cert")
9999
errs = append(errs, err)
100100
continue
101101
}
102-
if !certs.Active(ca) {
103-
logger.Warnf("CA cert not active")
104-
errs = append(errs, fmt.Errorf("found the CA cert is not active"))
105-
continue
106-
}
107102

108103
// Check if serving cert is active
109104
secretName := install.SecretName(serviceName)
@@ -113,17 +108,12 @@ func (a *Operator) checkAPIServiceResources(csv *v1alpha1.ClusterServiceVersion,
113108
errs = append(errs, err)
114109
continue
115110
}
116-
cert, err := certs.PEMToCert(secret.Data["tls.crt"])
111+
_, err = certs.PEMToCert(secret.Data["tls.crt"])
117112
if err != nil {
118113
logger.Warnf("could not convert serving cert to x509 cert")
119114
errs = append(errs, err)
120115
continue
121116
}
122-
if !certs.Active(cert) {
123-
logger.Warnf("serving cert not active")
124-
errs = append(errs, fmt.Errorf("found the serving cert not active"))
125-
continue
126-
}
127117

128118
// Check if CA hash matches expected
129119
caHash := hashFunc(caBundle)
@@ -133,18 +123,6 @@ func (a *Operator) checkAPIServiceResources(csv *v1alpha1.ClusterServiceVersion,
133123
continue
134124
}
135125

136-
// Check if serving cert is trusted by the CA
137-
hosts := []string{
138-
fmt.Sprintf("%s.%s", service.GetName(), csv.GetNamespace()),
139-
fmt.Sprintf("%s.%s.svc", service.GetName(), csv.GetNamespace()),
140-
}
141-
for _, host := range hosts {
142-
if err := certs.VerifyCert(ca, cert, host); err != nil {
143-
errs = append(errs, fmt.Errorf("could not verify cert: %s", err.Error()))
144-
continue
145-
}
146-
}
147-
148126
// Ensure the existing Deployment has a matching CA hash annotation
149127
deployment, err := a.lister.AppsV1().DeploymentLister().Deployments(csv.GetNamespace()).Get(desc.DeploymentName)
150128
if apierrors.IsNotFound(err) || err != nil {

staging/operator-lifecycle-manager/pkg/controller/operators/olm/operator.go

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2242,7 +2242,10 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v
22422242
}
22432243

22442244
// Check if it's time to refresh owned APIService certs
2245-
if install.ShouldRotateCerts(out) {
2245+
if shouldRotate, err := installer.ShouldRotateCerts(strategy); err != nil {
2246+
logger.WithError(err).Info("cert validity check")
2247+
return
2248+
} else if shouldRotate {
22462249
logger.Debug("CSV owns resources that require a cert refresh")
22472250
out.SetPhaseWithEvent(v1alpha1.CSVPhasePending, v1alpha1.CSVReasonNeedsCertRotation, "CSV owns resources that require a cert refresh", now, a.recorder)
22482251
return
@@ -2352,7 +2355,10 @@ func (a *Operator) transitionCSVState(in v1alpha1.ClusterServiceVersion) (out *v
23522355
}
23532356

23542357
// Check if it's time to refresh owned APIService certs
2355-
if install.ShouldRotateCerts(out) {
2358+
if shouldRotate, err := installer.ShouldRotateCerts(strategy); err != nil {
2359+
logger.WithError(err).Info("cert validity check")
2360+
return
2361+
} else if shouldRotate {
23562362
logger.Debug("CSV owns resources that require a cert refresh")
23572363
out.SetPhaseWithEvent(v1alpha1.CSVPhasePending, v1alpha1.CSVReasonNeedsCertRotation, "owned APIServices need cert refresh", now, a.recorder)
23582364
return

0 commit comments

Comments
 (0)