Skip to content

Commit afae1d8

Browse files
committed
Use RBAC while connecting ovn-controllers to SB database
This patch configures RBAC to access OVN SB databases so that ovn-controllers now have limited access to this DB and will only be able to modify its own data. On the other hand Northd requires "full access" to the SB DB, and to achieve that there is another DB listener created on port 16642 for to be used by northd. More info about OVN RBAC can be found in its documentation at [1]. [1] https://docs.ovn.org/en/latest/tutorials/ovn-rbac.html Related: #1922 Assisted-by: claude-opus-4.6 Signed-off-by: Slawek Kaplonski <skaplons@redhat.com>
1 parent 7285e1e commit afae1d8

6 files changed

Lines changed: 70 additions & 3 deletions

File tree

api/bases/ovn.openstack.org_ovndbclusters.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,12 @@ spec:
428428
description: InternalDBAddress - DB IP address used by other Pods
429429
in the cluster
430430
type: string
431+
internalDbAddressRbacFullAccess:
432+
description: |-
433+
InternalDBAddressRbacFullAccess - DB IP address used by other Pods which
434+
requires full access to the SB db, like e.g. Northd. This is used only
435+
when OVN RBAC for ovn-controllers is used (TLS enabled)
436+
type: string
431437
lastAppliedTopology:
432438
description: LastAppliedTopology - the last applied Topology
433439
properties:

api/v1beta1/ovndbcluster_types.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,11 @@ type OVNDBClusterStatus struct {
168168
// InternalDBAddress - DB IP address used by other Pods in the cluster
169169
InternalDBAddress string `json:"internalDbAddress,omitempty"`
170170

171+
// InternalDBAddressRbacFullAccess - DB IP address used by other Pods which
172+
// requires full access to the SB db, like e.g. Northd. This is used only
173+
// when OVN RBAC for ovn-controllers is used (TLS enabled)
174+
InternalDBAddressRbacFullAccess string `json:"internalDbAddressRbacFullAccess,omitempty"`
175+
171176
// NetworkAttachments status of the deployment pods
172177
NetworkAttachments map[string][]string `json:"networkAttachments,omitempty"`
173178

@@ -236,6 +241,23 @@ func (instance OVNDBCluster) GetInternalEndpoint() (string, error) {
236241
return instance.Status.InternalDBAddress, nil
237242
}
238243

244+
// GetInternalEndpointRbacFullAccess - return the DNS name that openshift coreDNS can resolve
245+
func (instance OVNDBCluster) GetInternalEndpointRbacFullAccess() (string, error) {
246+
if !instance.Spec.TLS.Enabled() {
247+
// if TLS is disabled, this is the same as internalDbAddress
248+
return instance.GetInternalEndpoint()
249+
}
250+
if instance.Spec.DBType != SBDBType {
251+
// if DBType is not SB, this is the same as internalDbAddress
252+
return instance.GetInternalEndpoint()
253+
}
254+
255+
if instance.Status.InternalDBAddressRbacFullAccess == "" {
256+
return "", fmt.Errorf("internal DBEndpoint not ready yet for %s", instance.Spec.DBType)
257+
}
258+
return instance.Status.InternalDBAddressRbacFullAccess, nil
259+
}
260+
239261
// GetExternalEndpoint - return the DNS that openstack dnsmasq can resolve
240262
func (instance OVNDBCluster) GetExternalEndpoint() (string, error) {
241263
if (instance.Spec.NetworkAttachment != "" || instance.Spec.Override.Service != nil) && instance.Status.DBAddress == "" {

config/crd/bases/ovn.openstack.org_ovndbclusters.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,12 @@ spec:
428428
description: InternalDBAddress - DB IP address used by other Pods
429429
in the cluster
430430
type: string
431+
internalDbAddressRbacFullAccess:
432+
description: |-
433+
InternalDBAddressRbacFullAccess - DB IP address used by other Pods which
434+
requires full access to the SB db, like e.g. Northd. This is used only
435+
when OVN RBAC for ovn-controllers is used (TLS enabled)
436+
type: string
431437
lastAppliedTopology:
432438
description: LastAppliedTopology - the last applied Topology
433439
properties:

internal/controller/ovndbcluster_controller.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -721,6 +721,7 @@ func (r *OVNDBClusterReconciler) reconcileNormal(ctx context.Context, instance *
721721
instance.Status.Conditions.MarkTrue(condition.DeploymentReadyCondition, condition.DeploymentReadyMessage)
722722
instance.Status.Conditions.MarkTrue(condition.ExposeServiceReadyCondition, condition.ExposeServiceReadyMessage)
723723
internalDbAddress := []string{}
724+
internalDbAddressRbacFullAccess := []string{}
724725
var svcPort int32
725726
scheme := "tcp"
726727
if instance.Spec.TLS.Enabled() {
@@ -736,6 +737,12 @@ func (r *OVNDBClusterReconciler) reconcileNormal(ctx context.Context, instance *
736737
// TODO: Watch operator.openshift.io resource once cluster domain is customizable
737738
clusterDomain := clusterdns.GetDNSClusterDomain()
738739
internalDbAddress = append(internalDbAddress, fmt.Sprintf("%s:%s.%s.svc.%s:%d", scheme, svc.Name, svc.Namespace, clusterDomain, svcPort))
740+
741+
// if TLS is enabled and DBType is SB, RBAC for ovn-controller is used, so additionally
742+
// set the internalDbAddressRbacFullAccess has to be set
743+
if instance.Spec.TLS.Enabled() && instance.Spec.DBType == ovnv1.SBDBType {
744+
internalDbAddressRbacFullAccess = append(internalDbAddressRbacFullAccess, fmt.Sprintf("%s:%s.%s.svc.%s:%d", scheme, svc.Name, svc.Namespace, clusterDomain, ovndbcluster.DbPortSBRBACFullAccess))
745+
}
739746
}
740747

741748
// Note setting this to the singular headless service address (e.g ssl:ovsdbserver-sb...) "works" but will not
@@ -745,6 +752,9 @@ func (r *OVNDBClusterReconciler) reconcileNormal(ctx context.Context, instance *
745752

746753
// Set DB Address
747754
instance.Status.InternalDBAddress = strings.Join(internalDbAddress, ",")
755+
if len(internalDbAddressRbacFullAccess) > 0 {
756+
instance.Status.InternalDBAddressRbacFullAccess = strings.Join(internalDbAddressRbacFullAccess, ",")
757+
}
748758
if instance.Spec.DBType == ovnv1.SBDBType && (instance.Spec.NetworkAttachment != "" || instance.Spec.Override.Service != nil) {
749759
// This config map will populate the sb db address to edpm, can't use the nb
750760
// If there's no networkAttachments the configMap is not needed

internal/controller/ovnnorthd_controller.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,17 @@ func getInternalEndpoint(
642642
if err != nil {
643643
return "", err
644644
}
645-
internalEndpoint, err := cluster.GetInternalEndpoint()
645+
internalEndpoint := ""
646+
if instance.Spec.TLS.Enabled() && dbType == ovnv1.SBDBType {
647+
// When TLS is enabled, OVN is configured to use RBAC and in that case
648+
// the "regular" internal endpoint is provides limited access to the SB
649+
// for ovn-controllers. Northd howerver needs endpoint with full access
650+
// to the SB db
651+
internalEndpoint, err = cluster.GetInternalEndpointRbacFullAccess()
652+
} else {
653+
internalEndpoint, err = cluster.GetInternalEndpoint()
654+
}
655+
646656
if err != nil {
647657
return "", err
648658
}

test/functional/ovnnorthd_controller_test.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,18 @@ var _ = Describe("OVNNorthd controller", func() {
263263
var ovnNorthdName types.NamespacedName
264264

265265
BeforeEach(func() {
266-
dbs := CreateOVNDBClusters(namespace, map[string][]string{}, 1)
266+
// OVNDBCluster TLS needs these secrets before its StatefulSet exists; use names
267+
// distinct from northd's CABundleSecretName / OvnDbCertSecretName so missing-secret specs stay valid.
268+
DeferCleanup(k8sClient.Delete, ctx, th.CreateCABundleSecret(types.NamespacedName{
269+
Name: OvnDBClusterFuncTLSCaBundleSecretName,
270+
Namespace: namespace,
271+
}))
272+
DeferCleanup(k8sClient.Delete, ctx, th.CreateCertSecret(types.NamespacedName{
273+
Name: OvnDBClusterFuncTLSCertSecretName,
274+
Namespace: namespace,
275+
}))
276+
dbs := CreateTLSOVNDBClustersUsingSecrets(namespace, map[string][]string{}, 1,
277+
OvnDBClusterFuncTLSCaBundleSecretName, OvnDBClusterFuncTLSCertSecretName)
267278
DeferCleanup(DeleteOVNDBClusters, dbs)
268279
spec := GetTLSOVNNorthdSpec()
269280
ovnNorthdName = ovn.CreateOVNNorthd(nil, namespace, spec)
@@ -309,7 +320,7 @@ var _ = Describe("OVNNorthd controller", func() {
309320
)
310321
})
311322

312-
It("creates a StatefulSet with TLS certs attached", func() {
323+
It("creates a StatefulSet with TLS certs attached and DB endpoints set", func() {
313324
DeferCleanup(k8sClient.Delete, ctx, th.CreateCABundleSecret(types.NamespacedName{
314325
Name: CABundleSecretName,
315326
Namespace: namespace,
@@ -345,6 +356,8 @@ var _ = Describe("OVNNorthd controller", func() {
345356
ContainElement(ContainSubstring("--private-key=")),
346357
ContainElement(ContainSubstring("--certificate=")),
347358
ContainElement(ContainSubstring("--ca-cert=")),
359+
ContainElement(ContainSubstring("--ovnnb-db=ssl:ovsdbserver-nb-0."+namespace+".svc.cluster.local:6641")),
360+
ContainElement(ContainSubstring("--ovnsb-db=ssl:ovsdbserver-sb-0."+namespace+".svc.cluster.local:16642")),
348361
))
349362

350363
// Verify metrics container exists and has correct configuration

0 commit comments

Comments
 (0)