Skip to content

Commit 1d135c9

Browse files
committed
Adding key field to proxyCA config.
1 parent d1837a0 commit 1d135c9

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
@@ -1626,8 +1626,9 @@ user_data_collector_config: {}
16261626

16271627
cr.Spec.OLSConfig.ProxyConfig = &olsv1alpha1.ProxyConfig{
16281628
ProxyURL: "https://proxy.example.com:8080",
1629-
ProxyCACertificateRef: &corev1.LocalObjectReference{
1629+
ProxyCACertificateRef: &olsv1alpha1.ProxyCACertConfigMapRef{
16301630
Name: caConfigMapName,
1631+
// No Key specified - tests backward compatibility
16311632
},
16321633
}
16331634

@@ -1646,6 +1647,12 @@ user_data_collector_config: {}
16461647
Name: caConfigMapName,
16471648
},
16481649
DefaultMode: &defaultVolumeMode,
1650+
Items: []corev1.KeyToPath{
1651+
{
1652+
Key: utils.ProxyCACertFileName,
1653+
Path: utils.ProxyCACertFileName,
1654+
},
1655+
},
16491656
},
16501657
},
16511658
}))
@@ -1665,14 +1672,54 @@ user_data_collector_config: {}
16651672

16661673
cr.Spec.OLSConfig.ProxyConfig = &olsv1alpha1.ProxyConfig{
16671674
ProxyURL: "https://proxy.example.com:8080",
1668-
ProxyCACertificateRef: &corev1.LocalObjectReference{
1675+
ProxyCACertificateRef: &olsv1alpha1.ProxyCACertConfigMapRef{
16691676
Name: caConfigMapName,
1677+
// No Key specified - tests backward compatibility
16701678
},
16711679
}
16721680
_, err = GenerateOLSConfigMap(testReconcilerInstance, ctx, cr)
16731681
Expect(err).To(HaveOccurred())
16741682
Expect(err.Error()).To(ContainSubstring("failed to validate proxy CA certificate"))
16751683
})
1684+
1685+
It("should support custom ConfigMap key for proxy CA certificate", func() {
1686+
customKey := "service-ca.crt"
1687+
proxyCACm.Data = map[string]string{
1688+
customKey: utils.TestCACert,
1689+
}
1690+
err := testReconcilerInstance.Update(ctx, proxyCACm)
1691+
Expect(err).NotTo(HaveOccurred())
1692+
1693+
cr.Spec.OLSConfig.ProxyConfig = &olsv1alpha1.ProxyConfig{
1694+
ProxyURL: "https://proxy.example.com:8080",
1695+
ProxyCACertificateRef: &olsv1alpha1.ProxyCACertConfigMapRef{
1696+
Name: caConfigMapName,
1697+
Key: customKey,
1698+
},
1699+
}
1700+
1701+
// Test OLS ConfigMap has correct path with custom key
1702+
olsCm, err := GenerateOLSConfigMap(testReconcilerInstance, ctx, cr)
1703+
Expect(err).NotTo(HaveOccurred())
1704+
Expect(olsCm.Data[utils.OLSConfigFilename]).To(ContainSubstring(
1705+
fmt.Sprintf("proxy_ca_cert_path: /etc/certs/proxy-ca/%s", customKey)))
1706+
1707+
// Test deployment has Items projection with custom key
1708+
dep, err := GenerateOLSDeployment(testReconcilerInstance, cr)
1709+
Expect(err).NotTo(HaveOccurred())
1710+
1711+
var proxyCAVolume *corev1.Volume
1712+
for i := range dep.Spec.Template.Spec.Volumes {
1713+
if dep.Spec.Template.Spec.Volumes[i].Name == utils.ProxyCACertVolumeName {
1714+
proxyCAVolume = &dep.Spec.Template.Spec.Volumes[i]
1715+
break
1716+
}
1717+
}
1718+
Expect(proxyCAVolume).NotTo(BeNil())
1719+
Expect(proxyCAVolume.ConfigMap.Items).To(HaveLen(1))
1720+
Expect(proxyCAVolume.ConfigMap.Items[0].Key).To(Equal(customKey))
1721+
Expect(proxyCAVolume.ConfigMap.Items[0].Path).To(Equal(customKey))
1722+
})
16761723
})
16771724
})
16781725

internal/controller/appserver/deployment.go

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

279302
volumes = append(volumes, corev1.Volume{
280-
Name: volumeName,
281-
VolumeSource: corev1.VolumeSource{
282-
ConfigMap: &corev1.ConfigMapVolumeSource{
283-
LocalObjectReference: corev1.LocalObjectReference{Name: name},
284-
DefaultMode: &volumeDefaultMode,
285-
},
286-
},
303+
Name: volumeName,
304+
VolumeSource: volumeSource,
287305
})
288306

289307
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)