Skip to content

Commit 777ec81

Browse files
committed
Add AC finalizer management
Signed-off-by: Veronika Fisarova <vfisarov@redhat.com>
1 parent 4e61969 commit 777ec81

8 files changed

Lines changed: 225 additions & 15 deletions

File tree

api/bases/barbican.openstack.org_barbicans.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,13 @@ spec:
840840
status:
841841
description: BarbicanStatus defines the observed state of Barbican
842842
properties:
843+
applicationCredentialSecret:
844+
description: |-
845+
ApplicationCredentialSecret - the AC secret barbican is currently
846+
consuming and protecting with the openstack.org/barbican-ac-consumer
847+
finalizer. Tracked so the controller can remove its finalizer from the
848+
old secret when the openstack-operator rotates the reference.
849+
type: string
843850
barbicanAPIReadyCount:
844851
description: ReadyCount of Barbican API instances
845852
format: int32

api/v1beta1/barbican_types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,12 @@ type BarbicanStatus struct {
153153
// Barbican Database Hostname
154154
DatabaseHostname string `json:"databaseHostname,omitempty"`
155155

156+
// ApplicationCredentialSecret - the AC secret barbican is currently
157+
// consuming and protecting with the openstack.org/barbican-ac-consumer
158+
// finalizer. Tracked so the controller can remove its finalizer from the
159+
// old secret when the openstack-operator rotates the reference.
160+
ApplicationCredentialSecret string `json:"applicationCredentialSecret,omitempty"`
161+
156162
// ObservedGeneration - the most recent generation observed for this
157163
// service. If the observed generation is less than the spec generation,
158164
// then the controller has not processed the latest changes injected by

config/crd/bases/barbican.openstack.org_barbicans.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,13 @@ spec:
840840
status:
841841
description: BarbicanStatus defines the observed state of Barbican
842842
properties:
843+
applicationCredentialSecret:
844+
description: |-
845+
ApplicationCredentialSecret - the AC secret barbican is currently
846+
consuming and protecting with the openstack.org/barbican-ac-consumer
847+
finalizer. Tracked so the controller can remove its finalizer from the
848+
old secret when the openstack-operator rotates the reference.
849+
type: string
843850
barbicanAPIReadyCount:
844851
description: ReadyCount of Barbican API instances
845852
format: int32

go.mod

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,14 @@ require (
1010
github.com/onsi/gomega v1.41.0
1111
github.com/openstack-k8s-operators/barbican-operator/api v0.0.0-00010101000000-000000000000
1212
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20260513130700-78e1a15a8289
13-
github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20260513130126-175a0958de92
13+
github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20260520090027-4d7b7a01c0bf
1414
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260518125357-72bdd580c587
15-
github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20260515134210-2e2a0d06648c
16-
github.com/openstack-k8s-operators/lib-common/modules/test v0.6.1-0.20260515134210-2e2a0d06648c
17-
github.com/openstack-k8s-operators/mariadb-operator/api v0.6.1-0.20260513143847-4b70b899997a
15+
github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20260506154724-30a976ba8ef0
16+
github.com/openstack-k8s-operators/lib-common/modules/test v0.6.1-0.20260518125357-72bdd580c587
17+
github.com/openstack-k8s-operators/mariadb-operator/api v0.6.1-0.20260421135251-4fb605db7d18
1818
go.uber.org/zap v1.28.0
1919
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67
20-
gopkg.in/ini.v1 v1.67.2
20+
gopkg.in/ini.v1 v1.67.1
2121
k8s.io/api v0.31.14
2222
k8s.io/apimachinery v0.31.14
2323
k8s.io/client-go v0.31.14

go.sum

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -120,18 +120,18 @@ github.com/openshift/api v0.0.0-20250711200046-c86d80652a9e h1:E1OdwSpqWuDPCedyU
120120
github.com/openshift/api v0.0.0-20250711200046-c86d80652a9e/go.mod h1:Shkl4HanLwDiiBzakv+con/aMGnVE2MAGvoKp5oyYUo=
121121
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20260513130700-78e1a15a8289 h1:c7jcPJt1jINUqWcYhmpeUDzeesOd0SfrFOpxEHHoJ7c=
122122
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20260513130700-78e1a15a8289/go.mod h1:1FRevwpKwNgNjDcd8Rz+mxlRleFsi7gNS0BC09x+oYE=
123-
github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20260513130126-175a0958de92 h1:9brYhCAbx+Cwfq8cEtn/g4xF0w6FlyM7CSuDqertxNQ=
124-
github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20260513130126-175a0958de92/go.mod h1:/nxao9LzRStCZPOpyY61Sbfzcogy5BrEP5nExUwFYZ0=
123+
github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20260520090027-4d7b7a01c0bf h1:FoKK0zNo48i4ZMFxScupCK/YAmy6Ps4IILz3CK4BCTI=
124+
github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20260520090027-4d7b7a01c0bf/go.mod h1:VNX1Mda2u5+yGxycIyVrgABucitMDR9ct3Lj6ROS92I=
125125
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260518125357-72bdd580c587 h1:p03uEXoSreyu7LpFmb9YyYM8tEx2D2+7qqhLXNWHTq0=
126126
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260518125357-72bdd580c587/go.mod h1:JC04T5G4E/he5ukonV1oCqa0QzFkLv761VbLruVghJM=
127127
github.com/openstack-k8s-operators/lib-common/modules/openstack v0.6.1-0.20260506154724-30a976ba8ef0 h1:kMie+G0aHlGwDHjimjj8AUxTl2R7LGfai/8pev2T+TY=
128128
github.com/openstack-k8s-operators/lib-common/modules/openstack v0.6.1-0.20260506154724-30a976ba8ef0/go.mod h1:7yqbVpg0k0vW+kZks+TMU/cd1ovoejyHfVPWcyGYLHI=
129-
github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20260515134210-2e2a0d06648c h1:yEjjh0YObWmY0lKqrvBOZpStS832nUrOHvRfDc+t3d0=
130-
github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20260515134210-2e2a0d06648c/go.mod h1:tft3oDiN+v6wX3ILPXGUM/gCLJz6QtrPN63hxpJ3E24=
131-
github.com/openstack-k8s-operators/lib-common/modules/test v0.6.1-0.20260515134210-2e2a0d06648c h1:R68ZhKmcepRdiIC7m7pHXSD3Ycayt6RdF2dP6cg3ga4=
132-
github.com/openstack-k8s-operators/lib-common/modules/test v0.6.1-0.20260515134210-2e2a0d06648c/go.mod h1:ZYG9CQe7cOePOKQbenEZFA28kPdkUOe9QKbDRwGhEV0=
133-
github.com/openstack-k8s-operators/mariadb-operator/api v0.6.1-0.20260513143847-4b70b899997a h1:5P4XUoB5s2NcPZiYWV2s7xBDLNJg4kMzJNxRreR65Aw=
134-
github.com/openstack-k8s-operators/mariadb-operator/api v0.6.1-0.20260513143847-4b70b899997a/go.mod h1:WHqmWfERjBKzbWUN9FU6n8p4FXcF9BKSFNklApqYgHw=
129+
github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20260506154724-30a976ba8ef0 h1:wuzSibIT9F/5RbMmxvBVFj6fy2vtKo58nibzmk5L4PM=
130+
github.com/openstack-k8s-operators/lib-common/modules/storage v0.6.1-0.20260506154724-30a976ba8ef0/go.mod h1:tft3oDiN+v6wX3ILPXGUM/gCLJz6QtrPN63hxpJ3E24=
131+
github.com/openstack-k8s-operators/lib-common/modules/test v0.6.1-0.20260518125357-72bdd580c587 h1:jpouKcgs2Kc5z2JHIpvsXMxEonfXLgzX3KswuBoeKQ0=
132+
github.com/openstack-k8s-operators/lib-common/modules/test v0.6.1-0.20260518125357-72bdd580c587/go.mod h1:nLS2oK4pBo756JNN1cPgr44S0X9V11QScgVla89Ojok=
133+
github.com/openstack-k8s-operators/mariadb-operator/api v0.6.1-0.20260421135251-4fb605db7d18 h1:fMMY6pp7+PEkcsdDoodTfJ6ct2RyGI8VB+toVJxxB5w=
134+
github.com/openstack-k8s-operators/mariadb-operator/api v0.6.1-0.20260421135251-4fb605db7d18/go.mod h1:g/xgMnzNHxdTkqnEgAKwVOv75uPN4nuApbkGqSvASvs=
135135
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
136136
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
137137
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -270,8 +270,8 @@ gopkg.in/evanphx/json-patch.v4 v4.12.0 h1:n6jtcsulIzXPJaxegRbvFNNrZDjbij7ny3gmSP
270270
gopkg.in/evanphx/json-patch.v4 v4.12.0/go.mod h1:p8EYWUEYMpynmqDbY58zCKCFZw8pRWMG4EsWvDvM72M=
271271
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
272272
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
273-
gopkg.in/ini.v1 v1.67.2 h1:JtOSMb9OuaCZKr7h5D/h6iii14sK0hLbplTc6frx4Ss=
274-
gopkg.in/ini.v1 v1.67.2/go.mod h1:x/cyOwCgZqOkJoDIJ3c1KNHMo10+nLGAhh+kn3Zizss=
273+
gopkg.in/ini.v1 v1.67.1 h1:tVBILHy0R6e4wkYOn3XmiITt/hEVH4TFMYvAX2Ytz6k=
274+
gopkg.in/ini.v1 v1.67.1/go.mod h1:x/cyOwCgZqOkJoDIJ3c1KNHMo10+nLGAhh+kn3Zizss=
275275
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
276276
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
277277
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

internal/barbican/const.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,6 @@ const (
7373
BarbicanUID int64 = 42403
7474
// BarbicanGID - based on https://github.com/openstack-k8s-operators/tcib/blob/main/container-images/kolla/base/uid_gid_manage.sh
7575
BarbicanGID int64 = 42403
76+
// ACConsumerFinalizer is added to AC secrets that barbican is actively consuming
77+
ACConsumerFinalizer = "openstack.org/barbican-ac-consumer"
7678
)

internal/controller/barbican_controller.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,23 @@ func (r *BarbicanReconciler) reconcileNormal(ctx context.Context, instance *barb
389389
return ctrl.Result{}, err
390390
}
391391

392+
// Manage consumer finalizer, the AC data was already read and rendered to the service config secret
393+
if instance.Spec.Auth.ApplicationCredentialSecret != "" || instance.Status.ApplicationCredentialSecret != "" {
394+
if err := keystonev1.ManageACSecretFinalizer(ctx, helper, instance.Namespace,
395+
instance.Spec.Auth.ApplicationCredentialSecret,
396+
instance.Status.ApplicationCredentialSecret,
397+
barbican.ACConsumerFinalizer); err != nil {
398+
instance.Status.Conditions.Set(condition.FalseCondition(
399+
condition.ServiceConfigReadyCondition,
400+
condition.ErrorReason,
401+
condition.SeverityWarning,
402+
condition.ServiceConfigReadyErrorMessage,
403+
err.Error()))
404+
return ctrl.Result{}, err
405+
}
406+
}
407+
instance.Status.ApplicationCredentialSecret = instance.Spec.Auth.ApplicationCredentialSecret
408+
392409
instance.Status.Conditions.MarkTrue(condition.ServiceConfigReadyCondition, condition.ServiceConfigReadyMessage)
393410

394411
// networks to attach to
@@ -611,6 +628,19 @@ func (r *BarbicanReconciler) reconcileDelete(ctx context.Context, instance *barb
611628
}
612629
}
613630

631+
// Remove consumer finalizer from AC secrets barbican was consuming.
632+
// Check both status and spec to handle the edge case where the reconciler
633+
// crashed after adding the finalizer but before updating the status.
634+
for _, secretName := range []string{
635+
instance.Status.ApplicationCredentialSecret,
636+
instance.Spec.Auth.ApplicationCredentialSecret,
637+
} {
638+
if err := keystonev1.RemoveACSecretConsumerFinalizer(ctx, helper, instance.Namespace,
639+
secretName, barbican.ACConsumerFinalizer); err != nil {
640+
return ctrl.Result{}, err
641+
}
642+
}
643+
614644
// Service is deleted so remove the finalizer.
615645
controllerutil.RemoveFinalizer(instance, helper.GetFinalizer())
616646
Log.Info(fmt.Sprintf("Reconciled Service '%s' delete successfully", instance.Name))

test/functional/barbican_controller_test.go

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,6 +1974,164 @@ var _ = Describe("Barbican controller", func() {
19741974
})
19751975
})
19761976

1977+
When("ApplicationCredential consumer finalizer is managed", func() {
1978+
var (
1979+
acSecretName string
1980+
servicePasswordSecret string
1981+
)
1982+
1983+
BeforeEach(func() {
1984+
servicePasswordSecret = "ac-test-osp-secret" //nolint:gosec // G101
1985+
1986+
DeferCleanup(k8sClient.Delete, ctx,
1987+
CreateBarbicanMessageBusSecret(
1988+
barbicanTest.Instance.Namespace,
1989+
barbicanTest.RabbitmqSecretName,
1990+
),
1991+
)
1992+
DeferCleanup(k8sClient.Delete, ctx,
1993+
CreateBarbicanSecret(
1994+
barbicanTest.Instance.Namespace, servicePasswordSecret))
1995+
1996+
acSecretName = "ac-barbican-a1b2c-secret" //nolint:gosec // G101
1997+
secret := &corev1.Secret{
1998+
ObjectMeta: metav1.ObjectMeta{
1999+
Namespace: barbicanTest.Instance.Namespace,
2000+
Name: acSecretName,
2001+
},
2002+
Data: map[string][]byte{
2003+
keystonev1.ACIDSecretKey: []byte("a1b2ctest-ac-id"),
2004+
keystonev1.ACSecretSecretKey: []byte("test-ac-secret"),
2005+
},
2006+
}
2007+
DeferCleanup(k8sClient.Delete, ctx, secret)
2008+
Expect(k8sClient.Create(ctx, secret)).To(Succeed())
2009+
2010+
spec := GetDefaultBarbicanSpec()
2011+
spec["secret"] = servicePasswordSecret
2012+
spec["simpleCryptoBackendSecret"] = servicePasswordSecret
2013+
spec["auth"] = map[string]any{
2014+
"applicationCredentialSecret": acSecretName,
2015+
}
2016+
DeferCleanup(th.DeleteInstance,
2017+
CreateBarbican(barbicanTest.Instance, spec))
2018+
DeferCleanup(
2019+
mariadb.DeleteDBService,
2020+
mariadb.CreateDBService(
2021+
barbicanTest.Instance.Namespace,
2022+
GetBarbican(barbicanTest.Instance).Spec.DatabaseInstance,
2023+
corev1.ServiceSpec{
2024+
Ports: []corev1.ServicePort{{Port: 3306}}}))
2025+
2026+
DeferCleanup(keystone.DeleteKeystoneAPI,
2027+
keystone.CreateKeystoneAPI(barbicanTest.Instance.Namespace))
2028+
2029+
infra.SimulateTransportURLReady(barbicanTest.BarbicanTransportURL)
2030+
mariadb.SimulateMariaDBAccountCompleted(barbicanTest.BarbicanDatabaseAccount)
2031+
mariadb.SimulateMariaDBDatabaseCompleted(barbicanTest.BarbicanDatabaseName)
2032+
th.SimulateJobSuccess(barbicanTest.BarbicanDBSync)
2033+
keystone.SimulateKeystoneEndpointReady(barbicanTest.BarbicanKeystoneEndpoint)
2034+
})
2035+
2036+
It("should add the consumer finalizer to the AC secret", func() {
2037+
Eventually(func(g Gomega) {
2038+
secret := th.GetSecret(types.NamespacedName{
2039+
Namespace: barbicanTest.Instance.Namespace,
2040+
Name: acSecretName,
2041+
})
2042+
g.Expect(secret.Finalizers).To(
2043+
ContainElement(barbican.ACConsumerFinalizer))
2044+
}, timeout, interval).Should(Succeed())
2045+
})
2046+
2047+
It("should track the consumed AC secret in status", func() {
2048+
Eventually(func(g Gomega) {
2049+
b := GetBarbican(barbicanTest.Instance)
2050+
g.Expect(b.Status.ApplicationCredentialSecret).To(Equal(acSecretName))
2051+
}, timeout, interval).Should(Succeed())
2052+
})
2053+
2054+
It("should move the finalizer from the old to the new secret on rotation", func() {
2055+
// Wait for the initial finalizer to appear
2056+
Eventually(func(g Gomega) {
2057+
secret := th.GetSecret(types.NamespacedName{
2058+
Namespace: barbicanTest.Instance.Namespace,
2059+
Name: acSecretName,
2060+
})
2061+
g.Expect(secret.Finalizers).To(
2062+
ContainElement(barbican.ACConsumerFinalizer))
2063+
}, timeout, interval).Should(Succeed())
2064+
2065+
// Create a new AC secret
2066+
newACSecretName := "ac-barbican-x9y8z-secret" //nolint:gosec // G101
2067+
newSecret := &corev1.Secret{
2068+
ObjectMeta: metav1.ObjectMeta{
2069+
Namespace: barbicanTest.Instance.Namespace,
2070+
Name: newACSecretName,
2071+
},
2072+
Data: map[string][]byte{
2073+
keystonev1.ACIDSecretKey: []byte("x9y8zrotated-ac-id"),
2074+
keystonev1.ACSecretSecretKey: []byte("rotated-ac-secret"),
2075+
},
2076+
}
2077+
DeferCleanup(k8sClient.Delete, ctx, newSecret)
2078+
Expect(k8sClient.Create(ctx, newSecret)).To(Succeed())
2079+
2080+
// Update the Barbican CR to reference the new AC secret
2081+
Eventually(func(g Gomega) {
2082+
b := GetBarbican(barbicanTest.Instance)
2083+
b.Spec.Auth.ApplicationCredentialSecret = newACSecretName
2084+
g.Expect(k8sClient.Update(ctx, b)).Should(Succeed())
2085+
}, timeout, interval).Should(Succeed())
2086+
2087+
// New secret should gain the consumer finalizer
2088+
Eventually(func(g Gomega) {
2089+
secret := th.GetSecret(types.NamespacedName{
2090+
Namespace: barbicanTest.Instance.Namespace,
2091+
Name: newACSecretName,
2092+
})
2093+
g.Expect(secret.Finalizers).To(
2094+
ContainElement(barbican.ACConsumerFinalizer))
2095+
}, timeout, interval).Should(Succeed())
2096+
2097+
// Old secret should lose the consumer finalizer
2098+
Eventually(func(g Gomega) {
2099+
secret := th.GetSecret(types.NamespacedName{
2100+
Namespace: barbicanTest.Instance.Namespace,
2101+
Name: acSecretName,
2102+
})
2103+
g.Expect(secret.Finalizers).NotTo(
2104+
ContainElement(barbican.ACConsumerFinalizer))
2105+
}, timeout, interval).Should(Succeed())
2106+
2107+
// Status should reflect the new secret
2108+
Eventually(func(g Gomega) {
2109+
b := GetBarbican(barbicanTest.Instance)
2110+
g.Expect(b.Status.ApplicationCredentialSecret).To(Equal(newACSecretName))
2111+
}, timeout, interval).Should(Succeed())
2112+
})
2113+
2114+
It("should remove the consumer finalizer from AC secret on CR deletion", func() {
2115+
Eventually(func(g Gomega) {
2116+
secret := th.GetSecret(types.NamespacedName{
2117+
Namespace: barbicanTest.Instance.Namespace,
2118+
Name: acSecretName,
2119+
})
2120+
g.Expect(secret.Finalizers).To(
2121+
ContainElement(barbican.ACConsumerFinalizer))
2122+
}, timeout, interval).Should(Succeed())
2123+
2124+
th.DeleteInstance(GetBarbican(barbicanTest.Instance))
2125+
2126+
secret := th.GetSecret(types.NamespacedName{
2127+
Namespace: barbicanTest.Instance.Namespace,
2128+
Name: acSecretName,
2129+
})
2130+
Expect(secret.Finalizers).NotTo(
2131+
ContainElement(barbican.ACConsumerFinalizer))
2132+
})
2133+
})
2134+
19772135
// Run MariaDBAccount suite tests. these are pre-packaged ginkgo tests
19782136
// that exercise standard account create / update patterns that should be
19792137
// common to all controllers that ensure MariaDBAccount CRs.

0 commit comments

Comments
 (0)