diff --git a/containers/Dockerfile.plugin b/containers/Dockerfile.plugin index 5777125c..f090e3b1 100644 --- a/containers/Dockerfile.plugin +++ b/containers/Dockerfile.plugin @@ -15,6 +15,7 @@ RUN go mod download COPY ../cmd/manager/main.go cmd/manager/main.go COPY ../api/ api/ COPY ../internal/ internal/ +COPY ../pkg/ pkg/ ENV GOCACHE=/root/.cache/go-build ENV GOMODCACHE=/go/pkg/mod diff --git a/containers/Dockerfile.sidecar b/containers/Dockerfile.sidecar index 828fcff5..a43b8d04 100644 --- a/containers/Dockerfile.sidecar +++ b/containers/Dockerfile.sidecar @@ -24,6 +24,7 @@ ENV GOMODCACHE=/go/pkg/mod COPY ../cmd/manager/main.go cmd/manager/main.go COPY ../api/ api/ COPY ../internal/ internal/ +COPY ../pkg/ pkg/ # Build # the GOARCH has not a default value to allow the binary be built according to the host where the command diff --git a/internal/cnpgi/common/common.go b/internal/cnpgi/common/common.go index 9526d7e2..7fa0674c 100644 --- a/internal/cnpgi/common/common.go +++ b/internal/cnpgi/common/common.go @@ -20,13 +20,17 @@ SPDX-License-Identifier: Apache-2.0 package common import ( + "context" "fmt" "path" "strings" barmanapi "github.com/cloudnative-pg/barman-cloud/pkg/api" + "github.com/cloudnative-pg/barman-cloud/pkg/command" + apiv1 "github.com/cloudnative-pg/plugin-barman-cloud/api/v1" "github.com/cloudnative-pg/plugin-barman-cloud/internal/cnpgi/metadata" + pluginmetadata "github.com/cloudnative-pg/plugin-barman-cloud/pkg/metadata" ) // TODO: refactor. @@ -97,3 +101,14 @@ func MergeEnv(env []string, incomingEnv []string) []string { func BuildCertificateFilePath(objectStoreName string) string { return path.Join(metadata.BarmanCertificatesPath, objectStoreName, metadata.BarmanCertificatesFileName) } + +// ContextWithProviderOptions enriches the context with cloud service provider specific options +// based on the ObjectStore resource +func ContextWithProviderOptions(ctx context.Context, objectStore apiv1.ObjectStore) context.Context { + if objectStore.GetAnnotations()[pluginmetadata.UseDefaultAzureCredentialAnnotationName] == + pluginmetadata.UseDefaultAzureCredentialTrueValue { + return command.ContextWithDefaultAzureCredentials(ctx, true) + } + + return ctx +} diff --git a/internal/cnpgi/common/wal.go b/internal/cnpgi/common/wal.go index 8e58cb42..c9b286bc 100644 --- a/internal/cnpgi/common/wal.go +++ b/internal/cnpgi/common/wal.go @@ -127,6 +127,8 @@ func (w WALServiceImplementation) Archive( return nil, err } + ctx = ContextWithProviderOptions(ctx, objectStore) + envArchive, err := barmanCredentials.EnvSetCloudCredentialsAndCertificates( ctx, w.Client, diff --git a/internal/cnpgi/instance/backup.go b/internal/cnpgi/instance/backup.go index ebf166c4..0b90edea 100644 --- a/internal/cnpgi/instance/backup.go +++ b/internal/cnpgi/instance/backup.go @@ -87,6 +87,8 @@ func (b BackupServiceImplementation) Backup( return nil, err } + ctx = common.ContextWithProviderOptions(ctx, objectStore) + if err := fileutils.EnsureDirectoryExists(postgres.BackupTemporaryDirectory); err != nil { contextLogger.Error(err, "Cannot create backup temporary directory", "err", err) return nil, err diff --git a/internal/cnpgi/instance/retention.go b/internal/cnpgi/instance/retention.go index 372d50ee..ec4becb6 100644 --- a/internal/cnpgi/instance/retention.go +++ b/internal/cnpgi/instance/retention.go @@ -93,6 +93,8 @@ func (c *CatalogMaintenanceRunnable) cycle(ctx context.Context) (time.Duration, return 0, err } + ctx = common.ContextWithProviderOptions(ctx, barmanObjectStore) + if err := c.maintenance(ctx, &cluster, &barmanObjectStore); err != nil { return 0, err } diff --git a/internal/cnpgi/restore/restore.go b/internal/cnpgi/restore/restore.go index 187143ee..42d8f623 100644 --- a/internal/cnpgi/restore/restore.go +++ b/internal/cnpgi/restore/restore.go @@ -109,7 +109,7 @@ func (impl JobHookImpl) Restore( } if err := impl.checkBackupDestination( - ctx, + common.ContextWithProviderOptions(ctx, targetObjectStore), configuration.Cluster, &targetObjectStore.Spec.Configuration, targetObjectStore.Name, @@ -118,6 +118,8 @@ func (impl JobHookImpl) Restore( } } + ctx = common.ContextWithProviderOptions(ctx, recoveryObjectStore) + // Detect the backup to recover backup, env, err := loadBackupObjectFromExternalCluster( ctx, diff --git a/pkg/metadata/doc.go b/pkg/metadata/doc.go new file mode 100644 index 00000000..5d2f6890 --- /dev/null +++ b/pkg/metadata/doc.go @@ -0,0 +1,2 @@ +// Package metadata provides metadata utilities for the Barman Cloud plugin +package metadata diff --git a/pkg/metadata/labels_annotations.go b/pkg/metadata/labels_annotations.go new file mode 100644 index 00000000..e277a237 --- /dev/null +++ b/pkg/metadata/labels_annotations.go @@ -0,0 +1,15 @@ +package metadata + +// MetadataNamespace is the namespace used for the Barman Cloud plugin metadata +const MetadataNamespace = "barmancloud.cnpg.io" + +const ( + // UseDefaultAzureCredentialAnnotationName is an annotation that can be set + // on an ObjectStore resource to enable the authentication to Azure via DefaultAzureCredential. + // This is meant to be used with inheritFromAzureAD enabled. + UseDefaultAzureCredentialAnnotationName = MetadataNamespace + "/useDefaultAzureCredential" + + // UseDefaultAzureCredentialTrueValue is the value for the annotation + // barmancloud.cnpg.io/useDefaultAzureCredential to enable the DefaultAzureCredentials auth mechanism. + UseDefaultAzureCredentialTrueValue = "true" +) diff --git a/web/docs/object_stores.md b/web/docs/object_stores.md index f1714c93..ea4f9425 100644 --- a/web/docs/object_stores.md +++ b/web/docs/object_stores.md @@ -233,6 +233,7 @@ Barman Cloud supports the following authentication methods: - Storage Account Name + [Access Key](https://learn.microsoft.com/en-us/azure/storage/common/storage-account-keys-manage) - Storage Account Name + [SAS Token](https://learn.microsoft.com/en-us/azure/storage/blobs/sas-service-create) - [Azure AD Workload Identity](https://azure.github.io/azure-workload-identity/docs/introduction.html) +- [DefaultAzureCredential](https://learn.microsoft.com/en-us/azure/developer/go/sdk/authentication/credential-chains#defaultazurecredential-overview) ### Azure AD Workload Identity @@ -252,6 +253,27 @@ spec: [...] ``` +### DefaultAzureCredential + +To authenticate using `DefaultAzureCredential`, set the annotation +`barmancloud.cnpg.io/useDefaultAzureCredential="true"` on the ObjectStore in +conjunction with the `.spec.configuration.inheritFromAzureAD` option: + +```yaml +apiVersion: barmancloud.cnpg.io/v1 +kind: ObjectStore +metadata: + name: azure-store + annotations: + barmancloud.cnpg.io/useDefaultAzureCredential: "true" +spec: + configuration: + destinationPath: "" + azureCredentials: + inheritFromAzureAD: true + [...] +``` + ### Access Key, SAS Token, or Connection String Store credentials in a Kubernetes secret: