Skip to content

OCPBUGS-5294: backport cert rotation fix #428

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

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions .golangci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
run:
timeout: 5m
skip-dirs:
- pkg/lib
- pkg/api
- pkg/fakes
- pkg/package-server/apis
- test/e2e

linters:
enable:
- depguard
- gofmt
- goimports
- importas
- misspell
- stylecheck
- tparallel
- unconvert
- whitespace
disable:
- errcheck

linters-settings:
importas:
alias:
- pkg: k8s.io/api/core/v1
alias: corev1
- pkg: k8s.io/api/apps/v1
alias: appsv1
- pkg: k8s.io/apimachinery/pkg/apis/meta/v1
alias: metav1
- pkg: k8s.io/apimachinery/pkg/api/errors
alias: apierrors
- pkg: github.com/operator-framework/api/pkg/operators/v1alpha1
alias: operatorsv1alpha1
- pkg: github.com/operator-framework/api/pkg/operators/v1
alias: operatorsv1
- pkg: github.com/operator-framework/api/pkg/operators/v2
alias: operatorsv2

issues:
max-issues-per-linter: 0
max-same-issues: 0

output:
format: tab
sort-results: true
6 changes: 3 additions & 3 deletions staging/operator-lifecycle-manager/cmd/olm/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
configv1client "github.com/openshift/client-go/config/clientset/versioned/typed/config/v1"
"github.com/sirupsen/logrus"
"github.com/spf13/pflag"
v1 "k8s.io/api/core/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/klog"
ctrl "sigs.k8s.io/controller-runtime"

Expand Down Expand Up @@ -103,8 +103,8 @@ func main() {
// the empty string, the resulting array will be `[]string{""}`.
namespaces := strings.Split(*watchedNamespaces, ",")
for _, ns := range namespaces {
if ns == v1.NamespaceAll {
namespaces = []string{v1.NamespaceAll}
if ns == corev1.NamespaceAll {
namespaces = []string{corev1.NamespaceAll}
break
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"strings"

log "github.com/sirupsen/logrus"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1"

Expand All @@ -26,7 +26,7 @@ func (i *StrategyDeploymentInstaller) createOrUpdateAPIService(caPEM []byte, des
exists := true
apiService, err := i.strategyClient.GetOpLister().APIRegistrationV1().APIServiceLister().Get(apiServiceName)
if err != nil {
if !k8serrors.IsNotFound(err) {
if !apierrors.IsNotFound(err) {
return err
}

Expand Down Expand Up @@ -120,14 +120,14 @@ func IsAPIServiceAdoptable(opLister operatorlister.OperatorLister, target *v1alp

// Get the CSV that target replaces
replacing, replaceGetErr := opLister.OperatorsV1alpha1().ClusterServiceVersionLister().ClusterServiceVersions(target.GetNamespace()).Get(target.Spec.Replaces)
if replaceGetErr != nil && !k8serrors.IsNotFound(replaceGetErr) && !k8serrors.IsGone(replaceGetErr) {
if replaceGetErr != nil && !apierrors.IsNotFound(replaceGetErr) && !apierrors.IsGone(replaceGetErr) {
err = replaceGetErr
return
}

// Get the current owner CSV of the APIService
currentOwnerCSV, ownerGetErr := opLister.OperatorsV1alpha1().ClusterServiceVersionLister().ClusterServiceVersions(ownerNamespace).Get(ownerName)
if ownerGetErr != nil && !k8serrors.IsNotFound(ownerGetErr) && !k8serrors.IsGone(ownerGetErr) {
if ownerGetErr != nil && !apierrors.IsNotFound(ownerGetErr) && !apierrors.IsGone(ownerGetErr) {
err = ownerGetErr
return
}
Expand Down Expand Up @@ -179,13 +179,13 @@ func (i *StrategyDeploymentInstaller) deleteLegacyAPIServiceResources(desc apiSe
// Attempt to delete the legacy Service.
existingService, err := i.strategyClient.GetOpClient().GetService(namespace, legacyServiceName)
if err != nil {
if !k8serrors.IsNotFound(err) {
if !apierrors.IsNotFound(err) {
return err
}
} else if ownerutil.AdoptableLabels(existingService.GetLabels(), true, i.owner) {
logger.Infof("Deleting Service with legacy APIService name %s", existingService.Name)
err = i.strategyClient.GetOpClient().DeleteService(namespace, legacyServiceName, &metav1.DeleteOptions{})
if err != nil && !k8serrors.IsNotFound(err) {
if err != nil && !apierrors.IsNotFound(err) {
return err
}
} else {
Expand All @@ -198,13 +198,13 @@ func (i *StrategyDeploymentInstaller) deleteLegacyAPIServiceResources(desc apiSe
// Attempt to delete the legacy Secret.
existingSecret, err := i.strategyClient.GetOpClient().GetSecret(namespace, SecretName(apiServiceName))
if err != nil {
if !k8serrors.IsNotFound(err) {
if !apierrors.IsNotFound(err) {
return err
}
} else if ownerutil.AdoptableLabels(existingSecret.GetLabels(), true, i.owner) {
logger.Infof("Deleting Secret with legacy APIService name %s", existingSecret.Name)
err = i.strategyClient.GetOpClient().DeleteSecret(namespace, SecretName(apiServiceName), &metav1.DeleteOptions{})
if err != nil && !k8serrors.IsNotFound(err) {
if err != nil && !apierrors.IsNotFound(err) {
return err
}
} else {
Expand All @@ -214,13 +214,13 @@ func (i *StrategyDeploymentInstaller) deleteLegacyAPIServiceResources(desc apiSe
// Attempt to delete the legacy Role.
existingRole, err := i.strategyClient.GetOpClient().GetRole(namespace, SecretName(apiServiceName))
if err != nil {
if !k8serrors.IsNotFound(err) {
if !apierrors.IsNotFound(err) {
return err
}
} else if ownerutil.AdoptableLabels(existingRole.GetLabels(), true, i.owner) {
logger.Infof("Deleting Role with legacy APIService name %s", existingRole.Name)
err = i.strategyClient.GetOpClient().DeleteRole(namespace, SecretName(apiServiceName), &metav1.DeleteOptions{})
if err != nil && !k8serrors.IsNotFound(err) {
if err != nil && !apierrors.IsNotFound(err) {
return err
}
} else {
Expand All @@ -230,13 +230,13 @@ func (i *StrategyDeploymentInstaller) deleteLegacyAPIServiceResources(desc apiSe
// Attempt to delete the legacy secret RoleBinding.
existingRoleBinding, err := i.strategyClient.GetOpClient().GetRoleBinding(namespace, SecretName(apiServiceName))
if err != nil {
if !k8serrors.IsNotFound(err) {
if !apierrors.IsNotFound(err) {
return err
}
} else if ownerutil.AdoptableLabels(existingRoleBinding.GetLabels(), true, i.owner) {
logger.Infof("Deleting RoleBinding with legacy APIService name %s", existingRoleBinding.Name)
err = i.strategyClient.GetOpClient().DeleteRoleBinding(namespace, SecretName(apiServiceName), &metav1.DeleteOptions{})
if err != nil && !k8serrors.IsNotFound(err) {
if err != nil && !apierrors.IsNotFound(err) {
return err
}
} else {
Expand All @@ -246,13 +246,13 @@ func (i *StrategyDeploymentInstaller) deleteLegacyAPIServiceResources(desc apiSe
// Attempt to delete the legacy ClusterRoleBinding.
existingClusterRoleBinding, err := i.strategyClient.GetOpClient().GetClusterRoleBinding(apiServiceName + "-system:auth-delegator")
if err != nil {
if !k8serrors.IsNotFound(err) {
if !apierrors.IsNotFound(err) {
return err
}
} else if ownerutil.AdoptableLabels(existingClusterRoleBinding.GetLabels(), true, i.owner) {
logger.Infof("Deleting ClusterRoleBinding with legacy APIService name %s", existingClusterRoleBinding.Name)
err = i.strategyClient.GetOpClient().DeleteClusterRoleBinding(apiServiceName+"-system:auth-delegator", &metav1.DeleteOptions{})
if err != nil && !k8serrors.IsNotFound(err) {
if err != nil && !apierrors.IsNotFound(err) {
return err
}
} else {
Expand All @@ -262,13 +262,13 @@ func (i *StrategyDeploymentInstaller) deleteLegacyAPIServiceResources(desc apiSe
// Attempt to delete the legacy AuthReadingRoleBinding.
existingRoleBinding, err = i.strategyClient.GetOpClient().GetRoleBinding(KubeSystem, apiServiceName+"-auth-reader")
if err != nil {
if !k8serrors.IsNotFound(err) {
if !apierrors.IsNotFound(err) {
return err
}
} else if ownerutil.AdoptableLabels(existingRoleBinding.GetLabels(), true, i.owner) {
logger.Infof("Deleting RoleBinding with legacy APIService name %s", existingRoleBinding.Name)
err = i.strategyClient.GetOpClient().DeleteRoleBinding(KubeSystem, apiServiceName+"-auth-reader", &metav1.DeleteOptions{})
if err != nil && !k8serrors.IsNotFound(err) {
if err != nil && !apierrors.IsNotFound(err) {
return err
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/intstr"

Expand Down Expand Up @@ -160,7 +160,7 @@ func (i *StrategyDeploymentInstaller) getCertResources() []certResource {
}

func (i *StrategyDeploymentInstaller) certResourcesForDeployment(deploymentName string) []certResource {
result := []certResource{}
var result []certResource
for _, desc := range i.getCertResources() {
if desc.getDeploymentName() == deploymentName {
result = append(result, desc)
Expand All @@ -185,13 +185,12 @@ func (i *StrategyDeploymentInstaller) installCertRequirements(strategy Strategy)
}

// Create the CA
expiration := time.Now().Add(DefaultCertValidFor)
ca, err := certs.GenerateCA(expiration, Organization)
i.certificateExpirationTime = CalculateCertExpiration(time.Now())
ca, err := certs.GenerateCA(i.certificateExpirationTime, Organization)
if err != nil {
logger.Debug("failed to generate CA")
return nil, err
}
rotateAt := expiration.Add(-1 * DefaultCertMinFresh)

for n, sddSpec := range strategyDetailsDeployment.DeploymentSpecs {
certResources := i.certResourcesForDeployment(sddSpec.Name)
Expand All @@ -202,7 +201,7 @@ func (i *StrategyDeploymentInstaller) installCertRequirements(strategy Strategy)
}

// Update the deployment for each certResource
newDepSpec, caPEM, err := i.installCertRequirementsForDeployment(sddSpec.Name, ca, rotateAt, sddSpec.Spec, getServicePorts(certResources))
newDepSpec, caPEM, err := i.installCertRequirementsForDeployment(sddSpec.Name, ca, i.certificateExpirationTime, sddSpec.Spec, getServicePorts(certResources))
if err != nil {
return nil, err
}
Expand All @@ -214,6 +213,14 @@ func (i *StrategyDeploymentInstaller) installCertRequirements(strategy Strategy)
return strategyDetailsDeployment, nil
}

func (i *StrategyDeploymentInstaller) CertsRotateAt() time.Time {
return CalculateCertRotatesAt(i.certificateExpirationTime)
}

func (i *StrategyDeploymentInstaller) CertsRotated() bool {
return i.certificatesRotated
}

func ShouldRotateCerts(csv *v1alpha1.ClusterServiceVersion) bool {
now := metav1.Now()
if !csv.Status.CertsRotateAt.IsZero() && csv.Status.CertsRotateAt.Before(&now) {
Expand All @@ -223,7 +230,15 @@ func ShouldRotateCerts(csv *v1alpha1.ClusterServiceVersion) bool {
return false
}

func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deploymentName string, ca *certs.KeyPair, rotateAt time.Time, depSpec appsv1.DeploymentSpec, ports []corev1.ServicePort) (*appsv1.DeploymentSpec, []byte, error) {
func CalculateCertExpiration(startingFrom time.Time) time.Time {
return startingFrom.Add(DefaultCertValidFor)
}

func CalculateCertRotatesAt(certExpirationTime time.Time) time.Time {
return certExpirationTime.Add(-1 * DefaultCertMinFresh)
}

func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deploymentName string, ca *certs.KeyPair, expiration time.Time, depSpec appsv1.DeploymentSpec, ports []corev1.ServicePort) (*appsv1.DeploymentSpec, []byte, error) {
logger := log.WithFields(log.Fields{})

// Create a service for the deployment
Expand All @@ -246,7 +261,7 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo

// Delete the Service to replace
deleteErr := i.strategyClient.GetOpClient().DeleteService(service.GetNamespace(), service.GetName(), &metav1.DeleteOptions{})
if deleteErr != nil && !k8serrors.IsNotFound(deleteErr) {
if deleteErr != nil && !apierrors.IsNotFound(deleteErr) {
return nil, nil, fmt.Errorf("could not delete existing service %s", service.GetName())
}
}
Expand All @@ -263,7 +278,7 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
fmt.Sprintf("%s.%s", service.GetName(), i.owner.GetNamespace()),
fmt.Sprintf("%s.%s.svc", service.GetName(), i.owner.GetNamespace()),
}
servingPair, err := certGenerator.Generate(rotateAt, Organization, ca, hosts)
servingPair, err := certGenerator.Generate(expiration, Organization, ca, hosts)
if err != nil {
logger.Warnf("could not generate signed certs for hosts %v", hosts)
return nil, nil, err
Expand Down Expand Up @@ -311,16 +326,18 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
secret = existingSecret
caPEM = existingCAPEM
caHash = certs.PEMSHA256(caPEM)
} else if _, err := i.strategyClient.GetOpClient().UpdateSecret(secret); err != nil {
logger.Warnf("could not update secret %s", secret.GetName())
return nil, nil, err
} else {
if _, err := i.strategyClient.GetOpClient().UpdateSecret(secret); err != nil {
logger.Warnf("could not update secret %s", secret.GetName())
return nil, nil, err
}
i.certificatesRotated = true
}

} else if k8serrors.IsNotFound(err) {
} else if apierrors.IsNotFound(err) {
// Create the secret
ownerutil.AddNonBlockingOwner(secret, i.owner)
if _, err := i.strategyClient.GetOpClient().CreateSecret(secret); err != nil {
if !k8serrors.IsAlreadyExists(err) {
if !apierrors.IsAlreadyExists(err) {
log.Warnf("could not create secret %s: %v", secret.GetName(), err)
return nil, nil, err
}
Expand All @@ -331,6 +348,7 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
return nil, nil, err
}
}
i.certificatesRotated = true
} else {
return nil, nil, err
}
Expand Down Expand Up @@ -361,7 +379,7 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
logger.Warnf("could not update secret role %s", secretRole.GetName())
return nil, nil, err
}
} else if k8serrors.IsNotFound(err) {
} else if apierrors.IsNotFound(err) {
// Create the role
ownerutil.AddNonBlockingOwner(secretRole, i.owner)
_, err = i.strategyClient.GetOpClient().CreateRole(secretRole)
Expand Down Expand Up @@ -407,7 +425,7 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
logger.Warnf("could not update secret rolebinding %s", secretRoleBinding.GetName())
return nil, nil, err
}
} else if k8serrors.IsNotFound(err) {
} else if apierrors.IsNotFound(err) {
// Create the role
ownerutil.AddNonBlockingOwner(secretRoleBinding, i.owner)
_, err = i.strategyClient.GetOpClient().CreateRoleBinding(secretRoleBinding)
Expand Down Expand Up @@ -452,7 +470,7 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
logger.Warnf("could not update auth delegator clusterrolebinding %s", authDelegatorClusterRoleBinding.GetName())
return nil, nil, err
}
} else if k8serrors.IsNotFound(err) {
} else if apierrors.IsNotFound(err) {
// Create the role.
if err := ownerutil.AddOwnerLabels(authDelegatorClusterRoleBinding, i.owner); err != nil {
return nil, nil, err
Expand Down Expand Up @@ -499,7 +517,7 @@ func (i *StrategyDeploymentInstaller) installCertRequirementsForDeployment(deplo
logger.Warnf("could not update auth reader role binding %s", authReaderRoleBinding.GetName())
return nil, nil, err
}
} else if k8serrors.IsNotFound(err) {
} else if apierrors.IsNotFound(err) {
// Create the role.
if err := ownerutil.AddOwnerLabels(authReaderRoleBinding, i.owner); err != nil {
return nil, nil, err
Expand Down
Loading