Skip to content
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

feat: Introduce Dedicated Istio Gateway Secret #2004

Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
47f48f4
feat: Introduce Dedicated Istio Gateway Secret
LeelaChacha Nov 3, 2024
2b89a3a
Merge branch 'main' into feature/#1890-tls-cert-rotation-migration
LeelaChacha Nov 3, 2024
a8217b5
refactor: Lint
LeelaChacha Nov 4, 2024
c76cffa
refactor: Lint
LeelaChacha Nov 4, 2024
d4935ad
test: Simulate Gateway Secret in Watcher Suite
LeelaChacha Nov 4, 2024
b71c975
refactor: gofumpt and gci
LeelaChacha Nov 4, 2024
897dd0f
fix: ca rotation e2e test
LeelaChacha Nov 4, 2024
5cb068d
test: ca rotation e2e fix
LeelaChacha Nov 6, 2024
0596448
Merge branch 'main' into feature/#1890-tls-cert-rotation-migration
LeelaChacha Nov 6, 2024
d48fd6f
test: ca rotation e2e fix
LeelaChacha Nov 7, 2024
6e35338
fix: give controller-manager permission to update istio-gateway-secret
LeelaChacha Nov 7, 2024
e4edfb6
Merge branch 'main' into feature/#1890-tls-cert-rotation-migration
LeelaChacha Nov 7, 2024
aeacc42
fix: give controller-manager permission to update istio-gateway-secret
LeelaChacha Nov 7, 2024
758c4d3
fix: KLM image name in kustomization
LeelaChacha Nov 7, 2024
8cb3b38
Merge branch 'main' into feature/#1890-tls-cert-rotation-migration
LeelaChacha Nov 11, 2024
ed7ea63
refactor: Rename zerodw package
LeelaChacha Nov 11, 2024
7016aac
refactor: PR Review
LeelaChacha Nov 14, 2024
bf0d76b
Merge branch 'main' into feature/#1890-tls-cert-rotation-migration
LeelaChacha Nov 14, 2024
b63ffe4
refactor: PR Review
LeelaChacha Nov 14, 2024
b467d13
refactor: gci
LeelaChacha Nov 14, 2024
333fd09
refactor: hide gateway secret name
LeelaChacha Nov 14, 2024
f7fc41c
test: add e2e test for istio gateway secret rotation
LeelaChacha Nov 15, 2024
ce69e8c
refactor: gci and gofumpt
LeelaChacha Nov 15, 2024
16848db
Merge branch 'main' into feature/#1890-tls-cert-rotation-migration
LeelaChacha Nov 15, 2024
5e71352
fix: flags_test.go
LeelaChacha Nov 15, 2024
11779fe
chore: remove debug print statement
LeelaChacha Nov 15, 2024
34363c6
fix: remove background context
LeelaChacha Nov 15, 2024
55fe04b
fix: test logics
LeelaChacha Nov 18, 2024
0ceb574
Merge branch 'main' into feature/#1890-tls-cert-rotation-migration
LeelaChacha Nov 18, 2024
45691cb
refactor: go routine style in main
LeelaChacha Nov 18, 2024
b260cbf
fix: KLM health check
LeelaChacha Nov 18, 2024
7f1110c
fix: Istion Rotation E2E Check
LeelaChacha Nov 18, 2024
0453158
fix: Istion Rotation E2E Check
LeelaChacha Nov 19, 2024
645dbdb
test: Add Unit Tests for handler.go
LeelaChacha Nov 20, 2024
25fb3a2
fix: Event name in unit test
LeelaChacha Nov 20, 2024
2fa53c8
refactor: require.Equal parameter order
LeelaChacha Nov 20, 2024
c8d2b0e
Merge branch 'main' into feature/#1890-tls-cert-rotation-migration
LeelaChacha Nov 20, 2024
9f6646d
refactor: shift namespace const to testutils package
LeelaChacha Nov 20, 2024
414f368
refactor: using require.Equal
LeelaChacha Nov 20, 2024
841b97d
refactor: PR comments
LeelaChacha Nov 21, 2024
cc784ea
Merge branch 'main' into feature/#1890-tls-cert-rotation-migration
LeelaChacha Nov 21, 2024
b03cd8f
refactor: handler unit test, remove secret manager interface
LeelaChacha Nov 25, 2024
43b4bcd
Merge branch 'main' into feature/#1890-tls-cert-rotation-migration
LeelaChacha Nov 25, 2024
4f899dc
refactor: lint gci and gofumpt
LeelaChacha Nov 25, 2024
8370566
refactor: unparam lint error
LeelaChacha Nov 25, 2024
6eccbd8
refactor: unparam lint error
LeelaChacha Nov 25, 2024
8490271
refactor: unparam lint error
LeelaChacha Nov 25, 2024
5aaaab9
Merge branch 'main' into feature/#1890-tls-cert-rotation-migration
LeelaChacha Nov 26, 2024
ca5e190
chore: add pkg/gatewaysecret unittest coverage
LeelaChacha Nov 27, 2024
203d529
chore: add pkg/gatewaysecret unittest coverage
LeelaChacha Nov 27, 2024
f098fc6
refactor: make ManageGatewaySecret private
LeelaChacha Nov 27, 2024
2207900
refactor: remove local testing artefacts
LeelaChacha Nov 27, 2024
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
14 changes: 12 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ import (
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
machineryruntime "k8s.io/apimachinery/pkg/runtime"
machineryutilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/client-go/kubernetes"
k8sclientscheme "k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
"k8s.io/client-go/util/workqueue"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/cache"
Expand Down Expand Up @@ -65,6 +67,7 @@ import (
"github.com/kyma-project/lifecycle-manager/pkg/matcher"
"github.com/kyma-project/lifecycle-manager/pkg/queue"
"github.com/kyma-project/lifecycle-manager/pkg/watcher"
"github.com/kyma-project/lifecycle-manager/pkg/zerodw"

_ "k8s.io/client-go/plugin/pkg/client/auth"
_ "ocm.software/ocm/api/ocm"
Expand Down Expand Up @@ -201,12 +204,21 @@ func setupManager(flagVar *flags.FlagVar, cacheOptions cache.Options, scheme *ma
go cleanupStoredVersions(flagVar.DropCrdStoredVersionMap, mgr, setupLog)
go scheduleMetricsCleanup(kymaMetrics, flagVar.MetricsCleanupIntervalInMinutes, mgr, setupLog)

setupIstioGatewaySecretRotation(config, kcpClient, setupLog)
LeelaChacha marked this conversation as resolved.
Show resolved Hide resolved

if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
setupLog.Error(err, "problem running manager")
os.Exit(runtimeProblemExitCode)
}
}

func setupIstioGatewaySecretRotation(config *rest.Config, kcpClient *remote.ConfigAndClient, setupLog logr.Logger) {
kcpClientset := kubernetes.NewForConfigOrDie(config)
gatewaySecretHandler := zerodw.NewGatewaySecretHandler(kcpClient)

go zerodw.WatchChangesOnRootCertificate(kcpClientset, gatewaySecretHandler, setupLog)
}

func addHealthChecks(mgr manager.Manager, setupLog logr.Logger) {
// +kubebuilder:scaffold:builder
if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil {
Expand Down Expand Up @@ -323,7 +335,6 @@ func setupKymaReconciler(mgr ctrl.Manager,
func createSkrWebhookManager(mgr ctrl.Manager, skrContextFactory remote.SkrContextProvider,
flagVar *flags.FlagVar,
) (*watcher.SKRWebhookManifestManager, error) {
caCertificateCache := watcher.NewCACertificateCache(flagVar.CaCertCacheTTL)
config := watcher.SkrWebhookManagerConfig{
SKRWatcherPath: flagVar.WatcherResourcesPath,
SkrWatcherImage: flagVar.GetWatcherImage(),
Expand Down Expand Up @@ -353,7 +364,6 @@ func createSkrWebhookManager(mgr ctrl.Manager, skrContextFactory remote.SkrConte
return watcher.NewSKRWebhookManifestManager(
mgr.GetClient(),
skrContextFactory,
caCertificateCache,
config,
certConfig,
resolvedKcpAddr)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ rules:
- watch
- create
- delete
- update
- apiGroups:
- cert-manager.io
resources:
Expand Down
2 changes: 1 addition & 1 deletion config/watcher/gateway.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ spec:
number: 443
protocol: HTTPS
tls:
credentialName: klm-watcher
credentialName: istio-gateway-secret
Tomasz-Smelcerz-SAP marked this conversation as resolved.
Show resolved Hide resolved
mode: MUTUAL
4 changes: 0 additions & 4 deletions internal/pkg/flags/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ const (
DefaultIstioGatewayNamespace = "kcp-system"
DefaultIstioNamespace = "istio-system"
DefaultCaCertName = "klm-watcher-serving"
DefaultCaCertCacheTTL time.Duration = 1 * time.Hour
DefaultSelfSignedCertDuration time.Duration = 90 * 24 * time.Hour
DefaultSelfSignedCertRenewBefore time.Duration = 60 * 24 * time.Hour
DefaultSelfSignedCertificateRenewBuffer = 24 * time.Hour
Expand Down Expand Up @@ -203,8 +202,6 @@ func DefineFlagVar() *FlagVar {
"Name of the namespace for syncing remote Kyma and module catalog")
flag.StringVar(&flagVar.CaCertName, "ca-cert-name", DefaultCaCertName,
"Name of the CA Certificate in Istio Namespace which is used to sign SKR Certificates")
flag.DurationVar(&flagVar.CaCertCacheTTL, "ca-cert-cache-ttl", DefaultCaCertCacheTTL,
"The ttl for the CA Certificate Cache")
flag.DurationVar(&flagVar.SelfSignedCertDuration, "self-signed-cert-duration", DefaultSelfSignedCertDuration,
"The lifetime duration of self-signed certificate, minimum accepted duration is 1 hour.")
flag.DurationVar(&flagVar.SelfSignedCertRenewBefore, "self-signed-cert-renew-before",
Expand Down Expand Up @@ -287,7 +284,6 @@ type FlagVar struct {
SkipPurgingFor string
RemoteSyncNamespace string
CaCertName string
CaCertCacheTTL time.Duration
IsKymaManaged bool
SelfSignedCertDuration time.Duration
SelfSignedCertRenewBefore time.Duration
Expand Down
5 changes: 0 additions & 5 deletions internal/pkg/flags/flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,6 @@ func Test_ConstantFlags(t *testing.T) {
constValue: DefaultCaCertName,
expectedValue: "klm-watcher-serving",
},
{
constName: "DefaultCaCertCacheTTL",
constValue: DefaultCaCertCacheTTL.String(),
expectedValue: (1 * time.Hour).String(),
},
{
constName: "DefaultSelfSignedCertDuration",
constValue: DefaultSelfSignedCertDuration.String(),
Expand Down
29 changes: 27 additions & 2 deletions pkg/testutils/watcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"errors"
"fmt"
"time"

certmanagerv1 "github.com/cert-manager/cert-manager/pkg/apis/certmanager/v1"
apicorev1 "k8s.io/api/core/v1"
Expand All @@ -14,8 +15,9 @@ import (
)

var (
errOldCreationTime = errors.New("certificate has an old creation timestamp")
errNotSyncedSecret = errors.New("secret is not synced to skr cluster")
errOldCreationTime = errors.New("certificate has an old creation timestamp")
errNotSyncedSecret = errors.New("secret is not synced to skr cluster")
errTLSSecretNotRotated = errors.New("tls secret did not rotated")
)

func CertificateSecretExists(ctx context.Context, secretName types.NamespacedName, k8sClient client.Client) error {
Expand Down Expand Up @@ -43,6 +45,19 @@ func CertificateSecretIsCreatedAfter(ctx context.Context,
return nil
}

func TLSSecretRotated(ctx context.Context, oldValue time.Time,
namespacedSecretName types.NamespacedName, kcpClient client.Client,
) error {
secret, err := GetTLSSecret(ctx, namespacedSecretName, kcpClient)
if err != nil {
return fmt.Errorf("failed to fetch tls secret: %w", err)
}
if secret.CreationTimestamp.Time == oldValue {
return errTLSSecretNotRotated
}
return nil
}

func CertificateSecretIsSyncedToSkrCluster(ctx context.Context,
kcpSecretName types.NamespacedName, kcpClient client.Client,
skrSecretName types.NamespacedName, skrClient client.Client,
Expand Down Expand Up @@ -104,3 +119,13 @@ func GetCACertificate(ctx context.Context, namespacedCertName types.NamespacedNa

return caCert, nil
}

func GetTLSSecret(ctx context.Context, namespacedSecretName types.NamespacedName, k8sClient client.Client,
) (*apicorev1.Secret, error) {
tlsSecret := &apicorev1.Secret{}
if err := k8sClient.Get(ctx, namespacedSecretName, tlsSecret); err != nil {
return nil, fmt.Errorf("failed to get secret %w", err)
}

return tlsSecret, nil
}
33 changes: 0 additions & 33 deletions pkg/watcher/ca_certificate_cache.go

This file was deleted.

62 changes: 22 additions & 40 deletions pkg/watcher/certificate_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/kyma-project/lifecycle-manager/api/v1beta2"
"github.com/kyma-project/lifecycle-manager/pkg/log"
"github.com/kyma-project/lifecycle-manager/pkg/util"
"github.com/kyma-project/lifecycle-manager/pkg/zerodw"
)

const (
Expand All @@ -43,7 +44,6 @@ type SubjectAltName struct {

type CertificateManager struct {
kcpClient client.Client
caCertCache *CACertificateCache
certificateName string
secretName string
labelSet k8slabels.Set
Expand Down Expand Up @@ -76,14 +76,12 @@ type CertificateSecret struct {
// NewCertificateManager returns a new CertificateManager, which can be used for creating a cert-manager Certificates.
func NewCertificateManager(kcpClient client.Client, kymaName string,
config CertificateConfig,
caCertCache *CACertificateCache,
) *CertificateManager {
return &CertificateManager{
kcpClient: kcpClient,
certificateName: ResolveTLSCertName(kymaName),
secretName: ResolveTLSCertName(kymaName),
config: config,
caCertCache: caCertCache,
labelSet: k8slabels.Set{
shared.PurposeLabel: shared.CertManager,
shared.ManagedBy: shared.OperatorName,
Expand Down Expand Up @@ -261,53 +259,29 @@ func (c *CertificateManager) getIssuer(ctx context.Context) (*certmanagerv1.Issu
return &issuerList.Items[0], nil
}

func (c *CertificateManager) getCertificateSecret(ctx context.Context) (*apicorev1.Secret, error) {
secret := &apicorev1.Secret{}
err := c.kcpClient.Get(ctx, client.ObjectKey{Name: c.secretName, Namespace: c.config.IstioNamespace},
secret)
if err != nil {
return nil, fmt.Errorf("failed to get secret for certificate %s-%s: %w", c.secretName, c.config.IstioNamespace,
err)
}

return secret, nil
}

type CertificateNotReadyError struct{}

func (e *CertificateNotReadyError) Error() string {
return "Certificate-Secret does not exist"
}

func (c *CertificateManager) GetCACertificateStatus(ctx context.Context) (certmanagerv1.CertificateStatus, error) {
cachedCertStatus := c.caCertCache.GetCACertStatusFromCache(c.config.CACertificateName)

if cachedCertStatus.RenewalTime == nil || certificateRenewalTimePassed(cachedCertStatus) {
caCert := certmanagerv1.Certificate{}
if err := c.kcpClient.Get(ctx,
client.ObjectKey{Namespace: c.config.IstioNamespace, Name: c.config.CACertificateName},
&caCert); err != nil {
return certmanagerv1.CertificateStatus{}, fmt.Errorf("failed to get CA certificate %w", err)
}
c.caCertCache.SetCACertToCache(caCert)
return caCert.Status, nil
}

return cachedCertStatus, nil
}

func (c *CertificateManager) RemoveSecretAfterCARotated(ctx context.Context, kymaObjKey client.ObjectKey) error {
caCertificateStatus, err := c.GetCACertificateStatus(ctx)
gatewaySecret, err := getCertificateSecret(ctx, c.kcpClient, client.ObjectKey{
Namespace: c.config.IstioNamespace,
Name: zerodw.GatewaySecretName,
})
if err != nil {
return fmt.Errorf("error while fetching CA Certificate: %w", err)
return err
}

certSecret, err := c.getCertificateSecret(ctx)
watcherCert, err := getCertificateSecret(ctx, c.kcpClient, client.ObjectKey{
Namespace: c.config.IstioNamespace,
Name: c.secretName,
})
if err != nil {
return fmt.Errorf("error while fetching certificate: %w", err)
return err
}

if certSecret != nil && (certSecret.CreationTimestamp.Before(caCertificateStatus.NotBefore)) {
if watcherCert != nil && isGatewaySecretNewerThanWatcherCert(gatewaySecret, watcherCert) {
logf.FromContext(ctx).V(log.DebugLevel).Info("CA Certificate was rotated, removing certificate",
"kyma", kymaObjKey)
if err = c.removeSecret(ctx); err != nil {
Expand All @@ -318,6 +292,14 @@ func (c *CertificateManager) RemoveSecretAfterCARotated(ctx context.Context, kym
return nil
}

func certificateRenewalTimePassed(certStatus certmanagerv1.CertificateStatus) bool {
return certStatus.RenewalTime.Before(&(apimetav1.Time{Time: time.Now()}))
func isGatewaySecretNewerThanWatcherCert(gatewaySecret *apicorev1.Secret, watcherSecret *apicorev1.Secret) bool {
LeelaChacha marked this conversation as resolved.
Show resolved Hide resolved
if gwSecretLastModifiedAtValue, ok := gatewaySecret.Annotations[zerodw.LastModifiedAtAnnotation]; ok {
if gwSecretLastModifiedAt, err := time.Parse(time.RFC3339, gwSecretLastModifiedAtValue); err == nil {
if watcherSecret.CreationTimestamp.Time.After(gwSecretLastModifiedAt) {
return false
}
}
}

return true
}
Loading
Loading