diff --git a/NOTICE b/NOTICE index a770673a..f55d8753 100644 --- a/NOTICE +++ b/NOTICE @@ -53,9 +53,9 @@ License URL: https://github.com/googleapis/google-cloud-go/blob/resourcemanager/ ---------- Module: cloud.google.com/go/serviceusage -Version: v1.10.0 +Version: v1.11.0 License: Apache-2.0 -License URL: https://github.com/googleapis/google-cloud-go/blob/serviceusage/v1.10.0/serviceusage/LICENSE +License URL: https://github.com/googleapis/google-cloud-go/blob/serviceusage/v1.11.0/serviceusage/LICENSE ---------- Module: code.gitea.io/sdk/gitea diff --git a/internal/bootstrap/gcp/install_config.go b/internal/bootstrap/gcp/install_config.go index e5d02864..cec7f0fe 100644 --- a/internal/bootstrap/gcp/install_config.go +++ b/internal/bootstrap/gcp/install_config.go @@ -113,7 +113,11 @@ func (b *GCPBootstrapper) UpdateInstallConfig() error { Hostname: b.Env.PostgreSQLNode.GetName(), } } + + previousPrimaryIP := b.Env.InstallConfig.Postgres.Primary.IP + previousPrimaryHostname := b.Env.InstallConfig.Postgres.Primary.Hostname b.Env.InstallConfig.Postgres.Primary.IP = b.Env.PostgreSQLNode.GetInternalIP() + b.Env.InstallConfig.Postgres.Primary.Hostname = b.Env.PostgreSQLNode.GetName() b.Env.InstallConfig.Ceph.CsiKubeletDir = "/var/lib/k0s/kubelet" b.Env.InstallConfig.Ceph.NodesSubnet = "10.10.0.0/20" @@ -247,24 +251,8 @@ func (b *GCPBootstrapper) UpdateInstallConfig() error { return fmt.Errorf("failed to generate secrets: %w", err) } } else { - var err error - b.Env.InstallConfig.Postgres.Primary.PrivateKey, b.Env.InstallConfig.Postgres.Primary.SSLConfig.ServerCertPem, err = installer.GenerateServerCertificate( - b.Env.InstallConfig.Postgres.CaCertPrivateKey, - b.Env.InstallConfig.Postgres.CACertPem, - b.Env.InstallConfig.Postgres.Primary.Hostname, - []string{b.Env.InstallConfig.Postgres.Primary.IP}) - if err != nil { - return fmt.Errorf("failed to generate primary server certificate: %w", err) - } - if b.Env.InstallConfig.Postgres.Replica != nil { - b.Env.InstallConfig.Postgres.ReplicaPrivateKey, b.Env.InstallConfig.Postgres.Replica.SSLConfig.ServerCertPem, err = installer.GenerateServerCertificate( - b.Env.InstallConfig.Postgres.CaCertPrivateKey, - b.Env.InstallConfig.Postgres.CACertPem, - b.Env.InstallConfig.Postgres.Replica.Name, - []string{b.Env.InstallConfig.Postgres.Replica.IP}) - if err != nil { - return fmt.Errorf("failed to generate replica server certificate: %w", err) - } + if err := b.regeneratePostgresCerts(previousPrimaryIP, previousPrimaryHostname); err != nil { + return err } } @@ -298,6 +286,47 @@ func (b *GCPBootstrapper) UpdateInstallConfig() error { return nil } +// regeneratePostgresCerts regenerates PostgreSQL TLS certificates when the IP/hostname +// changed or no private key was loaded from the vault. +func (b *GCPBootstrapper) regeneratePostgresCerts(previousPrimaryIP, previousPrimaryHostname string) error { + // Only regenerate postgres certificates if the IP or hostname changed, + // or if the private key was not loaded from the vault. + primaryNeedsRegen := b.Env.InstallConfig.Postgres.Primary.PrivateKey == "" || + previousPrimaryIP != b.Env.InstallConfig.Postgres.Primary.IP || + previousPrimaryHostname != b.Env.InstallConfig.Postgres.Primary.Hostname + + if primaryNeedsRegen { + var err error + b.Env.InstallConfig.Postgres.Primary.PrivateKey, b.Env.InstallConfig.Postgres.Primary.SSLConfig.ServerCertPem, err = installer.GenerateServerCertificate( + b.Env.InstallConfig.Postgres.CaCertPrivateKey, + b.Env.InstallConfig.Postgres.CACertPem, + b.Env.InstallConfig.Postgres.Primary.Hostname, + []string{b.Env.InstallConfig.Postgres.Primary.IP}) + if err != nil { + return fmt.Errorf("failed to generate primary server certificate: %w", err) + } + if err := installer.ValidateCertKeyPair(b.Env.InstallConfig.Postgres.Primary.SSLConfig.ServerCertPem, b.Env.InstallConfig.Postgres.Primary.PrivateKey); err != nil { + return fmt.Errorf("primary PostgreSQL cert/key validation failed: %w", err) + } + } + // Replica certificates only regenerate if the key is missing from the vault. + if b.Env.InstallConfig.Postgres.Replica != nil && (b.Env.InstallConfig.Postgres.ReplicaPrivateKey == "") { + var err error + b.Env.InstallConfig.Postgres.ReplicaPrivateKey, b.Env.InstallConfig.Postgres.Replica.SSLConfig.ServerCertPem, err = installer.GenerateServerCertificate( + b.Env.InstallConfig.Postgres.CaCertPrivateKey, + b.Env.InstallConfig.Postgres.CACertPem, + b.Env.InstallConfig.Postgres.Replica.Name, + []string{b.Env.InstallConfig.Postgres.Replica.IP}) + if err != nil { + return fmt.Errorf("failed to generate replica server certificate: %w", err) + } + if err := installer.ValidateCertKeyPair(b.Env.InstallConfig.Postgres.Replica.SSLConfig.ServerCertPem, b.Env.InstallConfig.Postgres.ReplicaPrivateKey); err != nil { + return fmt.Errorf("replica PostgreSQL cert/key validation failed: %w", err) + } + } + return nil +} + func (b *GCPBootstrapper) EnsureAgeKey() error { hasKey := b.Env.Jumpbox.NodeClient.HasFile(b.Env.Jumpbox, b.Env.SecretsDir+"/age_key.txt") if hasKey { diff --git a/internal/bootstrap/gcp/install_config_test.go b/internal/bootstrap/gcp/install_config_test.go index 9e30dbcd..88498eee 100644 --- a/internal/bootstrap/gcp/install_config_test.go +++ b/internal/bootstrap/gcp/install_config_test.go @@ -473,6 +473,131 @@ var _ = Describe("Installconfig & Secrets", func() { Expect(err.Error()).To(ContainSubstring("failed to copy secrets file to jumpbox")) }) }) + + Describe("ExistingConfigUsed", func() { + BeforeEach(func() { + csEnv.ExistingConfigUsed = true + }) + + Context("with unchanged IP and existing key", func() { + BeforeEach(func() { + caKey, caCert, err := installer.GenerateCA("Test CA", "DE", "Berlin", "TestOrg") + Expect(err).NotTo(HaveOccurred()) + + key, cert, err := installer.GenerateServerCertificate(caKey, caCert, "postgres", []string{"10.0.0.1"}) + Expect(err).NotTo(HaveOccurred()) + + csEnv.InstallConfig.Postgres.CaCertPrivateKey = caKey + csEnv.InstallConfig.Postgres.CACertPem = caCert + csEnv.InstallConfig.Postgres.Primary.IP = "10.0.0.1" + csEnv.InstallConfig.Postgres.Primary.Hostname = "postgres" + csEnv.InstallConfig.Postgres.Primary.PrivateKey = key + csEnv.InstallConfig.Postgres.Primary.SSLConfig.ServerCertPem = cert + }) + + It("preserves existing cert/key without regeneration", func() { + origKey := csEnv.InstallConfig.Postgres.Primary.PrivateKey + origCert := csEnv.InstallConfig.Postgres.Primary.SSLConfig.ServerCertPem + + icg.EXPECT().GenerateSecrets().Return(nil).Times(0) + icg.EXPECT().WriteInstallConfig("fake-config-file", true).Return(nil) + icg.EXPECT().WriteVault("fake-secret", true).Return(nil) + nodeClient.EXPECT().CopyFile(mock.Anything, mock.Anything, mock.Anything).Return(nil).Twice() + + err := bs.UpdateInstallConfig() + Expect(err).NotTo(HaveOccurred()) + + Expect(bs.Env.InstallConfig.Postgres.Primary.PrivateKey).To(Equal(origKey)) + Expect(bs.Env.InstallConfig.Postgres.Primary.SSLConfig.ServerCertPem).To(Equal(origCert)) + }) + }) + + Context("with changed IP", func() { + BeforeEach(func() { + caKey, caCert, err := installer.GenerateCA("Test CA", "DE", "Berlin", "TestOrg") + Expect(err).NotTo(HaveOccurred()) + + key, cert, err := installer.GenerateServerCertificate(caKey, caCert, "postgres", []string{"10.0.0.99"}) + Expect(err).NotTo(HaveOccurred()) + + csEnv.InstallConfig.Postgres.CaCertPrivateKey = caKey + csEnv.InstallConfig.Postgres.CACertPem = caCert + csEnv.InstallConfig.Postgres.Primary.IP = "10.0.0.99" + csEnv.InstallConfig.Postgres.Primary.Hostname = "postgres" + csEnv.InstallConfig.Postgres.Primary.PrivateKey = key + csEnv.InstallConfig.Postgres.Primary.SSLConfig.ServerCertPem = cert + }) + + It("regenerates cert/key for the new IP", func() { + origKey := csEnv.InstallConfig.Postgres.Primary.PrivateKey + + icg.EXPECT().WriteInstallConfig("fake-config-file", true).Return(nil) + icg.EXPECT().WriteVault("fake-secret", true).Return(nil) + nodeClient.EXPECT().CopyFile(mock.Anything, mock.Anything, mock.Anything).Return(nil).Twice() + + err := bs.UpdateInstallConfig() + Expect(err).NotTo(HaveOccurred()) + + // IP should be updated to the PostgreSQLNode's InternalIP ("10.0.0.1" from fakeNode) + Expect(bs.Env.InstallConfig.Postgres.Primary.IP).To(Equal("10.0.0.1")) + // Key should be regenerated + Expect(bs.Env.InstallConfig.Postgres.Primary.PrivateKey).NotTo(Equal(origKey)) + Expect(bs.Env.InstallConfig.Postgres.Primary.PrivateKey).NotTo(BeEmpty()) + // New cert/key should match + err = installer.ValidateCertKeyPair( + bs.Env.InstallConfig.Postgres.Primary.SSLConfig.ServerCertPem, + bs.Env.InstallConfig.Postgres.Primary.PrivateKey, + ) + Expect(err).NotTo(HaveOccurred()) + }) + }) + + Context("with empty PrivateKey (not loaded from vault)", func() { + BeforeEach(func() { + caKey, caCert, err := installer.GenerateCA("Test CA", "DE", "Berlin", "TestOrg") + Expect(err).NotTo(HaveOccurred()) + + csEnv.InstallConfig.Postgres.CaCertPrivateKey = caKey + csEnv.InstallConfig.Postgres.CACertPem = caCert + csEnv.InstallConfig.Postgres.Primary.IP = "10.0.0.1" + csEnv.InstallConfig.Postgres.Primary.Hostname = "postgres" + csEnv.InstallConfig.Postgres.Primary.PrivateKey = "" + }) + + It("generates new cert/key pair", func() { + icg.EXPECT().WriteInstallConfig("fake-config-file", true).Return(nil) + icg.EXPECT().WriteVault("fake-secret", true).Return(nil) + nodeClient.EXPECT().CopyFile(mock.Anything, mock.Anything, mock.Anything).Return(nil).Twice() + + err := bs.UpdateInstallConfig() + Expect(err).NotTo(HaveOccurred()) + + Expect(bs.Env.InstallConfig.Postgres.Primary.PrivateKey).NotTo(BeEmpty()) + Expect(bs.Env.InstallConfig.Postgres.Primary.SSLConfig.ServerCertPem).NotTo(BeEmpty()) + err = installer.ValidateCertKeyPair( + bs.Env.InstallConfig.Postgres.Primary.SSLConfig.ServerCertPem, + bs.Env.InstallConfig.Postgres.Primary.PrivateKey, + ) + Expect(err).NotTo(HaveOccurred()) + }) + }) + + Context("with missing CA cert (cert generation fails)", func() { + BeforeEach(func() { + csEnv.InstallConfig.Postgres.CaCertPrivateKey = "" + csEnv.InstallConfig.Postgres.CACertPem = "" + csEnv.InstallConfig.Postgres.Primary.IP = "10.0.0.1" + csEnv.InstallConfig.Postgres.Primary.Hostname = "postgres" + csEnv.InstallConfig.Postgres.Primary.PrivateKey = "" + }) + + It("returns an error", func() { + err := bs.UpdateInstallConfig() + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("failed to generate primary server certificate")) + }) + }) + }) }) Describe("EnsureAgeKey", func() { diff --git a/internal/installer/config_manager.go b/internal/installer/config_manager.go index e8e88041..297a29e1 100644 --- a/internal/installer/config_manager.go +++ b/internal/installer/config_manager.go @@ -242,7 +242,21 @@ func (g *InstallConfig) WriteVault(vaultPath string, withComments bool) error { return fmt.Errorf("no configuration provided - config is nil") } - vault := g.Config.AddSecretsToVault(g.GetVault()) + vault := g.Config.ExtractVault() + + // Preserve vault-only secrets that were added directly via SetSecret and aren't on the config struct. + if g.Vault != nil { + configSecretNames := make(map[string]bool) + for _, s := range vault.Secrets { + configSecretNames[s.Name] = true + } + for _, s := range g.Vault.Secrets { + if !configSecretNames[s.Name] { + vault.Secrets = append(vault.Secrets, s) + } + } + } + vaultYAML, err := vault.Marshal() if err != nil { return fmt.Errorf("failed to marshal vault.yaml: %w", err) diff --git a/internal/installer/config_manager_secrets.go b/internal/installer/config_manager_secrets.go index 790538d5..887f41b8 100644 --- a/internal/installer/config_manager_secrets.go +++ b/internal/installer/config_manager_secrets.go @@ -59,6 +59,10 @@ func (g *InstallConfig) generatePostgresSecrets(config *files.RootConfig) error return fmt.Errorf("failed to generate primary PostgreSQL certificate: %w", err) } + if err := ValidateCertKeyPair(config.Postgres.Primary.SSLConfig.ServerCertPem, config.Postgres.Primary.PrivateKey); err != nil { + return fmt.Errorf("primary PostgreSQL cert/key validation failed: %w", err) + } + config.Postgres.AdminPassword = GeneratePassword(32) config.Postgres.ReplicaPassword = GeneratePassword(32) @@ -72,6 +76,10 @@ func (g *InstallConfig) generatePostgresSecrets(config *files.RootConfig) error if err != nil { return fmt.Errorf("failed to generate replica PostgreSQL certificate: %w", err) } + + if err := ValidateCertKeyPair(config.Postgres.Replica.SSLConfig.ServerCertPem, config.Postgres.ReplicaPrivateKey); err != nil { + return fmt.Errorf("replica PostgreSQL cert/key validation failed: %w", err) + } } services := []string{"auth", "deployment", "ide", "marketplace", "payment", "public_api", "team", "workspace"} diff --git a/internal/installer/config_manager_test.go b/internal/installer/config_manager_test.go index 7b1c6810..f78d008d 100644 --- a/internal/installer/config_manager_test.go +++ b/internal/installer/config_manager_test.go @@ -85,6 +85,26 @@ func (m *MockFileIO) ReadDir(dirname string) ([]os.DirEntry, error) { return nil, nil } +func (m *MockFileIO) ReadFile(filename string) ([]byte, error) { + if data, ok := m.files[filename]; ok { + return data, nil + } + return nil, os.ErrNotExist +} + +func (m *MockFileIO) Remove(path string) error { + delete(m.files, path) + return nil +} + +func (m *MockFileIO) Chmod(name string, mode os.FileMode) error { + return nil +} + +func (m *MockFileIO) GetFileContent(path string) []byte { + return m.files[path] +} + type MockFile struct { *bytes.Buffer closed bool @@ -504,5 +524,145 @@ var _ = Describe("ConfigManager", func() { }) }) + Context("vault deduplication on re-write", func() { + It("should not produce duplicate vault entries when WriteVault is called after loading existing vault", func() { + mockIO := NewMockFileIO() + configManager.SetFileIO(mockIO) + + err := configManager.ApplyProfile("prod") + Expect(err).ToNot(HaveOccurred()) + + err = configManager.GenerateSecrets() + Expect(err).ToNot(HaveOccurred()) + + // First write via WriteVault + err = configManager.WriteVault("/tmp/vault.yaml", false) + Expect(err).ToNot(HaveOccurred()) + + firstVaultBytes := mockIO.GetFileContent("/tmp/vault.yaml") + Expect(firstVaultBytes).ToNot(BeEmpty()) + + // Load the written vault back + vault := &files.InstallVault{} + err = vault.Unmarshal(firstVaultBytes) + Expect(err).ToNot(HaveOccurred()) + configManager.Vault = vault + + // Re-write vault (simulating a second run) + err = configManager.WriteVault("/tmp/vault.yaml", false) + Expect(err).ToNot(HaveOccurred()) + + secondVaultBytes := mockIO.GetFileContent("/tmp/vault.yaml") + Expect(secondVaultBytes).To(Equal(firstVaultBytes), + "serialized vault should be identical after load and re-write") + }) + }) + + Context("full bootstrap re-run simulation", func() { + It("should preserve matching cert/key pairs across write → load → merge → re-write cycle", func() { + mockIO := NewMockFileIO() + configManager.SetFileIO(mockIO) + + // --- First run: generate everything from scratch --- + err := configManager.ApplyProfile("prod") + Expect(err).ToNot(HaveOccurred()) + + err = configManager.GenerateSecrets() + Expect(err).ToNot(HaveOccurred()) + + // Verify cert/key pair matches after initial generation + err = installer.ValidateCertKeyPair( + configManager.Config.Postgres.Primary.SSLConfig.ServerCertPem, + configManager.Config.Postgres.Primary.PrivateKey, + ) + Expect(err).ToNot(HaveOccurred(), "cert/key should match after initial generation") + + // Save the original cert and key for later comparison + origCert := configManager.Config.Postgres.Primary.SSLConfig.ServerCertPem + origKey := configManager.Config.Postgres.Primary.PrivateKey + Expect(origCert).ToNot(BeEmpty()) + Expect(origKey).ToNot(BeEmpty()) + + // Write config and vault + err = configManager.WriteInstallConfig("/tmp/config.yaml", false) + Expect(err).ToNot(HaveOccurred()) + err = configManager.WriteVault("/tmp/vault.yaml", false) + Expect(err).ToNot(HaveOccurred()) + + // --- Second run: simulate loading existing files --- + configManager2 := &installer.InstallConfig{} + configManager2.SetFileIO(mockIO) + + // Reload config from written YAML + configBytes := mockIO.GetFileContent("/tmp/config.yaml") + Expect(configBytes).ToNot(BeNil()) + config2 := files.NewRootConfig() + err = config2.Unmarshal(configBytes) + Expect(err).ToNot(HaveOccurred()) + configManager2.Config = &config2 + + Expect(configManager2.Config.Postgres.Primary.PrivateKey).To(BeEmpty(), + "private key should NOT be in config.yaml (it has yaml:\"-\" tag)") + Expect(configManager2.Config.Postgres.Primary.SSLConfig.ServerCertPem).To(Equal(origCert), + "cert should be in config.yaml") + + // Reload vault from written YAML + vaultBytes := mockIO.GetFileContent("/tmp/vault.yaml") + Expect(vaultBytes).ToNot(BeNil()) + vault2 := &files.InstallVault{} + err = vault2.Unmarshal(vaultBytes) + Expect(err).ToNot(HaveOccurred()) + configManager2.Vault = vault2 + + // Merge vault into config + err = configManager2.MergeVaultIntoConfig() + Expect(err).ToNot(HaveOccurred()) + + // After merge, the private key should be restored from vault + Expect(configManager2.Config.Postgres.Primary.PrivateKey).To(Equal(origKey), + "private key should be restored from vault after merge") + + // Cert/key should still match + err = installer.ValidateCertKeyPair( + configManager2.Config.Postgres.Primary.SSLConfig.ServerCertPem, + configManager2.Config.Postgres.Primary.PrivateKey, + ) + Expect(err).ToNot(HaveOccurred(), "cert/key should match after load + merge") + + // Write vault again + err = configManager2.WriteVault("/tmp/vault2.yaml", false) + Expect(err).ToNot(HaveOccurred()) + + // Verify no duplicates in re-written vault + vault3 := &files.InstallVault{} + vaultBytes2 := mockIO.GetFileContent("/tmp/vault2.yaml") + err = vault3.Unmarshal(vaultBytes2) + Expect(err).ToNot(HaveOccurred()) + + nameCount := make(map[string]int) + for _, secret := range vault3.Secrets { + nameCount[secret.Name]++ + } + for name, count := range nameCount { + Expect(count).To(Equal(1), "secret '%s' has %d entries (expected 1) — duplication bug!", name, count) + } + + // Verify the key in re-written vault still matches the cert + var rewrittenKey string + for _, secret := range vault3.Secrets { + if secret.Name == "postgresPrimaryServerKeyPem" && secret.File != nil { + rewrittenKey = secret.File.Content + } + } + Expect(rewrittenKey).To(Equal(origKey), + "re-written vault should contain the same key") + err = installer.ValidateCertKeyPair( + configManager2.Config.Postgres.Primary.SSLConfig.ServerCertPem, + rewrittenKey, + ) + Expect(err).ToNot(HaveOccurred(), "cert/key should match in re-written vault") + }) + }) + }) }) diff --git a/internal/installer/crypto.go b/internal/installer/crypto.go index 0fbe829f..e85a9cc7 100644 --- a/internal/installer/crypto.go +++ b/internal/installer/crypto.go @@ -8,6 +8,7 @@ import ( "crypto/elliptic" "crypto/rand" "crypto/rsa" + "crypto/tls" "crypto/x509" "crypto/x509/pkix" "encoding/base64" @@ -219,3 +220,9 @@ func encodePEMCert(certDER []byte) string { Bytes: certDER, })) } + +// ValidateCertKeyPair verifies that a PEM-encoded certificate's public key matches a PEM-encoded private key. +func ValidateCertKeyPair(certPEM, keyPEM string) error { + _, err := tls.X509KeyPair([]byte(certPEM), []byte(keyPEM)) + return err +} diff --git a/internal/installer/crypto_test.go b/internal/installer/crypto_test.go index faeaa69e..5649ddd9 100644 --- a/internal/installer/crypto_test.go +++ b/internal/installer/crypto_test.go @@ -107,3 +107,49 @@ var _ = Describe("GeneratePassword", func() { Expect(password1).NotTo(Equal(password2)) }) }) + +var _ = Describe("ValidateCertKeyPair", func() { + It("succeeds for a matching cert and key pair", func() { + caKeyPEM, caCertPEM, err := GenerateCA("Test CA", "DE", "Berlin", "TestOrg") + Expect(err).NotTo(HaveOccurred()) + + keyPEM, certPEM, err := GenerateServerCertificate(caKeyPEM, caCertPEM, "test-server", []string{"10.0.0.1"}) + Expect(err).NotTo(HaveOccurred()) + + err = ValidateCertKeyPair(certPEM, keyPEM) + Expect(err).NotTo(HaveOccurred()) + }) + + It("fails for a mismatched cert and key pair", func() { + caKeyPEM, caCertPEM, err := GenerateCA("Test CA", "DE", "Berlin", "TestOrg") + Expect(err).NotTo(HaveOccurred()) + + _, certPEM, err := GenerateServerCertificate(caKeyPEM, caCertPEM, "server-1", []string{"10.0.0.1"}) + Expect(err).NotTo(HaveOccurred()) + + keyPEM, _, err := GenerateServerCertificate(caKeyPEM, caCertPEM, "server-2", []string{"10.0.0.2"}) + Expect(err).NotTo(HaveOccurred()) + + err = ValidateCertKeyPair(certPEM, keyPEM) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("private key does not match public key")) + }) + + It("fails for invalid cert PEM", func() { + err := ValidateCertKeyPair("not-a-cert", "not-a-key") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("failed to find any PEM data")) + }) + + It("fails for invalid key PEM", func() { + caKeyPEM, caCertPEM, err := GenerateCA("Test CA", "DE", "Berlin", "TestOrg") + Expect(err).NotTo(HaveOccurred()) + + _, certPEM, err := GenerateServerCertificate(caKeyPEM, caCertPEM, "test-server", []string{"10.0.0.1"}) + Expect(err).NotTo(HaveOccurred()) + + err = ValidateCertKeyPair(certPEM, "not-a-key") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("failed to find any PEM data")) + }) +}) diff --git a/internal/tmpl/NOTICE b/internal/tmpl/NOTICE index a770673a..f55d8753 100644 --- a/internal/tmpl/NOTICE +++ b/internal/tmpl/NOTICE @@ -53,9 +53,9 @@ License URL: https://github.com/googleapis/google-cloud-go/blob/resourcemanager/ ---------- Module: cloud.google.com/go/serviceusage -Version: v1.10.0 +Version: v1.11.0 License: Apache-2.0 -License URL: https://github.com/googleapis/google-cloud-go/blob/serviceusage/v1.10.0/serviceusage/LICENSE +License URL: https://github.com/googleapis/google-cloud-go/blob/serviceusage/v1.11.0/serviceusage/LICENSE ---------- Module: code.gitea.io/sdk/gitea