mirror of
https://github.com/cloudnative-pg/plugin-barman-cloud.git
synced 2026-09-06 06:52:21 +02:00
Compare commits
7 Commits
2608cdc5f6
...
e25fdcb8f7
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e25fdcb8f7 | ||
|
|
6d0aeec367 | ||
|
|
ce8179442b | ||
|
|
4632011ea4 | ||
|
|
c1d963973d | ||
|
|
2a12a52211 | ||
|
|
2a70f54ef8 |
14
go.mod
14
go.mod
@ -16,10 +16,10 @@ require (
|
||||
github.com/spf13/viper v1.21.0
|
||||
google.golang.org/grpc v1.82.1
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
k8s.io/api v0.36.2
|
||||
k8s.io/apiextensions-apiserver v0.36.2
|
||||
k8s.io/apimachinery v0.36.2
|
||||
k8s.io/client-go v0.36.2
|
||||
k8s.io/api v0.36.3
|
||||
k8s.io/apiextensions-apiserver v0.36.3
|
||||
k8s.io/apimachinery v0.36.3
|
||||
k8s.io/client-go v0.36.3
|
||||
k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3
|
||||
sigs.k8s.io/controller-runtime v0.24.1
|
||||
sigs.k8s.io/kustomize/api v0.21.1
|
||||
@ -125,11 +125,11 @@ require (
|
||||
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect
|
||||
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
k8s.io/apiserver v0.36.2 // indirect
|
||||
k8s.io/component-base v0.36.2 // indirect
|
||||
k8s.io/apiserver v0.36.3 // indirect
|
||||
k8s.io/component-base v0.36.3 // indirect
|
||||
k8s.io/klog/v2 v2.140.0 // indirect
|
||||
k8s.io/kube-openapi v0.0.0-20260603220949-865597e52e25 // indirect
|
||||
k8s.io/streaming v0.36.2 // indirect
|
||||
k8s.io/streaming v0.36.3 // indirect
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 // indirect
|
||||
sigs.k8s.io/gateway-api v1.6.0 // indirect
|
||||
sigs.k8s.io/json v0.0.0-20250730193827-2d320260d730 // indirect
|
||||
|
||||
28
go.sum
28
go.sum
@ -308,24 +308,24 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
k8s.io/api v0.36.2 h1:TF6YDLIzKfccK7cq9YpTcGX8TJmEkHVRv78DM51fRYY=
|
||||
k8s.io/api v0.36.2/go.mod h1:F4LbMO4brjZYh7yFkXWhynSvtB7YauxV4c+HHkNRGNg=
|
||||
k8s.io/apiextensions-apiserver v0.36.2 h1:3O5gqOj/dt2XWWbpMe+TXWpE9yU6pjM/tXxtHHJT/K4=
|
||||
k8s.io/apiextensions-apiserver v0.36.2/go.mod h1:cL1tBWe8XSaP1H30iWKGo7hf6iAUUUJPEU70dskmAnA=
|
||||
k8s.io/apimachinery v0.36.2 h1:0PE/W/WNy1UX61NLbXY5TMbJ6UwLL6E6lAPkYrKFxbQ=
|
||||
k8s.io/apimachinery v0.36.2/go.mod h1:fvf/HOLXq9RId0rnDIbN1OEBvHXdQbLMM8nu0LcBUf4=
|
||||
k8s.io/apiserver v0.36.2 h1:6vMnkmHZPeBloNkHUhmZYq7Ylv8WIB8xjyEl+eSt26E=
|
||||
k8s.io/apiserver v0.36.2/go.mod h1:9PoQ2ikCytrZyZg11mGhLEF5m8Rgsb5FJmYJ4Wvnl1k=
|
||||
k8s.io/client-go v0.36.2 h1:bfgxmFKc9CgqsgX4xKLAAdmTQlWee7Ob/HlDOrJ5TBI=
|
||||
k8s.io/client-go v0.36.2/go.mod h1:1vgO4OAlfPnoLcb+Rze2GF5rAr14w8qjrYMoyXJzQj0=
|
||||
k8s.io/component-base v0.36.2 h1:Z0VH80O7Ng0HDZnZj3WRR3urEGa0kTwmO8CwEwjVK1w=
|
||||
k8s.io/component-base v0.36.2/go.mod h1:mGfFOA7Gwpdm1VW2cwSQYbiDIlz8GD2WGwH88QSeCyA=
|
||||
k8s.io/api v0.36.3 h1:NxB+05W2UGqXWFXcLO0RB5cnqnUPP5v5sVlaOH0Iz4w=
|
||||
k8s.io/api v0.36.3/go.mod h1:JzLQKqRHC5+I8RVj/lS3lCg0mg6nWI9Fo/Sk3ElxHzg=
|
||||
k8s.io/apiextensions-apiserver v0.36.3 h1:dPmOAPhwTtqb1bTxbFPsy18KHPhktQeO3WUPXunZIB0=
|
||||
k8s.io/apiextensions-apiserver v0.36.3/go.mod h1:KTXFqgXiuw2pRoL+Wpmttqc+up9Xt/GohadPWeLLOa4=
|
||||
k8s.io/apimachinery v0.36.3 h1:PkzMRBRG8joFD8EhCuQAtNPvJlxb82FwplP26HIzvAM=
|
||||
k8s.io/apimachinery v0.36.3/go.mod h1:cTSjBWgPe/6CQyBKzY/hDIRWCQQQeK0mfLbml0UYFHE=
|
||||
k8s.io/apiserver v0.36.3 h1:MGSg2SkdfuytiDEcRylT5mQFmmSsbx90XFUO67Y4bsQ=
|
||||
k8s.io/apiserver v0.36.3/go.mod h1:fVH7zv9EUNUA7Fl7LtDKh8aB9W7u1VQPSGtWV5SjUxg=
|
||||
k8s.io/client-go v0.36.3 h1:M4JdVzXxYcZk4fGpfDdYnxSwhLKWCFoQsHW6t+z8Hfg=
|
||||
k8s.io/client-go v0.36.3/go.mod h1:gcPwr0c87vjjG6HB6pWEqOeuYVoXSsREjzux2j6GF30=
|
||||
k8s.io/component-base v0.36.3 h1:vc/UFvPCkW0irPz84LAodAL1j3f4xktPM6dDJIEheAY=
|
||||
k8s.io/component-base v0.36.3/go.mod h1:hZbNFG+gCMl9EbykDGEu73feKP9/Cq6JsV4pTo9GTO8=
|
||||
k8s.io/klog/v2 v2.140.0 h1:Tf+J3AH7xnUzZyVVXhTgGhEKnFqye14aadWv7bzXdzc=
|
||||
k8s.io/klog/v2 v2.140.0/go.mod h1:o+/RWfJ6PwpnFn7OyAG3QnO47BFsymfEfrz6XyYSSp0=
|
||||
k8s.io/kube-openapi v0.0.0-20260603220949-865597e52e25 h1:mPMaPMpBij2V1Wv/fR+HW124vVGXXvOSS9ver/9yjWs=
|
||||
k8s.io/kube-openapi v0.0.0-20260603220949-865597e52e25/go.mod h1:V/QaCUYDa+0QpcHhVVc5l99Uz56wEMEXBSj9oCDkNDY=
|
||||
k8s.io/streaming v0.36.2 h1:NSKthPPg9UFSKsRauVJUVGH2Dvn8fhKmY4qrMkw/p98=
|
||||
k8s.io/streaming v0.36.2/go.mod h1:z6fV3D+NVkoeqRMtWwlUZK6U17SY/LqNzOxWL6GyR/s=
|
||||
k8s.io/streaming v0.36.3 h1:9rAaqBk0C0Pc7+/fqGekj07NV+/Xrew58p647A0JT8w=
|
||||
k8s.io/streaming v0.36.3/go.mod h1:z6fV3D+NVkoeqRMtWwlUZK6U17SY/LqNzOxWL6GyR/s=
|
||||
k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3 h1:jVkFFVfXdXP74B/zbO3hM3hpSFD0xvhQ5U686DPurkE=
|
||||
k8s.io/utils v0.0.0-20260707023825-cf1189d6abe3/go.mod h1:M2s5JB1lIYP3jzZdorPLHXIPJzt9vv2muW5a6L9DtNM=
|
||||
sigs.k8s.io/apiserver-network-proxy/konnectivity-client v0.34.0 h1:hSfpvjjTQXQY2Fol2CS0QHMNs/WI1MOSGzCm1KhM5ec=
|
||||
|
||||
@ -150,18 +150,25 @@ func (impl LifecycleImplementation) reconcileJob(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
useAzureWorkloadIdentity, err := impl.collectAzureWorkloadIdentityUsage(ctx, pluginConfiguration)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return reconcileJob(ctx, cluster, request, sidecarConfiguration{
|
||||
env: env,
|
||||
certificates: certificates,
|
||||
resources: resources,
|
||||
env: env,
|
||||
certificates: certificates,
|
||||
resources: resources,
|
||||
useAzureWorkloadIdentity: useAzureWorkloadIdentity,
|
||||
})
|
||||
}
|
||||
|
||||
type sidecarConfiguration struct {
|
||||
env []corev1.EnvVar
|
||||
certificates []corev1.VolumeProjection
|
||||
resources corev1.ResourceRequirements
|
||||
additionalArgs []string
|
||||
env []corev1.EnvVar
|
||||
certificates []corev1.VolumeProjection
|
||||
resources corev1.ResourceRequirements
|
||||
additionalArgs []string
|
||||
useAzureWorkloadIdentity bool
|
||||
}
|
||||
|
||||
func reconcileJob(
|
||||
@ -248,11 +255,17 @@ func (impl LifecycleImplementation) reconcilePod(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
useAzureWorkloadIdentity, err := impl.collectAzureWorkloadIdentityUsage(ctx, pluginConfiguration)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return reconcileInstancePod(ctx, cluster, request, pluginConfiguration, sidecarConfiguration{
|
||||
env: env,
|
||||
certificates: certificates,
|
||||
resources: resources,
|
||||
additionalArgs: additionalArgs,
|
||||
env: env,
|
||||
certificates: certificates,
|
||||
resources: resources,
|
||||
additionalArgs: additionalArgs,
|
||||
useAzureWorkloadIdentity: useAzureWorkloadIdentity,
|
||||
})
|
||||
}
|
||||
|
||||
@ -322,6 +335,25 @@ func (impl LifecycleImplementation) collectAdditionalInstanceArgs(
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (impl LifecycleImplementation) collectAzureWorkloadIdentityUsage(
|
||||
ctx context.Context,
|
||||
pluginConfiguration *config.PluginConfiguration,
|
||||
) (bool, error) {
|
||||
for _, objectKey := range pluginConfiguration.GetReferredBarmanObjectsKey() {
|
||||
var objectStore barmancloudv1.ObjectStore
|
||||
if err := impl.Client.Get(ctx, objectKey, &objectStore); err != nil {
|
||||
return false, fmt.Errorf("while getting object store %s: %w", objectKey.String(), err)
|
||||
}
|
||||
|
||||
if objectStore.Spec.Configuration.Azure != nil &&
|
||||
objectStore.Spec.Configuration.Azure.UseDefaultAzureCredentials {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func reconcileInstancePod(
|
||||
ctx context.Context,
|
||||
cluster *cnpgv1.Cluster,
|
||||
@ -400,6 +432,13 @@ func reconcilePodSpec(
|
||||
},
|
||||
)
|
||||
|
||||
if config.useAzureWorkloadIdentity {
|
||||
envs = append(envs, corev1.EnvVar{
|
||||
Name: "AZURE_FEDERATED_TOKEN_FILE",
|
||||
Value: azureFederatedTokenFilePath,
|
||||
})
|
||||
}
|
||||
|
||||
envs = append(envs, config.env...)
|
||||
|
||||
baseProbe := &corev1.Probe{
|
||||
@ -488,6 +527,34 @@ func reconcilePodSpec(
|
||||
spec.Volumes = removeVolume(spec.Volumes, barmanCertificatesVolumeName)
|
||||
}
|
||||
|
||||
if config.useAzureWorkloadIdentity {
|
||||
sidecarTemplate.VolumeMounts = ensureVolumeMount(
|
||||
sidecarTemplate.VolumeMounts,
|
||||
corev1.VolumeMount{
|
||||
Name: azureFederatedTokenVolumeName,
|
||||
MountPath: azureFederatedTokenMountPath,
|
||||
ReadOnly: true,
|
||||
},
|
||||
)
|
||||
|
||||
spec.Volumes = ensureVolume(spec.Volumes, corev1.Volume{
|
||||
Name: azureFederatedTokenVolumeName,
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Projected: &corev1.ProjectedVolumeSource{
|
||||
Sources: []corev1.VolumeProjection{
|
||||
{
|
||||
ServiceAccountToken: &corev1.ServiceAccountTokenProjection{
|
||||
Path: azureFederatedTokenFileName,
|
||||
Audience: azureFederatedTokenAudience,
|
||||
ExpirationSeconds: ptr.To[int64](azureFederatedTokenExpirationSeconds),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if err := injectPluginSidecarPodSpec(spec, &sidecarTemplate, mainContainerName); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -495,6 +562,15 @@ func reconcilePodSpec(
|
||||
return nil
|
||||
}
|
||||
|
||||
const (
|
||||
azureFederatedTokenVolumeName = "azure-identity-token"
|
||||
azureFederatedTokenMountPath = "/var/run/secrets/azure/tokens"
|
||||
azureFederatedTokenFileName = "azure-identity-token"
|
||||
azureFederatedTokenFilePath = azureFederatedTokenMountPath + "/" + azureFederatedTokenFileName
|
||||
azureFederatedTokenAudience = "api://AzureADTokenExchange"
|
||||
azureFederatedTokenExpirationSeconds = 3600
|
||||
)
|
||||
|
||||
// TODO: move to machinery once the logic is finalized
|
||||
|
||||
// InjectPluginVolumePodSpec injects the plugin volume into a CNPG Pod spec.
|
||||
|
||||
@ -22,6 +22,7 @@ package operator
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
barmanapi "github.com/cloudnative-pg/barman-cloud/pkg/api"
|
||||
cnpgv1 "github.com/cloudnative-pg/cloudnative-pg/api/v1"
|
||||
"github.com/cloudnative-pg/cloudnative-pg/pkg/utils"
|
||||
"github.com/cloudnative-pg/cnpg-i/pkg/lifecycle"
|
||||
@ -517,6 +518,134 @@ var _ = Describe("LifecycleImplementation", func() {
|
||||
Expect(err).To(HaveOccurred())
|
||||
})
|
||||
})
|
||||
|
||||
Describe("collectAzureWorkloadIdentityUsage", func() {
|
||||
It("returns true when any referred object store uses default Azure credentials", func(ctx SpecContext) {
|
||||
ns := "test-ns"
|
||||
cluster := &cnpgv1.Cluster{ObjectMeta: metav1.ObjectMeta{Name: "c", Namespace: ns}}
|
||||
pc := &config.PluginConfiguration{
|
||||
Cluster: cluster,
|
||||
BarmanObjectName: "primary-store",
|
||||
RecoveryBarmanObjectName: "recovery-store",
|
||||
}
|
||||
primaryStore := &barmancloudv1.ObjectStore{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: pc.BarmanObjectName, Namespace: ns},
|
||||
Spec: barmancloudv1.ObjectStoreSpec{
|
||||
Configuration: barmanapi.BarmanObjectStoreConfiguration{
|
||||
BarmanCredentials: barmanapi.BarmanCredentials{
|
||||
Azure: &barmanapi.AzureCredentials{UseDefaultAzureCredentials: true},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
recoveryStore := &barmancloudv1.ObjectStore{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: pc.RecoveryBarmanObjectName, Namespace: ns},
|
||||
}
|
||||
cli := buildClientFunc(primaryStore, recoveryStore).Build()
|
||||
|
||||
impl := LifecycleImplementation{Client: cli}
|
||||
useWorkloadIdentity, err := impl.collectAzureWorkloadIdentityUsage(ctx, pc)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(useWorkloadIdentity).To(BeTrue())
|
||||
})
|
||||
|
||||
It("returns false when none of the referred object stores use default Azure credentials", func(ctx SpecContext) {
|
||||
ns := "test-ns"
|
||||
cluster := &cnpgv1.Cluster{ObjectMeta: metav1.ObjectMeta{Name: "c", Namespace: ns}}
|
||||
pc := &config.PluginConfiguration{
|
||||
Cluster: cluster,
|
||||
BarmanObjectName: "primary-store",
|
||||
}
|
||||
primaryStore := &barmancloudv1.ObjectStore{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: pc.BarmanObjectName, Namespace: ns},
|
||||
Spec: barmancloudv1.ObjectStoreSpec{
|
||||
Configuration: barmanapi.BarmanObjectStoreConfiguration{
|
||||
BarmanCredentials: barmanapi.BarmanCredentials{
|
||||
Azure: &barmanapi.AzureCredentials{InheritFromAzureAD: true},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
cli := buildClientFunc(primaryStore).Build()
|
||||
|
||||
impl := LifecycleImplementation{Client: cli}
|
||||
useWorkloadIdentity, err := impl.collectAzureWorkloadIdentityUsage(ctx, pc)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(useWorkloadIdentity).To(BeFalse())
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
var _ = Describe("reconcilePodSpec", func() {
|
||||
It("injects the Azure federated token volume and env when workload identity is enabled", func() {
|
||||
cluster := &cnpgv1.Cluster{ObjectMeta: metav1.ObjectMeta{Name: "cluster-1", Namespace: "ns-1"}}
|
||||
spec := &corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
Name: "postgres",
|
||||
Env: []corev1.EnvVar{
|
||||
{Name: "AZURE_CLIENT_ID", Value: "client-id"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err := reconcilePodSpec(
|
||||
cluster,
|
||||
spec,
|
||||
"postgres",
|
||||
corev1.Container{Args: []string{"instance"}},
|
||||
sidecarConfiguration{useAzureWorkloadIdentity: true},
|
||||
)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(spec.Volumes).To(ContainElement(HaveField("Name", azureFederatedTokenVolumeName)))
|
||||
Expect(spec.InitContainers).To(HaveLen(1))
|
||||
Expect(spec.InitContainers[0].Env).To(ContainElement(corev1.EnvVar{
|
||||
Name: "AZURE_FEDERATED_TOKEN_FILE",
|
||||
Value: azureFederatedTokenFilePath,
|
||||
}))
|
||||
Expect(spec.InitContainers[0].Env).To(ContainElement(corev1.EnvVar{
|
||||
Name: "AZURE_CLIENT_ID",
|
||||
Value: "client-id",
|
||||
}))
|
||||
Expect(spec.InitContainers[0].VolumeMounts).To(ContainElement(corev1.VolumeMount{
|
||||
Name: azureFederatedTokenVolumeName,
|
||||
MountPath: azureFederatedTokenMountPath,
|
||||
ReadOnly: true,
|
||||
}))
|
||||
})
|
||||
|
||||
It("does not override an existing federated token file env", func() {
|
||||
cluster := &cnpgv1.Cluster{ObjectMeta: metav1.ObjectMeta{Name: "cluster-1", Namespace: "ns-1"}}
|
||||
spec := &corev1.PodSpec{
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
Name: "postgres",
|
||||
Env: []corev1.EnvVar{
|
||||
{Name: "AZURE_FEDERATED_TOKEN_FILE", Value: "/custom/token"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
err := reconcilePodSpec(
|
||||
cluster,
|
||||
spec,
|
||||
"postgres",
|
||||
corev1.Container{Args: []string{"instance"}},
|
||||
sidecarConfiguration{useAzureWorkloadIdentity: true},
|
||||
)
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(spec.InitContainers).To(HaveLen(1))
|
||||
Expect(spec.InitContainers[0].Env).To(ContainElement(corev1.EnvVar{
|
||||
Name: "AZURE_FEDERATED_TOKEN_FILE",
|
||||
Value: "/custom/token",
|
||||
}))
|
||||
Expect(spec.InitContainers[0].Env).NotTo(ContainElement(corev1.EnvVar{
|
||||
Name: "AZURE_FEDERATED_TOKEN_FILE",
|
||||
Value: azureFederatedTokenFilePath,
|
||||
}))
|
||||
})
|
||||
})
|
||||
|
||||
var _ = Describe("Volume utilities", func() {
|
||||
|
||||
@ -121,8 +121,8 @@ func newS3ClientDeployment(namespace string) *appsv1.Deployment {
|
||||
{
|
||||
Name: s3ClientName,
|
||||
// renovate: datasource=docker depName=amazon/aws-cli versioning=docker
|
||||
// Version: 2.36.3
|
||||
Image: "docker.io/amazon/aws-cli@sha256:bdd02067a00c354684086071b475955c54caa7bd88b851aac99a51326fe19652",
|
||||
// Version: 2.36.7
|
||||
Image: "docker.io/amazon/aws-cli@sha256:5b76c069e37cfa091ec6398dc683c09e0c9ef8ae2e557b0a36d931df34011227",
|
||||
Command: []string{"sleep", "infinity"},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
|
||||
@ -272,9 +272,10 @@ flow, which uses [`DefaultAzureCredential`](https://learn.microsoft.com/en-us/py
|
||||
to automatically discover and use available credentials in the following order:
|
||||
|
||||
1. **Environment Variables** — `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, and `AZURE_TENANT_ID` for Service Principal authentication
|
||||
2. **Managed Identity** — Uses the managed identity assigned to the pod
|
||||
3. **Azure CLI** — Uses credentials from the Azure CLI if available
|
||||
4. **Azure PowerShell** — Uses credentials from Azure PowerShell if available
|
||||
2. **Workload Identity** — Uses `AZURE_CLIENT_ID`, `AZURE_TENANT_ID`, and a federated service account token
|
||||
3. **Managed Identity** — Uses the managed identity assigned to the pod
|
||||
4. **Azure CLI** — Uses credentials from the Azure CLI if available
|
||||
5. **Azure PowerShell** — Uses credentials from Azure PowerShell if available
|
||||
|
||||
This approach is particularly useful for getting started with development and testing; it allows
|
||||
the SDK to attempt multiple authentication mechanisms seamlessly across different environments.
|
||||
@ -295,6 +296,30 @@ spec:
|
||||
[...]
|
||||
```
|
||||
|
||||
When `useDefaultAzureCredentials: true` is set, the plugin sidecar projects a
|
||||
service account token with the Azure workload identity audience and exposes it
|
||||
as `AZURE_FEDERATED_TOKEN_FILE`. If your platform does not already inject
|
||||
`AZURE_CLIENT_ID` and `AZURE_TENANT_ID`, you can provide them through
|
||||
`.spec.instanceSidecarConfiguration.env`:
|
||||
|
||||
```yaml
|
||||
apiVersion: barmancloud.cnpg.io/v1
|
||||
kind: ObjectStore
|
||||
metadata:
|
||||
name: azure-store
|
||||
spec:
|
||||
configuration:
|
||||
destinationPath: "<destination path here>"
|
||||
azureCredentials:
|
||||
useDefaultAzureCredentials: true
|
||||
instanceSidecarConfiguration:
|
||||
env:
|
||||
- name: AZURE_CLIENT_ID
|
||||
value: "<managed-identity-client-id>"
|
||||
- name: AZURE_TENANT_ID
|
||||
value: "<tenant-id>"
|
||||
```
|
||||
|
||||
### Access Key, SAS Token, or Connection String
|
||||
|
||||
Store credentials in a Kubernetes secret:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user