Skip to content

Commit baafb49

Browse files
Merge pull request #303 from chiragkyal/istio-clusterID
CM-680: [istio-csr] Enable multi-cluster support with clusterID
2 parents 4185654 + e9c19ab commit baafb49

File tree

12 files changed

+419
-37
lines changed

12 files changed

+419
-37
lines changed

api/operator/v1alpha1/istiocsr_types.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,12 @@ type IstiodTLSConfig struct {
212212
// ServerConfig is for configuring the server endpoint used by istio
213213
// for obtaining the certificates.
214214
type ServerConfig struct {
215+
// clusterID is the istio cluster ID to verify incoming CSRs.
216+
// +kubebuilder:default:="Kubernetes"
217+
// +kubebuilder:validation:Optional
218+
// +optional
219+
ClusterID string `json:"clusterID,omitempty"`
220+
215221
// port to serve istio-csr gRPC service.
216222
// +kubebuilder:default:=443
217223
// +kubebuilder:validation:XValidation:rule="oldSelf == 0 || self == oldSelf",message="port is immutable once set"

bundle/manifests/operator.openshift.io_istiocsrs.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,6 +1221,11 @@ spec:
12211221
server is for configuring the server endpoint used by istio
12221222
for obtaining the certificates.
12231223
properties:
1224+
clusterID:
1225+
default: Kubernetes
1226+
description: clusterID is the istio cluster ID to verify incoming
1227+
CSRs.
1228+
type: string
12241229
port:
12251230
default: 443
12261231
description: port to serve istio-csr gRPC service.

config/crd/bases/operator.openshift.io_istiocsrs.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1221,6 +1221,11 @@ spec:
12211221
server is for configuring the server endpoint used by istio
12221222
for obtaining the certificates.
12231223
properties:
1224+
clusterID:
1225+
default: Kubernetes
1226+
description: clusterID is the istio cluster ID to verify incoming
1227+
CSRs.
1228+
type: string
12241229
port:
12251230
default: 443
12261231
description: port to serve istio-csr gRPC service.

pkg/controller/istiocsr/deployments.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@ func updatePodTemplateLabels(deployment *appsv1.Deployment, resourceLabels map[s
139139

140140
func updateArgList(deployment *appsv1.Deployment, istiocsr *v1alpha1.IstioCSR) {
141141
istiocsrConfigs := istiocsr.Spec.IstioCSRConfig
142+
// Default clusterID to "Kubernetes" if not provided.
143+
clusterID := "Kubernetes"
144+
if istiocsrConfigs.Server != nil && istiocsrConfigs.Server.ClusterID != "" {
145+
clusterID = istiocsrConfigs.Server.ClusterID
146+
}
142147
args := []string{
143148
fmt.Sprintf("--log-level=%d", istiocsrConfigs.LogLevel),
144149
fmt.Sprintf("--log-format=%s", istiocsrConfigs.LogFormat),
@@ -152,7 +157,7 @@ func updateArgList(deployment *appsv1.Deployment, istiocsr *v1alpha1.IstioCSR) {
152157
fmt.Sprintf("--serving-certificate-dns-names=cert-manager-istio-csr.%s.svc", istiocsr.GetNamespace()),
153158
fmt.Sprintf("--serving-certificate-duration=%.0fm", istiocsrConfigs.IstiodTLSConfig.CertificateDuration.Minutes()),
154159
fmt.Sprintf("--trust-domain=%s", istiocsrConfigs.IstiodTLSConfig.TrustDomain),
155-
"--cluster-id=Kubernetes",
160+
fmt.Sprintf("--cluster-id=%s", clusterID),
156161
fmt.Sprintf("--max-client-certificate-duration=%.0fm", istiocsrConfigs.IstiodTLSConfig.MaxCertificateDuration.Minutes()),
157162
"--serving-address=0.0.0.0:6443",
158163
fmt.Sprintf("--serving-certificate-key-size=%d", istiocsrConfigs.IstiodTLSConfig.PrivateKeySize),

pkg/controller/istiocsr/deployments_test.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ package istiocsr
22

33
import (
44
"context"
5+
"fmt"
6+
"slices"
57
"testing"
68

79
appsv1 "k8s.io/api/apps/v1"
@@ -736,3 +738,81 @@ func TestCreateOrApplyDeployments(t *testing.T) {
736738
})
737739
}
738740
}
741+
742+
func TestUpdateArgList(t *testing.T) {
743+
tests := []struct {
744+
name string
745+
updateIstioCSR func(*v1alpha1.IstioCSR)
746+
expectedArgs map[string]string // key is arg name (without --), value is expected value
747+
}{
748+
{
749+
name: "clusterID not provided should default to Kubernetes",
750+
updateIstioCSR: func(istiocsr *v1alpha1.IstioCSR) {
751+
// Server config is nil, so clusterID should default
752+
},
753+
expectedArgs: map[string]string{
754+
"cluster-id": "Kubernetes",
755+
},
756+
},
757+
{
758+
name: "clusterID empty string should default to Kubernetes",
759+
updateIstioCSR: func(istiocsr *v1alpha1.IstioCSR) {
760+
istiocsr.Spec.IstioCSRConfig.Server = &v1alpha1.ServerConfig{
761+
ClusterID: "",
762+
}
763+
},
764+
expectedArgs: map[string]string{
765+
"cluster-id": "Kubernetes",
766+
},
767+
},
768+
{
769+
name: "clusterID provided should use custom value",
770+
updateIstioCSR: func(istiocsr *v1alpha1.IstioCSR) {
771+
istiocsr.Spec.IstioCSRConfig.Server = &v1alpha1.ServerConfig{
772+
ClusterID: "cluster-123_dev.local",
773+
}
774+
},
775+
expectedArgs: map[string]string{
776+
"cluster-id": "cluster-123_dev.local",
777+
},
778+
},
779+
}
780+
781+
for _, tt := range tests {
782+
t.Run(tt.name, func(t *testing.T) {
783+
deployment := testDeployment()
784+
istiocsr := testIstioCSR()
785+
if tt.updateIstioCSR != nil {
786+
tt.updateIstioCSR(istiocsr)
787+
}
788+
789+
updateArgList(deployment, istiocsr)
790+
791+
// Find the istio-csr container and check its arguments
792+
var containerArgs []string
793+
for _, container := range deployment.Spec.Template.Spec.Containers {
794+
if container.Name == istiocsrContainerName {
795+
containerArgs = container.Args
796+
break
797+
}
798+
}
799+
800+
if len(containerArgs) == 0 {
801+
t.Fatalf("Expected container args to be set, but got empty args")
802+
}
803+
804+
// Verify each expected argument
805+
for argName, expectedValue := range tt.expectedArgs {
806+
expectedArg := fmt.Sprintf("--%s=%s", argName, expectedValue)
807+
if !containsArg(containerArgs, expectedArg) {
808+
t.Errorf("Expected to find argument %q in container args, but it was not found. Args: %v", expectedArg, containerArgs)
809+
}
810+
}
811+
})
812+
}
813+
}
814+
815+
// containsArg checks if the given argument is present in the args list
816+
func containsArg(args []string, targetArg string) bool {
817+
return slices.Contains(args, targetArg)
818+
}

pkg/operator/applyconfigurations/operator/v1alpha1/serverconfig.go

Lines changed: 10 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

test/e2e/config_template.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ type CertificateConfig struct {
2525
type IstioCSRGRPCurlJobConfig struct {
2626
CertificateSigningRequest string
2727
IstioCSRStatus v1alpha1.IstioCSRStatus
28+
ClusterID string
29+
JobName string
2830
}
2931

3032
// replaceWithTemplate puts field values from a template struct

0 commit comments

Comments
 (0)