From 00b5e555656346ce3a0983971d8151b057b9a974 Mon Sep 17 00:00:00 2001 From: Livio Spring Date: Thu, 20 Jun 2024 16:09:20 +0200 Subject: [PATCH] fix: set certificate validity for SAML IdPs (#8170) # Which Problems Are Solved Certificates created for a SAML IdP (used for metadata and request singing) did not have any validity set. While it's not required for SAML, when trying to import the certificate into a (keychain) tool it might fail. # How the Problems Are Solved The validity is set based on the `CertificateLifetime` set in the runtime config. ## After the fix: If an IdP was created with a certificate without validity, an admin can regenerate the certificate: - for instance wide IdPs: https://zitadel.com/docs/apis/resources/admin/admin-service-regenerate-saml-provider-certificate#regenerate-saml-identity-provider-certificate - for organization specific IdPs: https://zitadel.com/docs/apis/resources/mgmt/management-service-regenerate-saml-provider-certificate#regenerate-saml-identity-provider-certificate Due to the new certificate, the metadata will change and will need to be updated at the external IdP. # Additional Changes Additionally the `CertificateSize` instead of the `Size` (used for keys) is used for generating the certificate, resp. the underlying key pair. # Additional Context - noted by a customer - needs backports --------- Co-authored-by: Elio Bischof --- internal/command/command.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/internal/command/command.go b/internal/command/command.go index d8e6cfb7cf..22a0ba819b 100644 --- a/internal/command/command.go +++ b/internal/command/command.go @@ -156,7 +156,7 @@ func StartCommands( defaultRefreshTokenLifetime: defaultRefreshTokenLifetime, defaultRefreshTokenIdleLifetime: defaultRefreshTokenIdleLifetime, defaultSecretGenerators: defaultSecretGenerators, - samlCertificateAndKeyGenerator: samlCertificateAndKeyGenerator(defaults.KeyConfig.Size), + samlCertificateAndKeyGenerator: samlCertificateAndKeyGenerator(defaults.KeyConfig.CertificateSize, defaults.KeyConfig.CertificateLifetime), // always true for now until we can check with an eventlist EventExisting: func(event string) bool { return true }, // always true for now until we can check with an eventlist @@ -223,7 +223,7 @@ func exists(ctx context.Context, filter preparation.FilterToQueryReducer, wm exi return wm.Exists(), nil } -func samlCertificateAndKeyGenerator(keySize int) func(id string) ([]byte, []byte, error) { +func samlCertificateAndKeyGenerator(keySize int, lifetime time.Duration) func(id string) ([]byte, []byte, error) { return func(id string) ([]byte, []byte, error) { priv, pub, err := crypto.GenerateKeyPair(keySize) if err != nil { @@ -234,12 +234,15 @@ func samlCertificateAndKeyGenerator(keySize int) func(id string) ([]byte, []byte if err != nil { return nil, nil, err } + now := time.Now() template := x509.Certificate{ SerialNumber: big.NewInt(int64(serial)), Subject: pkix.Name{ Organization: []string{"ZITADEL"}, SerialNumber: id, }, + NotBefore: now, + NotAfter: now.Add(lifetime), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, BasicConstraintsValid: true,