Skip to content

Commit 614ef62

Browse files
committed
Wire TLS security profile through operator to service config.
Propagate the CR tlsSecurityProfile into generated olsconfig.yaml (with Intermediate defaults) so service endpoint TLS follows operator/user configuration, and add appserver coverage for default, modern, and custom profiles. Made-with: Cursor
1 parent c083ce9 commit 614ef62

3 files changed

Lines changed: 114 additions & 0 deletions

File tree

internal/controller/appserver/assets.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ import (
88
"slices"
99
"strings"
1010

11+
configv1 "github.com/openshift/api/config/v1"
12+
1113
"github.com/openshift/lightspeed-operator/internal/controller/reconciler"
14+
utiltls "github.com/openshift/lightspeed-operator/internal/tls"
1215

1316
monv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
1417
corev1 "k8s.io/api/core/v1"
@@ -237,6 +240,17 @@ func GenerateOLSConfigMap(r reconciler.Reconciler, ctx context.Context, cr *olsv
237240
ProxyConfig: proxyConfig,
238241
}
239242

243+
tlsProfileType := utiltls.DefaultTLSProfileType
244+
if cr.Spec.OLSConfig.TLSSecurityProfile != nil && cr.Spec.OLSConfig.TLSSecurityProfile.Type != "" {
245+
tlsProfileType = cr.Spec.OLSConfig.TLSSecurityProfile.Type
246+
}
247+
tlsProfileSpec := utiltls.GetTLSProfileSpec(cr.Spec.OLSConfig.TLSSecurityProfile)
248+
olsConfig.TLSSecurityProfile = &utils.TLSSecurityProfileConfig{
249+
ProfileType: serviceTLSProfileType(tlsProfileType),
250+
MinTLSVersion: utiltls.MinTLSVersion(tlsProfileSpec),
251+
Ciphers: utiltls.TLSCiphers(tlsProfileSpec),
252+
}
253+
240254
if cr.Spec.OLSConfig.QuotaHandlersConfig != nil {
241255
olsConfig.QuotaHandlersConfig = &utils.QuotaHandlersConfig{
242256
Storage: postgresCacheConfig(r, cr),
@@ -740,6 +754,21 @@ func GenerateMetricsReaderSecret(r reconciler.Reconciler, cr *olsv1alpha1.OLSCon
740754
return secret, nil
741755
}
742756

757+
func serviceTLSProfileType(profileType configv1.TLSProfileType) string {
758+
switch profileType {
759+
case configv1.TLSProfileOldType:
760+
return "OldType"
761+
case configv1.TLSProfileIntermediateType:
762+
return "IntermediateType"
763+
case configv1.TLSProfileModernType:
764+
return "ModernType"
765+
case configv1.TLSProfileCustomType:
766+
return "Custom"
767+
default:
768+
return "IntermediateType"
769+
}
770+
}
771+
743772
func getQueryFilters(cr *olsv1alpha1.OLSConfig) []utils.QueryFilters {
744773
if cr.Spec.OLSConfig.QueryFilters == nil {
745774
return nil

internal/controller/appserver/assets_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
. "github.com/onsi/ginkgo/v2"
99
. "github.com/onsi/gomega"
1010
. "github.com/onsi/gomega/gstruct"
11+
configv1 "github.com/openshift/api/config/v1"
1112
monv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
1213
networkingv1 "k8s.io/api/networking/v1"
1314

@@ -104,6 +105,11 @@ var _ = Describe("App server assets", func() {
104105
TLSCertificatePath: path.Join(utils.OLSAppCertsMountRoot, utils.OLSCertsSecretName, "tls.crt"),
105106
TLSKeyPath: path.Join(utils.OLSAppCertsMountRoot, utils.OLSCertsSecretName, "tls.key"),
106107
},
108+
TLSSecurityProfile: &utils.TLSSecurityProfileConfig{
109+
ProfileType: "IntermediateType",
110+
MinTLSVersion: string(configv1.TLSProfiles[configv1.TLSProfileIntermediateType].MinTLSVersion),
111+
Ciphers: configv1.TLSProfiles[configv1.TLSProfileIntermediateType].Ciphers,
112+
},
107113
ReferenceContent: utils.ReferenceContent{
108114
EmbeddingsModelPath: "/app-root/embeddings_model",
109115
Indexes: []utils.ReferenceIndex{
@@ -154,6 +160,48 @@ var _ = Describe("App server assets", func() {
154160
utils.DeleteTelemetryPullSecret(ctx, k8sClient)
155161
})
156162

163+
It("should generate configmap with modern TLS security profile", func() {
164+
cr.Spec.OLSConfig.TLSSecurityProfile = &configv1.TLSSecurityProfile{
165+
Type: configv1.TLSProfileModernType,
166+
}
167+
cm, err := GenerateOLSConfigMap(testReconcilerInstance, context.TODO(), cr)
168+
Expect(err).NotTo(HaveOccurred())
169+
170+
var olsConfigMap map[string]interface{}
171+
err = yaml.Unmarshal([]byte(cm.Data[utils.OLSConfigFilename]), &olsConfigMap)
172+
Expect(err).NotTo(HaveOccurred())
173+
Expect(olsConfigMap).To(HaveKeyWithValue("ols_config", HaveKeyWithValue("tlsSecurityProfile", MatchKeys(Options(IgnoreExtras), Keys{
174+
"type": Equal("ModernType"),
175+
"minTLSVersion": Equal(string(configv1.TLSProfiles[configv1.TLSProfileModernType].MinTLSVersion)),
176+
}))))
177+
})
178+
179+
It("should generate configmap with custom TLS security profile", func() {
180+
cr.Spec.OLSConfig.TLSSecurityProfile = &configv1.TLSSecurityProfile{
181+
Type: configv1.TLSProfileCustomType,
182+
Custom: &configv1.CustomTLSProfile{
183+
TLSProfileSpec: configv1.TLSProfileSpec{
184+
MinTLSVersion: configv1.VersionTLS13,
185+
Ciphers: []string{
186+
"TLS_AES_128_GCM_SHA256",
187+
"TLS_AES_256_GCM_SHA384",
188+
},
189+
},
190+
},
191+
}
192+
cm, err := GenerateOLSConfigMap(testReconcilerInstance, context.TODO(), cr)
193+
Expect(err).NotTo(HaveOccurred())
194+
195+
var olsConfigMap map[string]interface{}
196+
err = yaml.Unmarshal([]byte(cm.Data[utils.OLSConfigFilename]), &olsConfigMap)
197+
Expect(err).NotTo(HaveOccurred())
198+
Expect(olsConfigMap).To(HaveKeyWithValue("ols_config", HaveKeyWithValue("tlsSecurityProfile", MatchKeys(Options(IgnoreExtras), Keys{
199+
"type": Equal("Custom"),
200+
"minTLSVersion": Equal("VersionTLS13"),
201+
"ciphers": ContainElements("TLS_AES_128_GCM_SHA256", "TLS_AES_256_GCM_SHA384"),
202+
}))))
203+
})
204+
157205
It("should generate configmap with queryFilters", func() {
158206
crWithFilters := utils.WithQueryFilters(cr)
159207
cm, err := GenerateOLSConfigMap(testReconcilerInstance, context.TODO(), crWithFilters)
@@ -1237,6 +1285,19 @@ ols_config:
12371285
- product_docs_index_id: ocp-product-docs-` + major + `_` + minor + `
12381286
product_docs_index_path: /app-root/vector_db/ocp_product_docs/` + major + `.` + minor + `
12391287
product_docs_origin: Red Hat OpenShift 123.456 documentation
1288+
tlsSecurityProfile:
1289+
ciphers:
1290+
- TLS_AES_128_GCM_SHA256
1291+
- TLS_AES_256_GCM_SHA384
1292+
- TLS_CHACHA20_POLY1305_SHA256
1293+
- ECDHE-ECDSA-AES128-GCM-SHA256
1294+
- ECDHE-RSA-AES128-GCM-SHA256
1295+
- ECDHE-ECDSA-AES256-GCM-SHA384
1296+
- ECDHE-RSA-AES256-GCM-SHA384
1297+
- ECDHE-ECDSA-CHACHA20-POLY1305
1298+
- ECDHE-RSA-CHACHA20-POLY1305
1299+
minTLSVersion: VersionTLS12
1300+
type: IntermediateType
12401301
tls_config:
12411302
tls_certificate_path: /etc/certs/lightspeed-tls/tls.crt
12421303
tls_key_path: /etc/certs/lightspeed-tls/tls.key
@@ -1297,6 +1358,19 @@ ols_config:
12971358
- product_docs_index_id: ocp-product-docs-` + major + `_` + minor + `
12981359
product_docs_index_path: /app-root/vector_db/ocp_product_docs/` + major + `.` + minor + `
12991360
product_docs_origin: Red Hat OpenShift 123.456 documentation
1361+
tlsSecurityProfile:
1362+
ciphers:
1363+
- TLS_AES_128_GCM_SHA256
1364+
- TLS_AES_256_GCM_SHA384
1365+
- TLS_CHACHA20_POLY1305_SHA256
1366+
- ECDHE-ECDSA-AES128-GCM-SHA256
1367+
- ECDHE-RSA-AES128-GCM-SHA256
1368+
- ECDHE-ECDSA-AES256-GCM-SHA384
1369+
- ECDHE-RSA-AES256-GCM-SHA384
1370+
- ECDHE-ECDSA-CHACHA20-POLY1305
1371+
- ECDHE-RSA-CHACHA20-POLY1305
1372+
minTLSVersion: VersionTLS12
1373+
type: IntermediateType
13001374
tls_config:
13011375
tls_certificate_path: /etc/certs/lightspeed-tls/tls.crt
13021376
tls_key_path: /etc/certs/lightspeed-tls/tls.key

internal/controller/utils/types.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ type OLSConfig struct {
165165
ConversationCache ConversationCacheConfig `json:"conversation_cache,omitempty"`
166166
// TLS configuration
167167
TLSConfig TLSConfig `json:"tls_config,omitempty"`
168+
// TLS security profile for service endpoint
169+
TLSSecurityProfile *TLSSecurityProfileConfig `json:"tlsSecurityProfile,omitempty"`
168170
// Query filters
169171
QueryFilters []QueryFilters `json:"query_filters,omitempty"`
170172
// Reference content for RAG
@@ -187,6 +189,15 @@ type OLSConfig struct {
187189
ToolsApproval *ToolsApprovalConfig `json:"tools_approval,omitempty"`
188190
}
189191

192+
type TLSSecurityProfileConfig struct {
193+
// Profile type expected by the service (OldType, IntermediateType, ModernType, Custom)
194+
ProfileType string `json:"type,omitempty"`
195+
// Minimum TLS protocol version (VersionTLS12, VersionTLS13, ...)
196+
MinTLSVersion string `json:"minTLSVersion,omitempty"`
197+
// Allowed ciphers in OpenSSL format
198+
Ciphers []string `json:"ciphers,omitempty"`
199+
}
200+
190201
// ToolFilteringConfig defines configuration for tool filtering using hybrid RAG retrieval
191202
// The embedding model is not exposed as it's handled by the container image
192203
type ToolFilteringConfig struct {

0 commit comments

Comments
 (0)