Skip to content

Commit af69e45

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

9 files changed

Lines changed: 216 additions & 2 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/go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,3 +93,5 @@ replace k8s.io/component-base => k8s.io/component-base v0.31.14 //allow-merging
9393
replace github.com/rabbitmq/cluster-operator/v2 => github.com/openstack-k8s-operators/rabbitmq-cluster-operator/v2 v2.6.1-0.20250929174222-a0d328fa4dec //allow-merging
9494

9595
replace k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20250627150254-e9823e99808e //allow-merging
96+
97+
replace github.com/openstack-k8s-operators/keystone-operator/api => github.com/Deydra71/keystone-operator/api v0.0.0-20260424093804-00a0ccdc9d20

api/v1beta1/barbican_types.go

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

158+
// ApplicationCredentialSecret - the AC secret barbican is currently
159+
// consuming and protecting with the openstack.org/barbican-ac-consumer
160+
// finalizer. Tracked so the controller can remove its finalizer from the
161+
// old secret when the openstack-operator rotates the reference.
162+
ApplicationCredentialSecret string `json:"applicationCredentialSecret,omitempty"`
163+
158164
// ObservedGeneration - the most recent generation observed for this
159165
// service. If the observed generation is less than the spec generation,
160166
// 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: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,5 @@ replace k8s.io/component-base => k8s.io/component-base v0.31.14 //allow-merging
142142
replace github.com/rabbitmq/cluster-operator/v2 => github.com/openstack-k8s-operators/rabbitmq-cluster-operator/v2 v2.6.1-0.20250929174222-a0d328fa4dec //allow-merging
143143

144144
replace k8s.io/kube-openapi => k8s.io/kube-openapi v0.0.0-20250627150254-e9823e99808e //allow-merging
145+
146+
replace github.com/openstack-k8s-operators/keystone-operator/api => github.com/Deydra71/keystone-operator/api v0.0.0-20260424093804-00a0ccdc9d20

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
github.com/Deydra71/keystone-operator/api v0.0.0-20260424093804-00a0ccdc9d20 h1:iyxfh2SDvQrOrsHItYAE3A3+8Ku9UnzWAq9jnLJDLjg=
2+
github.com/Deydra71/keystone-operator/api v0.0.0-20260424093804-00a0ccdc9d20/go.mod h1:SpO4CL7c5/1HG+61fP6kWhL2+3aqR+5SNatdZueKrz8=
13
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
24
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
35
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
@@ -120,8 +122,6 @@ github.com/openshift/api v0.0.0-20250711200046-c86d80652a9e h1:E1OdwSpqWuDPCedyU
120122
github.com/openshift/api v0.0.0-20250711200046-c86d80652a9e/go.mod h1:Shkl4HanLwDiiBzakv+con/aMGnVE2MAGvoKp5oyYUo=
121123
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20260416122644-5476763a36b6 h1:117Gu9HCSu2tAp579WnCJ9QtnslH2qnPB8UFvn8ZpqE=
122124
github.com/openstack-k8s-operators/infra-operator/apis v0.6.1-0.20260416122644-5476763a36b6/go.mod h1:i7l8cihvFktd/LSuyvL2z6OcwauarQGoVhDMePL4VyI=
123-
github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20260422175310-d957b8482944 h1:C0qDfnVa//1NwYyO6o5EK5RBKohYjldnmbGvj7RTQ2E=
124-
github.com/openstack-k8s-operators/keystone-operator/api v0.6.1-0.20260422175310-d957b8482944/go.mod h1:SpO4CL7c5/1HG+61fP6kWhL2+3aqR+5SNatdZueKrz8=
125125
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260417092244-81c71b39e981 h1:v1viH0gmNb+AXMg/0GxDcj8VUTdjVLotfOIGrNyMxHk=
126126
github.com/openstack-k8s-operators/lib-common/modules/common v0.6.1-0.20260417092244-81c71b39e981/go.mod h1:I/VBXZLdjk8DUGsEbB+Ha72JBFYYntP7Pm2FpEto9K8=
127127
github.com/openstack-k8s-operators/lib-common/modules/openstack v0.6.1-0.20260417092244-81c71b39e981 h1:jN3Kvt+RYUTaL9EXeeeIqRXVjqeNF74SuLTDXmi4X2Y=

internal/barbican/const.go

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

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
@@ -1803,6 +1803,164 @@ var _ = Describe("Barbican controller", func() {
18031803
})
18041804
})
18051805

1806+
When("ApplicationCredential consumer finalizer is managed", func() {
1807+
var (
1808+
acSecretName string
1809+
servicePasswordSecret string
1810+
)
1811+
1812+
BeforeEach(func() {
1813+
servicePasswordSecret = "ac-test-osp-secret" //nolint:gosec // G101
1814+
1815+
DeferCleanup(k8sClient.Delete, ctx,
1816+
CreateBarbicanMessageBusSecret(
1817+
barbicanTest.Instance.Namespace,
1818+
barbicanTest.RabbitmqSecretName,
1819+
),
1820+
)
1821+
DeferCleanup(k8sClient.Delete, ctx,
1822+
CreateBarbicanSecret(
1823+
barbicanTest.Instance.Namespace, servicePasswordSecret))
1824+
1825+
acSecretName = "ac-barbican-a1b2c-secret" //nolint:gosec // G101
1826+
secret := &corev1.Secret{
1827+
ObjectMeta: metav1.ObjectMeta{
1828+
Namespace: barbicanTest.Instance.Namespace,
1829+
Name: acSecretName,
1830+
},
1831+
Data: map[string][]byte{
1832+
keystonev1.ACIDSecretKey: []byte("a1b2ctest-ac-id"),
1833+
keystonev1.ACSecretSecretKey: []byte("test-ac-secret"),
1834+
},
1835+
}
1836+
DeferCleanup(k8sClient.Delete, ctx, secret)
1837+
Expect(k8sClient.Create(ctx, secret)).To(Succeed())
1838+
1839+
spec := GetDefaultBarbicanSpec()
1840+
spec["secret"] = servicePasswordSecret
1841+
spec["simpleCryptoBackendSecret"] = servicePasswordSecret
1842+
spec["auth"] = map[string]any{
1843+
"applicationCredentialSecret": acSecretName,
1844+
}
1845+
DeferCleanup(th.DeleteInstance,
1846+
CreateBarbican(barbicanTest.Instance, spec))
1847+
DeferCleanup(
1848+
mariadb.DeleteDBService,
1849+
mariadb.CreateDBService(
1850+
barbicanTest.Instance.Namespace,
1851+
GetBarbican(barbicanTest.Instance).Spec.DatabaseInstance,
1852+
corev1.ServiceSpec{
1853+
Ports: []corev1.ServicePort{{Port: 3306}}}))
1854+
1855+
DeferCleanup(keystone.DeleteKeystoneAPI,
1856+
keystone.CreateKeystoneAPI(barbicanTest.Instance.Namespace))
1857+
1858+
infra.SimulateTransportURLReady(barbicanTest.BarbicanTransportURL)
1859+
mariadb.SimulateMariaDBAccountCompleted(barbicanTest.BarbicanDatabaseAccount)
1860+
mariadb.SimulateMariaDBDatabaseCompleted(barbicanTest.BarbicanDatabaseName)
1861+
th.SimulateJobSuccess(barbicanTest.BarbicanDBSync)
1862+
keystone.SimulateKeystoneEndpointReady(barbicanTest.BarbicanKeystoneEndpoint)
1863+
})
1864+
1865+
It("should add the consumer finalizer to the AC secret", func() {
1866+
Eventually(func(g Gomega) {
1867+
secret := th.GetSecret(types.NamespacedName{
1868+
Namespace: barbicanTest.Instance.Namespace,
1869+
Name: acSecretName,
1870+
})
1871+
g.Expect(secret.Finalizers).To(
1872+
ContainElement(barbican.ACConsumerFinalizer))
1873+
}, timeout, interval).Should(Succeed())
1874+
})
1875+
1876+
It("should track the consumed AC secret in status", func() {
1877+
Eventually(func(g Gomega) {
1878+
b := GetBarbican(barbicanTest.Instance)
1879+
g.Expect(b.Status.ApplicationCredentialSecret).To(Equal(acSecretName))
1880+
}, timeout, interval).Should(Succeed())
1881+
})
1882+
1883+
It("should move the finalizer from the old to the new secret on rotation", func() {
1884+
// Wait for the initial finalizer to appear
1885+
Eventually(func(g Gomega) {
1886+
secret := th.GetSecret(types.NamespacedName{
1887+
Namespace: barbicanTest.Instance.Namespace,
1888+
Name: acSecretName,
1889+
})
1890+
g.Expect(secret.Finalizers).To(
1891+
ContainElement(barbican.ACConsumerFinalizer))
1892+
}, timeout, interval).Should(Succeed())
1893+
1894+
// Create a new AC secret
1895+
newACSecretName := "ac-barbican-x9y8z-secret" //nolint:gosec // G101
1896+
newSecret := &corev1.Secret{
1897+
ObjectMeta: metav1.ObjectMeta{
1898+
Namespace: barbicanTest.Instance.Namespace,
1899+
Name: newACSecretName,
1900+
},
1901+
Data: map[string][]byte{
1902+
keystonev1.ACIDSecretKey: []byte("x9y8zrotated-ac-id"),
1903+
keystonev1.ACSecretSecretKey: []byte("rotated-ac-secret"),
1904+
},
1905+
}
1906+
DeferCleanup(k8sClient.Delete, ctx, newSecret)
1907+
Expect(k8sClient.Create(ctx, newSecret)).To(Succeed())
1908+
1909+
// Update the Barbican CR to reference the new AC secret
1910+
Eventually(func(g Gomega) {
1911+
b := GetBarbican(barbicanTest.Instance)
1912+
b.Spec.Auth.ApplicationCredentialSecret = newACSecretName
1913+
g.Expect(k8sClient.Update(ctx, b)).Should(Succeed())
1914+
}, timeout, interval).Should(Succeed())
1915+
1916+
// New secret should gain the consumer finalizer
1917+
Eventually(func(g Gomega) {
1918+
secret := th.GetSecret(types.NamespacedName{
1919+
Namespace: barbicanTest.Instance.Namespace,
1920+
Name: newACSecretName,
1921+
})
1922+
g.Expect(secret.Finalizers).To(
1923+
ContainElement(barbican.ACConsumerFinalizer))
1924+
}, timeout, interval).Should(Succeed())
1925+
1926+
// Old secret should lose the consumer finalizer
1927+
Eventually(func(g Gomega) {
1928+
secret := th.GetSecret(types.NamespacedName{
1929+
Namespace: barbicanTest.Instance.Namespace,
1930+
Name: acSecretName,
1931+
})
1932+
g.Expect(secret.Finalizers).NotTo(
1933+
ContainElement(barbican.ACConsumerFinalizer))
1934+
}, timeout, interval).Should(Succeed())
1935+
1936+
// Status should reflect the new secret
1937+
Eventually(func(g Gomega) {
1938+
b := GetBarbican(barbicanTest.Instance)
1939+
g.Expect(b.Status.ApplicationCredentialSecret).To(Equal(newACSecretName))
1940+
}, timeout, interval).Should(Succeed())
1941+
})
1942+
1943+
It("should remove the consumer finalizer from AC secret on CR deletion", func() {
1944+
Eventually(func(g Gomega) {
1945+
secret := th.GetSecret(types.NamespacedName{
1946+
Namespace: barbicanTest.Instance.Namespace,
1947+
Name: acSecretName,
1948+
})
1949+
g.Expect(secret.Finalizers).To(
1950+
ContainElement(barbican.ACConsumerFinalizer))
1951+
}, timeout, interval).Should(Succeed())
1952+
1953+
th.DeleteInstance(GetBarbican(barbicanTest.Instance))
1954+
1955+
secret := th.GetSecret(types.NamespacedName{
1956+
Namespace: barbicanTest.Instance.Namespace,
1957+
Name: acSecretName,
1958+
})
1959+
Expect(secret.Finalizers).NotTo(
1960+
ContainElement(barbican.ACConsumerFinalizer))
1961+
})
1962+
})
1963+
18061964
// Run MariaDBAccount suite tests. these are pre-packaged ginkgo tests
18071965
// that exercise standard account create / update patterns that should be
18081966
// common to all controllers that ensure MariaDBAccount CRs.

0 commit comments

Comments
 (0)