Skip to content
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
87 changes: 0 additions & 87 deletions internal/cnpgi/common/common.go

This file was deleted.

4 changes: 1 addition & 3 deletions internal/cnpgi/common/wal.go
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,7 @@ func (w WALServiceImplementation) restoreFromPgbackrestArchive(

pgbackrestConfiguration := &archive.Spec.Configuration

env := GetRestoreCABundleEnv(pgbackrestConfiguration)
credentialsEnv, err := pgbackrestCredentials.EnvSetBackupCloudCredentials(
env, err := pgbackrestCredentials.EnvSetRestoreCloudCredentials(
ctx,
w.Client,
archive.Namespace,
Expand All @@ -295,7 +294,6 @@ func (w WALServiceImplementation) restoreFromPgbackrestArchive(
if err != nil {
return fmt.Errorf("while getting recover credentials: %w", err)
}
env = MergeEnv(env, credentialsEnv)

options, err := pgbackrestCommand.CloudWalRestoreOptions(ctx, pgbackrestConfiguration, stanza, w.PGDataPath)
if err != nil {
Expand Down
4 changes: 1 addition & 3 deletions internal/cnpgi/instance/backup.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"

pgbackrestv1 "github.com/operasoftware/cnpg-plugin-pgbackrest/api/v1"
"github.com/operasoftware/cnpg-plugin-pgbackrest/internal/cnpgi/common"
"github.com/operasoftware/cnpg-plugin-pgbackrest/internal/cnpgi/metadata"
"github.com/operasoftware/cnpg-plugin-pgbackrest/internal/cnpgi/operator/config"
pgbackrestBackup "github.com/operasoftware/cnpg-plugin-pgbackrest/internal/pgbackrest/backup"
Expand Down Expand Up @@ -106,13 +105,12 @@ func (b BackupServiceImplementation) Backup(
// We need to connect to PostgreSQL and to do that we need
// PGHOST (and the like) to be available
osEnvironment := utils.SanitizedEnviron()
caBundleEnvironment := common.GetRestoreCABundleEnv(&archive.Spec.Configuration)
env, err := pgbackrestCredentials.EnvSetBackupCloudCredentials(
ctx,
b.Client,
archive.Namespace,
&archive.Spec.Configuration,
common.MergeEnv(osEnvironment, caBundleEnvironment))
osEnvironment)
if err != nil {
contextLogger.Error(err, "while setting backup cloud credentials")
return nil, err
Expand Down
4 changes: 4 additions & 0 deletions internal/cnpgi/operator/specs/role.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

pgbackrestv1 "github.com/operasoftware/cnpg-plugin-pgbackrest/api/v1"
pgbackrestApi "github.com/operasoftware/cnpg-plugin-pgbackrest/internal/pgbackrest/api"
)

// BuildRole builds the Role object for this cluster
Expand All @@ -51,6 +52,9 @@ func BuildRole(
for _, secret := range CollectSecretNamesFromCredentials(&repo.PgbackrestCredentials) {
secretsSet.Put(secret)
}
for _, secret := range CollectSecretNamesFromRepositories([]pgbackrestApi.PgbackrestRepository{repo}) {
secretsSet.Put(secret)
}
}
}

Expand Down
18 changes: 17 additions & 1 deletion internal/cnpgi/operator/specs/secrets.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ import (
pgbackrestApi "github.com/operasoftware/cnpg-plugin-pgbackrest/internal/pgbackrest/api"
)

// CollectSecretNamesFromCredentials collects the names of the secrets
// CollectSecretNamesFromCredentials collects the names of the S3 credential
// secrets referenced by the backup credentials.
func CollectSecretNamesFromCredentials(pgbackrestCredentials *pgbackrestApi.PgbackrestCredentials) []string {
var references []*machineryapi.SecretKeySelector
if pgbackrestCredentials.AWS != nil {
Expand All @@ -44,3 +45,18 @@ func CollectSecretNamesFromCredentials(pgbackrestCredentials *pgbackrestApi.Pgba

return result
}

// CollectSecretNamesFromRepositories collects the names of all secrets referenced
// by the repository configurations, including the endpoint CA certificate secret.
func CollectSecretNamesFromRepositories(repositories []pgbackrestApi.PgbackrestRepository) []string {
var result []string
for _, repo := range repositories {
if repo.EndpointCA != nil {
result = append(result, repo.EndpointCA.Name)
}
if repo.EncryptionKey != nil {
result = append(result, repo.EncryptionKey.Name)
Comment thread
Agalin marked this conversation as resolved.
}
}
return result
}
75 changes: 53 additions & 22 deletions internal/pgbackrest/credentials/credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ package credentials
import (
"context"
"fmt"
"os"

machineryapi "github.com/cloudnative-pg/machinery/pkg/api"
corev1 "k8s.io/api/core/v1"
Expand All @@ -38,28 +39,24 @@ const (
// CertificatesDir location to store the certificates
CertificatesDir = ScratchDataDirectory + "/certificates/"

// TODO: Properly mount/read and pass CA file for each pgbackrest repository.
Comment thread
Agalin marked this conversation as resolved.

// BarmanBackupEndpointCACertificateLocation is the location where the barman endpoint
// CA certificate is stored
BarmanBackupEndpointCACertificateLocation = CertificatesDir + BarmanBackupEndpointCACertificateFileName

// BarmanBackupEndpointCACertificateFileName is the name of the file in which the barman endpoint
// CA certificate for backups is stored
BarmanBackupEndpointCACertificateFileName = "backup-" + BarmanEndpointCACertificateFileName

// BarmanRestoreEndpointCACertificateLocation is the location where the barman endpoint
// CA certificate is stored
BarmanRestoreEndpointCACertificateLocation = CertificatesDir + BarmanRestoreEndpointCACertificateFileName
// PgBackRestEndpointCACertificateFileName is the base name of the file in
// which the pgBackRest endpoint CA certificate is stored.
PgBackRestEndpointCACertificateFileName = "pgbackrest-ca.crt"
)

// BarmanRestoreEndpointCACertificateFileName is the name of the file in which the barman endpoint
// CA certificate for restores is stored
BarmanRestoreEndpointCACertificateFileName = "restore-" + BarmanEndpointCACertificateFileName
// PgBackRestBackupEndpointCACertificateLocation returns the file path where
// the pgBackRest endpoint CA certificate for backups of the given repository
// (zero-based index) is stored.
func PgBackRestBackupEndpointCACertificateLocation(repoIndex int) string {
return CertificatesDir + fmt.Sprintf("backup-repo%d-%s", repoIndex+1, PgBackRestEndpointCACertificateFileName)
}

// BarmanEndpointCACertificateFileName is the name of the file in which the barman endpoint
// CA certificate is stored
BarmanEndpointCACertificateFileName = "barman-ca.crt"
)
// PgBackRestRestoreEndpointCACertificateLocation returns the file path where
// the pgBackRest endpoint CA certificate for restores of the given repository
// (zero-based index) is stored.
func PgBackRestRestoreEndpointCACertificateLocation(repoIndex int) string {
return CertificatesDir + fmt.Sprintf("restore-repo%d-%s", repoIndex+1, PgBackRestEndpointCACertificateFileName)
}

// EnvSetBackupCloudCredentials sets the AWS environment variables needed for backups
// given the configuration inside the cluster
Expand All @@ -72,7 +69,11 @@ func EnvSetBackupCloudCredentials(
) ([]string, error) {
for index, repo := range configuration.Repositories {
if repo.EndpointCA != nil {
env = append(env, utils.FormatRepoEnv(index, "HOST_CA_FILE", BarmanBackupEndpointCACertificateLocation))
caPath := PgBackRestBackupEndpointCACertificateLocation(index)
if err := writeEndpointCACertificate(ctx, c, repo.EndpointCA, namespace, caPath); err != nil {
return nil, fmt.Errorf("writing backup endpoint CA certificate: %w", err)
}
env = append(env, utils.FormatRepoEnv(index, "STORAGE_CA_FILE", caPath))
}
}

Expand All @@ -90,7 +91,11 @@ func EnvSetRestoreCloudCredentials(
) ([]string, error) {
for index, repo := range configuration.Repositories {
if repo.EndpointCA != nil {
env = append(env, utils.FormatRepoEnv(index, "HOST_CA_FILE", BarmanBackupEndpointCACertificateLocation))
caPath := PgBackRestRestoreEndpointCACertificateLocation(index)
if err := writeEndpointCACertificate(ctx, c, repo.EndpointCA, namespace, caPath); err != nil {
return nil, fmt.Errorf("writing restore endpoint CA certificate: %w", err)
}
env = append(env, utils.FormatRepoEnv(index, "STORAGE_CA_FILE", caPath))
}
}

Expand Down Expand Up @@ -229,3 +234,29 @@ func extractValueFromSecret(

return value, nil
}

// writeEndpointCACertificate reads the CA certificate from the referenced Kubernetes
// Secret and writes it to the given file path so pgBackRest can verify the S3
// endpoint's TLS certificate via the PGBACKREST_REPO<N>_STORAGE_CA_FILE env var.
func writeEndpointCACertificate(
ctx context.Context,
c client.Client,
secretReference *machineryapi.SecretKeySelector,
namespace string,
filePath string,
) error {
caData, err := extractValueFromSecret(ctx, c, secretReference, namespace)
if err != nil {
return fmt.Errorf("reading endpoint CA secret %s/%s: %w", namespace, secretReference.Name, err)
}

if err := os.MkdirAll(CertificatesDir, 0o700); err != nil {
return fmt.Errorf("creating certificates directory %s: %w", CertificatesDir, err)
}

if err := os.WriteFile(filePath, caData, 0o600); err != nil {
return fmt.Errorf("writing endpoint CA certificate to %s: %w", filePath, err)
}

return nil
}