Skip to content

Commit 690cc37

Browse files
committed
Adding key field to proxyCA config.
1 parent 63dc243 commit 690cc37

16 files changed

Lines changed: 291 additions & 43 deletions

api/v1alpha1/olsconfig_types.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -505,9 +505,25 @@ type ProxyConfig struct {
505505
// +kubebuilder:validation:Pattern=`^https?://.*$`
506506
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Proxy URL"
507507
ProxyURL string `json:"proxyURL,omitempty"`
508-
// The configmap holding proxy CA certificate
508+
// The configmap and key holding proxy CA certificate.
509+
// The key is optional and defaults to "proxy-ca.crt" for backward compatibility.
510+
// If you use a different key name in your ConfigMap, specify it in the ConfigMapKeySelector.
509511
// +operator-sdk:csv:customresourcedefinitions:type=spec,displayName="Proxy CA Certificate"
510-
ProxyCACertificateRef *corev1.LocalObjectReference `json:"proxyCACertificate,omitempty"`
512+
ProxyCACertificateRef *ProxyCACertConfigMapRef `json:"proxyCACertificate,omitempty"`
513+
}
514+
515+
// ProxyCACertConfigMapRef references a ConfigMap containing the proxy CA certificate.
516+
// Provides backward compatibility by making the key field optional with a default value.
517+
type ProxyCACertConfigMapRef struct {
518+
// Name of the ConfigMap containing the proxy CA certificate
519+
// +kubebuilder:validation:Required
520+
// +required
521+
Name string `json:"name"`
522+
// Key in the ConfigMap that contains the proxy CA certificate.
523+
// Defaults to "proxy-ca.crt" if not specified.
524+
// +kubebuilder:default="proxy-ca.crt"
525+
// +optional
526+
Key string `json:"key,omitempty"`
511527
}
512528

513529
// MCPServer defines the settings for a single MCP server.

api/v1alpha1/zz_generated.deepcopy.go

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

config/crd/bases/ols.openshift.io_olsconfigs.yaml

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4346,19 +4346,24 @@ spec:
43464346
such as LLM providers.
43474347
properties:
43484348
proxyCACertificate:
4349-
description: The configmap holding proxy CA certificate
4349+
description: |-
4350+
The configmap and key holding proxy CA certificate.
4351+
The key is optional and defaults to "proxy-ca.crt" for backward compatibility.
4352+
If you use a different key name in your ConfigMap, specify it in the ConfigMapKeySelector.
43504353
properties:
4351-
name:
4352-
default: ""
4354+
key:
4355+
default: proxy-ca.crt
43534356
description: |-
4354-
Name of the referent.
4355-
This field is effectively required, but due to backwards compatibility is
4356-
allowed to be empty. Instances of this type with an empty value here are
4357-
almost certainly wrong.
4358-
More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
4357+
Key in the ConfigMap that contains the proxy CA certificate.
4358+
Defaults to "proxy-ca.crt" if not specified.
43594359
type: string
4360+
name:
4361+
description: Name of the ConfigMap containing the proxy
4362+
CA certificate
4363+
type: string
4364+
required:
4365+
- name
43604366
type: object
4361-
x-kubernetes-map-type: atomic
43624367
proxyURL:
43634368
description: |-
43644369
Proxy URL, e.g. https://proxy.example.com:8080

internal/controller/appserver/assets.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,12 +181,15 @@ func GenerateOLSConfigMap(r reconciler.Reconciler, ctx context.Context, cr *olsv
181181
ProxyURL: cr.Spec.OLSConfig.ProxyConfig.ProxyURL,
182182
ProxyCACertPath: "",
183183
}
184-
if cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef != nil && cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef.Name != "" {
185-
err := validateCertificateInConfigMap(r, ctx, cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef.Name, utils.ProxyCACertFileName)
184+
proxyCACertRef := cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef
185+
cmName := utils.GetProxyCACertConfigMapName(proxyCACertRef)
186+
if cmName != "" {
187+
certKey := utils.GetProxyCACertKey(proxyCACertRef)
188+
err := validateCertificateInConfigMap(r, ctx, cmName, certKey)
186189
if err != nil {
187-
return nil, fmt.Errorf("failed to validate proxy CA certificate %s: %w", cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef.Name, err)
190+
return nil, fmt.Errorf("failed to validate proxy CA certificate %s: %w", cmName, err)
188191
}
189-
proxyConfig.ProxyCACertPath = path.Join(utils.OLSAppCertsMountRoot, utils.ProxyCACertVolumeName, utils.ProxyCACertFileName)
192+
proxyConfig.ProxyCACertPath = path.Join(utils.OLSAppCertsMountRoot, utils.ProxyCACertVolumeName, certKey)
190193
}
191194
}
192195

internal/controller/appserver/assets_test.go

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1648,8 +1648,9 @@ user_data_collector_config: {}
16481648

16491649
cr.Spec.OLSConfig.ProxyConfig = &olsv1alpha1.ProxyConfig{
16501650
ProxyURL: "https://proxy.example.com:8080",
1651-
ProxyCACertificateRef: &corev1.LocalObjectReference{
1651+
ProxyCACertificateRef: &olsv1alpha1.ProxyCACertConfigMapRef{
16521652
Name: caConfigMapName,
1653+
// No Key specified - tests backward compatibility
16531654
},
16541655
}
16551656

@@ -1668,6 +1669,12 @@ user_data_collector_config: {}
16681669
Name: caConfigMapName,
16691670
},
16701671
DefaultMode: &defaultVolumeMode,
1672+
Items: []corev1.KeyToPath{
1673+
{
1674+
Key: utils.ProxyCACertFileName,
1675+
Path: utils.ProxyCACertFileName,
1676+
},
1677+
},
16711678
},
16721679
},
16731680
}))
@@ -1687,14 +1694,54 @@ user_data_collector_config: {}
16871694

16881695
cr.Spec.OLSConfig.ProxyConfig = &olsv1alpha1.ProxyConfig{
16891696
ProxyURL: "https://proxy.example.com:8080",
1690-
ProxyCACertificateRef: &corev1.LocalObjectReference{
1697+
ProxyCACertificateRef: &olsv1alpha1.ProxyCACertConfigMapRef{
16911698
Name: caConfigMapName,
1699+
// No Key specified - tests backward compatibility
16921700
},
16931701
}
16941702
_, err = GenerateOLSConfigMap(testReconcilerInstance, ctx, cr)
16951703
Expect(err).To(HaveOccurred())
16961704
Expect(err.Error()).To(ContainSubstring("failed to validate proxy CA certificate"))
16971705
})
1706+
1707+
It("should support custom ConfigMap key for proxy CA certificate", func() {
1708+
customKey := "service-ca.crt"
1709+
proxyCACm.Data = map[string]string{
1710+
customKey: utils.TestCACert,
1711+
}
1712+
err := testReconcilerInstance.Update(ctx, proxyCACm)
1713+
Expect(err).NotTo(HaveOccurred())
1714+
1715+
cr.Spec.OLSConfig.ProxyConfig = &olsv1alpha1.ProxyConfig{
1716+
ProxyURL: "https://proxy.example.com:8080",
1717+
ProxyCACertificateRef: &olsv1alpha1.ProxyCACertConfigMapRef{
1718+
Name: caConfigMapName,
1719+
Key: customKey,
1720+
},
1721+
}
1722+
1723+
// Test OLS ConfigMap has correct path with custom key
1724+
olsCm, err := GenerateOLSConfigMap(testReconcilerInstance, ctx, cr)
1725+
Expect(err).NotTo(HaveOccurred())
1726+
Expect(olsCm.Data[utils.OLSConfigFilename]).To(ContainSubstring(
1727+
fmt.Sprintf("proxy_ca_cert_path: /etc/certs/proxy-ca/%s", customKey)))
1728+
1729+
// Test deployment has Items projection with custom key
1730+
dep, err := GenerateOLSDeployment(testReconcilerInstance, cr)
1731+
Expect(err).NotTo(HaveOccurred())
1732+
1733+
var proxyCAVolume *corev1.Volume
1734+
for i := range dep.Spec.Template.Spec.Volumes {
1735+
if dep.Spec.Template.Spec.Volumes[i].Name == utils.ProxyCACertVolumeName {
1736+
proxyCAVolume = &dep.Spec.Template.Spec.Volumes[i]
1737+
break
1738+
}
1739+
}
1740+
Expect(proxyCAVolume).NotTo(BeNil())
1741+
Expect(proxyCAVolume.ConfigMap.Items).To(HaveLen(1))
1742+
Expect(proxyCAVolume.ConfigMap.Items[0].Key).To(Equal(customKey))
1743+
Expect(proxyCAVolume.ConfigMap.Items[0].Path).To(Equal(customKey))
1744+
})
16981745
})
16991746
})
17001747

internal/controller/appserver/deployment.go

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -263,25 +263,43 @@ func GenerateOLSDeployment(r reconciler.Reconciler, cr *olsv1alpha1.OLSConfig) (
263263
// User provided CA certificates - create both volumes and volume mounts in single pass
264264
_ = utils.ForEachExternalConfigMap(cr, func(name, source string) error {
265265
var volumeName, mountPath string
266+
var volumeSource corev1.VolumeSource
267+
266268
switch source {
267269
case "additional-ca":
268270
volumeName = utils.AdditionalCAVolumeName
269271
mountPath = UserCAMountPath
272+
volumeSource = corev1.VolumeSource{
273+
ConfigMap: &corev1.ConfigMapVolumeSource{
274+
LocalObjectReference: corev1.LocalObjectReference{Name: name},
275+
DefaultMode: &volumeDefaultMode,
276+
},
277+
}
270278
case "proxy-ca":
271279
volumeName = utils.ProxyCACertVolumeName
272280
mountPath = path.Join(utils.OLSAppCertsMountRoot, utils.ProxyCACertVolumeName)
281+
// Get the key to use for the certificate
282+
proxyCACertRef := cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef
283+
certKey := utils.GetProxyCACertKey(proxyCACertRef)
284+
volumeSource = corev1.VolumeSource{
285+
ConfigMap: &corev1.ConfigMapVolumeSource{
286+
LocalObjectReference: corev1.LocalObjectReference{Name: name},
287+
DefaultMode: &volumeDefaultMode,
288+
Items: []corev1.KeyToPath{
289+
{
290+
Key: certKey,
291+
Path: certKey, // Mount with same filename as key
292+
},
293+
},
294+
},
295+
}
273296
default:
274297
return nil
275298
}
276299

277300
volumes = append(volumes, corev1.Volume{
278-
Name: volumeName,
279-
VolumeSource: corev1.VolumeSource{
280-
ConfigMap: &corev1.ConfigMapVolumeSource{
281-
LocalObjectReference: corev1.LocalObjectReference{Name: name},
282-
DefaultMode: &volumeDefaultMode,
283-
},
284-
},
301+
Name: volumeName,
302+
VolumeSource: volumeSource,
285303
})
286304

287305
volumeMounts = append(volumeMounts, corev1.VolumeMount{

internal/controller/appserver/reconciler.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,8 +245,15 @@ func reconcileProxyCAConfigMap(r reconciler.Reconciler, ctx context.Context, cr
245245
return nil
246246
}
247247

248+
cmName := utils.GetProxyCACertConfigMapName(cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef)
249+
if cmName == "" {
250+
// no proxy CA certs, skip
251+
r.GetLogger().Info("Proxy CA not configured, reconciliation skipped")
252+
return nil
253+
}
254+
248255
cm := &corev1.ConfigMap{}
249-
err := r.Get(ctx, client.ObjectKey{Name: cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef.Name, Namespace: r.GetNamespace()}, cm)
256+
err := r.Get(ctx, client.ObjectKey{Name: cmName, Namespace: r.GetNamespace()}, cm)
250257
if err != nil {
251258
return fmt.Errorf("%s: %w", utils.ErrGetProxyCACM, err)
252259
}

internal/controller/appserver/reconciler_test.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -981,7 +981,7 @@ var _ = Describe("App server reconciliator", Ordered, func() {
981981
By("Set up a proxy CA cert")
982982
cr.Spec.OLSConfig.ProxyConfig = &olsv1alpha1.ProxyConfig{
983983
ProxyURL: "https://proxy.example.com:8080",
984-
ProxyCACertificateRef: &corev1.LocalObjectReference{
984+
ProxyCACertificateRef: &olsv1alpha1.ProxyCACertConfigMapRef{
985985
Name: cmCACertName,
986986
},
987987
}
@@ -1008,6 +1008,12 @@ var _ = Describe("App server reconciliator", Ordered, func() {
10081008
Name: cmCACertName,
10091009
},
10101010
DefaultMode: &volumeDefaultMode,
1011+
Items: []corev1.KeyToPath{
1012+
{
1013+
Key: utils.ProxyCACertFileName,
1014+
Path: utils.ProxyCACertFileName,
1015+
},
1016+
},
10111017
},
10121018
},
10131019
},

internal/controller/lcore/config.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -635,7 +635,7 @@ func buildLCoreServiceConfig(_ reconciler.Reconciler, cr *olsv1alpha1.OLSConfig)
635635
// color_log: enable colored logs for DEBUG, disable for production (INFO+)
636636
colorLog := logLevel == olsv1alpha1.LogLevelDebug
637637

638-
return map[string]interface{}{
638+
serviceConfig := map[string]interface{}{
639639
"host": "0.0.0.0",
640640
"port": utils.OLSAppServerContainerPort,
641641
"auth_enabled": false,
@@ -649,6 +649,28 @@ func buildLCoreServiceConfig(_ reconciler.Reconciler, cr *olsv1alpha1.OLSConfig)
649649
"tls_key_path": "/etc/certs/lightspeed-tls/tls.key",
650650
},
651651
}
652+
653+
// Add proxy configuration if specified
654+
if cr.Spec.OLSConfig.ProxyConfig != nil {
655+
proxyConfigMap := map[string]interface{}{}
656+
657+
if cr.Spec.OLSConfig.ProxyConfig.ProxyURL != "" {
658+
proxyConfigMap["proxy_url"] = cr.Spec.OLSConfig.ProxyConfig.ProxyURL
659+
}
660+
661+
proxyCACertRef := cr.Spec.OLSConfig.ProxyConfig.ProxyCACertificateRef
662+
cmName := utils.GetProxyCACertConfigMapName(proxyCACertRef)
663+
if cmName != "" {
664+
certKey := utils.GetProxyCACertKey(proxyCACertRef)
665+
proxyConfigMap["proxy_ca_cert_path"] = "/etc/certs/" + utils.ProxyCACertVolumeName + "/" + certKey
666+
}
667+
668+
if len(proxyConfigMap) > 0 {
669+
serviceConfig["proxy_config"] = proxyConfigMap
670+
}
671+
}
672+
673+
return serviceConfig
652674
}
653675

654676
func buildLCoreLlamaStackConfig(_ reconciler.Reconciler, _ *olsv1alpha1.OLSConfig) map[string]interface{} {

0 commit comments

Comments
 (0)