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{
barmancloudv1.GroupVersion.Group,
@ -87,7 +87,11 @@ func BuildRoleRules(barmanObjects []barmancloudv1.ObjectStore) []rbacv1.PolicyRu
},
ResourceNames: barmanObjectsSet.ToSortedList(),
},
{
}
secrets := secretsSet.ToSortedList()
if len(secrets) > 0 {
rules = append(rules, rbacv1.PolicyRule{
APIGroups: []string{
"",
},
@ -99,9 +103,11 @@ func BuildRoleRules(barmanObjects []barmancloudv1.ObjectStore) []rbacv1.PolicyRu
"watch",
"list",
},
ResourceNames: secretsSet.ToSortedList(),
},
ResourceNames: secrets,
})
}
return rules
}
// 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"))
})
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)
Expect(rules).To(HaveLen(3))
Expect(rules).To(HaveLen(2))
Expect(rules[0].ResourceNames).To(BeEmpty())
Expect(rules[0].ResourceNames).NotTo(BeNil())
Expect(rules[1].ResourceNames).To(BeEmpty())
Expect(rules[2].ResourceNames).To(BeEmpty())
})
It("should deduplicate secret names across ObjectStores", func() {
@ -95,6 +94,31 @@ var _ = Describe("BuildRoleRules", func() {
rules := BuildRoleRules(objects)
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() {

View File

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

View File

@ -57,6 +57,29 @@ var _ = Describe("CollectSecretNamesFromCredentials", func() {
secrets := CollectSecretNamesFromCredentials(credentials)
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() {

View File

@ -31,8 +31,8 @@ import (
apierrs "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"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/fake"
"sigs.k8s.io/controller-runtime/pkg/client/interceptor"
@ -261,7 +261,7 @@ var _ = Describe("ObjectStoreReconciler", func() {
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")
role := newLabeledRole("my-cluster", "default", []barmancloudv1.ObjectStore{*store})
@ -291,10 +291,11 @@ var _ = Describe("ObjectStoreReconciler", func() {
Name: "my-cluster-barman-cloud",
}, &updatedRole)).To(Succeed())
// All rules should have empty ResourceNames
Expect(updatedRole.Rules[0].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() {

View File

@ -58,7 +58,7 @@ func WithIgnoreExistingResources(ignore bool) InstallOption {
// DefaultVersion is the default version of cert-manager to install.
//
// 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.
func Install(ctx context.Context, cl client.Client, opts ...InstallOption) error {

View File

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

File diff suppressed because it is too large Load Diff