Compare commits

...

5 Commits

Author SHA1 Message Date
Martin Hansen
cf8ce5b99e
Merge ea0a7b5698 into 24758e8b90 2026-07-15 15:37:17 -04:00
renovate[bot]
24758e8b90
chore(deps): lock file maintenance (#988)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-15 13:34:21 +02:00
renovate[bot]
88f2e29674
fix(deps): update documentation dependencies to v3.10.2 (#1001)
Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-15 12:16:43 +02:00
renovate[bot]
3813ce8cfd
chore(deps): update dependency cert-manager/cert-manager to v1.21.0 (#1002)
| Package | Update | Change |
|---|---|---|
|
[cert-manager/cert-manager](https://redirect.github.com/cert-manager/cert-manager)
| minor | `v1.20.3` → `v1.21.0` |

Signed-off-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2026-07-15 10:23:14 +02:00
Martin Hansen
ea0a7b5698
Scope barman Secret RBAC
Avoid granting namespace-wide Secret access when ObjectStores do not need credential Secrets.

Ref: #892
Signed-off-by: Martin Hansen <dontbeevilpls@gmail.com>
2026-05-07 15:49:04 +02:00
8 changed files with 655 additions and 618 deletions

View File

@ -60,7 +60,7 @@ func BuildRoleRules(barmanObjects []barmancloudv1.ObjectStore) []rbacv1.PolicyRu
} }
} }
return []rbacv1.PolicyRule{ rules := []rbacv1.PolicyRule{
{ {
APIGroups: []string{ APIGroups: []string{
barmancloudv1.GroupVersion.Group, barmancloudv1.GroupVersion.Group,
@ -87,7 +87,11 @@ func BuildRoleRules(barmanObjects []barmancloudv1.ObjectStore) []rbacv1.PolicyRu
}, },
ResourceNames: barmanObjectsSet.ToSortedList(), ResourceNames: barmanObjectsSet.ToSortedList(),
}, },
{ }
secrets := secretsSet.ToSortedList()
if len(secrets) > 0 {
rules = append(rules, rbacv1.PolicyRule{
APIGroups: []string{ APIGroups: []string{
"", "",
}, },
@ -99,9 +103,11 @@ func BuildRoleRules(barmanObjects []barmancloudv1.ObjectStore) []rbacv1.PolicyRu
"watch", "watch",
"list", "list",
}, },
ResourceNames: secretsSet.ToSortedList(), ResourceNames: secrets,
}, })
} }
return rules
} }
// ObjectStoreNamesFromRole extracts the ObjectStore names referenced // ObjectStoreNamesFromRole extracts the ObjectStore names referenced

View File

@ -78,13 +78,12 @@ var _ = Describe("BuildRoleRules", func() {
Expect(rules[2].ResourceNames).To(ConsistOf("secret-a", "secret-b")) Expect(rules[2].ResourceNames).To(ConsistOf("secret-a", "secret-b"))
}) })
It("should produce rules with empty ResourceNames for empty input", func() { It("should not produce a secrets rule for empty input", func() {
rules := BuildRoleRules(nil) rules := BuildRoleRules(nil)
Expect(rules).To(HaveLen(3)) Expect(rules).To(HaveLen(2))
Expect(rules[0].ResourceNames).To(BeEmpty()) Expect(rules[0].ResourceNames).To(BeEmpty())
Expect(rules[0].ResourceNames).NotTo(BeNil()) Expect(rules[0].ResourceNames).NotTo(BeNil())
Expect(rules[1].ResourceNames).To(BeEmpty()) Expect(rules[1].ResourceNames).To(BeEmpty())
Expect(rules[2].ResourceNames).To(BeEmpty())
}) })
It("should deduplicate secret names across ObjectStores", func() { It("should deduplicate secret names across ObjectStores", func() {
@ -95,6 +94,31 @@ var _ = Describe("BuildRoleRules", func() {
rules := BuildRoleRules(objects) rules := BuildRoleRules(objects)
Expect(rules[2].ResourceNames).To(Equal([]string{"shared-secret"})) Expect(rules[2].ResourceNames).To(Equal([]string{"shared-secret"}))
}) })
It("should not produce a secrets rule when ObjectStores use IAM role inheritance", func() {
objects := []barmancloudv1.ObjectStore{
{
ObjectMeta: metav1.ObjectMeta{
Name: "store-a",
Namespace: "default",
},
Spec: barmancloudv1.ObjectStoreSpec{
Configuration: barmanapi.BarmanObjectStoreConfiguration{
DestinationPath: "s3://bucket/path",
BarmanCredentials: barmanapi.BarmanCredentials{
AWS: &barmanapi.S3Credentials{
InheritFromIAMRole: true,
},
},
},
},
},
}
rules := BuildRoleRules(objects)
Expect(rules).To(HaveLen(2))
Expect(rules[0].ResourceNames).To(Equal([]string{"store-a"}))
Expect(rules[1].ResourceNames).To(Equal([]string{"store-a"}))
})
}) })
var _ = Describe("BuildRole", func() { var _ = Describe("BuildRole", func() {

View File

@ -28,13 +28,17 @@ import (
func CollectSecretNamesFromCredentials(barmanCredentials *barmanapi.BarmanCredentials) []string { func CollectSecretNamesFromCredentials(barmanCredentials *barmanapi.BarmanCredentials) []string {
var references []*machineryapi.SecretKeySelector var references []*machineryapi.SecretKeySelector
if barmanCredentials.AWS != nil { if barmanCredentials.AWS != nil {
references = append( // When using IAM role inheritance, barman-cloud uses the pod
references, // environment credential chain and does not read credential Secrets.
barmanCredentials.AWS.AccessKeyIDReference, if !barmanCredentials.AWS.InheritFromIAMRole {
barmanCredentials.AWS.SecretAccessKeyReference, references = append(
barmanCredentials.AWS.RegionReference, references,
barmanCredentials.AWS.SessionToken, barmanCredentials.AWS.AccessKeyIDReference,
) barmanCredentials.AWS.SecretAccessKeyReference,
barmanCredentials.AWS.RegionReference,
barmanCredentials.AWS.SessionToken,
)
}
} }
if barmanCredentials.Azure != nil { if barmanCredentials.Azure != nil {
// When using default Azure credentials or managed identity, no secrets are required // When using default Azure credentials or managed identity, no secrets are required

View File

@ -57,6 +57,29 @@ var _ = Describe("CollectSecretNamesFromCredentials", func() {
secrets := CollectSecretNamesFromCredentials(credentials) secrets := CollectSecretNamesFromCredentials(credentials)
Expect(secrets).To(BeEmpty()) Expect(secrets).To(BeEmpty())
}) })
It("should return empty list when using InheritFromIAMRole", func() {
credentials := &barmanapi.BarmanCredentials{
AWS: &barmanapi.S3Credentials{
InheritFromIAMRole: true,
AccessKeyIDReference: &machineryapi.SecretKeySelector{
LocalObjectReference: machineryapi.LocalObjectReference{
Name: "aws-secret",
},
Key: "access-key-id",
},
RegionReference: &machineryapi.SecretKeySelector{
LocalObjectReference: machineryapi.LocalObjectReference{
Name: "aws-region",
},
Key: "region",
},
},
}
secrets := CollectSecretNamesFromCredentials(credentials)
Expect(secrets).To(BeEmpty())
})
}) })
Context("when collecting secrets from Azure credentials", func() { Context("when collecting secrets from Azure credentials", func() {

View File

@ -31,8 +31,8 @@ import (
apierrs "k8s.io/apimachinery/pkg/api/errors" apierrs "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/controller-runtime/pkg/client/fake"
"sigs.k8s.io/controller-runtime/pkg/client/interceptor" "sigs.k8s.io/controller-runtime/pkg/client/interceptor"
@ -261,7 +261,7 @@ var _ = Describe("ObjectStoreReconciler", func() {
Expect(result).To(Equal(reconcile.Result{})) Expect(result).To(Equal(reconcile.Result{}))
}) })
It("should produce empty ResourceNames when all ObjectStores are deleted", func() { It("should omit the secrets rule when all ObjectStores are deleted", func() {
store := newTestObjectStore("my-store", "default", "aws-creds") store := newTestObjectStore("my-store", "default", "aws-creds")
role := newLabeledRole("my-cluster", "default", []barmancloudv1.ObjectStore{*store}) role := newLabeledRole("my-cluster", "default", []barmancloudv1.ObjectStore{*store})
@ -291,10 +291,11 @@ var _ = Describe("ObjectStoreReconciler", func() {
Name: "my-cluster-barman-cloud", Name: "my-cluster-barman-cloud",
}, &updatedRole)).To(Succeed()) }, &updatedRole)).To(Succeed())
// All rules should have empty ResourceNames
Expect(updatedRole.Rules[0].ResourceNames).To(BeEmpty()) Expect(updatedRole.Rules[0].ResourceNames).To(BeEmpty())
Expect(updatedRole.Rules[1].ResourceNames).To(BeEmpty()) Expect(updatedRole.Rules[1].ResourceNames).To(BeEmpty())
Expect(updatedRole.Rules[2].ResourceNames).To(BeEmpty()) for _, rule := range updatedRole.Rules {
Expect(rule.Resources).NotTo(Equal([]string{"secrets"}))
}
}) })
It("should return an error when listing Roles fails", func() { It("should return an error when listing Roles fails", func() {

View File

@ -58,7 +58,7 @@ func WithIgnoreExistingResources(ignore bool) InstallOption {
// DefaultVersion is the default version of cert-manager to install. // DefaultVersion is the default version of cert-manager to install.
// //
// renovate: datasource=github-releases depName=cert-manager/cert-manager // renovate: datasource=github-releases depName=cert-manager/cert-manager
const DefaultVersion = "v1.20.3" const DefaultVersion = "v1.21.0"
// Install installs cert-manager using kubectl. // Install installs cert-manager using kubectl.
func Install(ctx context.Context, cl client.Client, opts ...InstallOption) error { func Install(ctx context.Context, cl client.Client, opts ...InstallOption) error {

View File

@ -15,8 +15,8 @@
"typecheck": "tsc" "typecheck": "tsc"
}, },
"dependencies": { "dependencies": {
"@docusaurus/core": "3.10.1", "@docusaurus/core": "3.10.2",
"@docusaurus/preset-classic": "3.10.1", "@docusaurus/preset-classic": "3.10.2",
"@easyops-cn/docusaurus-search-local": "^0.55.0", "@easyops-cn/docusaurus-search-local": "^0.55.0",
"@mdx-js/react": "^3.0.0", "@mdx-js/react": "^3.0.0",
"clsx": "^2.0.0", "clsx": "^2.0.0",
@ -25,9 +25,9 @@
"react-dom": "^19.0.0" "react-dom": "^19.0.0"
}, },
"devDependencies": { "devDependencies": {
"@docusaurus/module-type-aliases": "3.10.1", "@docusaurus/module-type-aliases": "3.10.2",
"@docusaurus/tsconfig": "3.10.1", "@docusaurus/tsconfig": "3.10.2",
"@docusaurus/types": "3.10.1", "@docusaurus/types": "3.10.2",
"typescript": "~6.0.0" "typescript": "~6.0.0"
}, },
"browserslist": { "browserslist": {

File diff suppressed because it is too large Load Diff