Skip to content

Commit ad10fe3

Browse files
committed
Add centrally managed TLS configuration for console-plugin nginx
1 parent 8f65ba2 commit ad10fe3

2 files changed

Lines changed: 572 additions & 0 deletions

File tree

pkg/reconciler/openshift/tektonconfig/console_plugin_reconciler.go

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,10 @@ const (
4444
PipelinesConsolePluginImageEnvironmentKey = "IMAGE_PIPELINES_CONSOLE_PLUGIN"
4545
// pipelines console plugin container name, used to replace the image from the environment
4646
PipelinesConsolePluginContainerName = "pipelines-console-plugin"
47+
// TLS configuration environment variables
48+
TLSMinVersionEnvKey = "TLS_MIN_VERSION"
49+
TLSCipherSuitesEnvKey = "TLS_CIPHER_SUITES"
50+
TLSCurvePreferencesEnvKey = "TLS_CURVE_PREFERENCES"
4751
)
4852

4953
var (
@@ -64,6 +68,10 @@ type consolePluginReconciler struct {
6468
operatorVersion string
6569
pipelinesConsolePluginImage string
6670
manifest mf.Manifest
71+
// TLS configuration
72+
tlsMinVersion string
73+
tlsCipherSuites string
74+
tlsCurvePreferences string
6775
}
6876

6977
// reconcile steps
@@ -169,6 +177,26 @@ func (cpr *consolePluginReconciler) updateOnce(ctx context.Context) {
169177
"environmentVariable", PipelinesConsolePluginImageEnvironmentKey,
170178
)
171179
}
180+
181+
// Read TLS configuration from environment
182+
cpr.tlsMinVersion = os.Getenv(TLSMinVersionEnvKey)
183+
cpr.tlsCipherSuites = os.Getenv(TLSCipherSuitesEnvKey)
184+
cpr.tlsCurvePreferences = os.Getenv(TLSCurvePreferencesEnvKey)
185+
186+
// Apply fail-safe defaults if not provided
187+
if cpr.tlsMinVersion == "" {
188+
cpr.tlsMinVersion = "VersionTLS12" // Safe default
189+
cpr.logger.Warnw("TLS min version not configured, using safe default",
190+
"default", "TLSv1.2",
191+
"environmentVariable", TLSMinVersionEnvKey,
192+
)
193+
}
194+
195+
cpr.logger.Debugw("TLS configuration loaded",
196+
"minVersion", cpr.tlsMinVersion,
197+
"hasCipherSuites", cpr.tlsCipherSuites != "",
198+
"hasCurvePreferences", cpr.tlsCurvePreferences != "",
199+
)
172200
})
173201
}
174202

@@ -206,6 +234,8 @@ func (cpr *consolePluginReconciler) transform(ctx context.Context, manifest *mf.
206234
// updates "metadata.namespace" to targetNamespace
207235
common.ReplaceNamespace(tektonConfigCR.Spec.TargetNamespace),
208236
cpr.transformerConsolePlugin(tektonConfigCR.Spec.TargetNamespace),
237+
// Add nginx TLS configuration transformer
238+
cpr.transformerNginxTLS(),
209239
common.AddConfiguration(tektonConfigCR.Spec.Config),
210240
}
211241

@@ -234,3 +264,105 @@ func (cpr *consolePluginReconciler) transformerConsolePlugin(targetNamespace str
234264
return unstructured.SetNestedField(u.Object, targetNamespace, "spec", "backend", "service", "namespace")
235265
}
236266
}
267+
268+
// transformerNginxTLS updates the nginx.conf ConfigMap with TLS directives
269+
func (cpr *consolePluginReconciler) transformerNginxTLS() mf.Transformer {
270+
return func(u *unstructured.Unstructured) error {
271+
if u.GetKind() != "ConfigMap" || u.GetName() != "pipelines-console-plugin" {
272+
return nil
273+
}
274+
275+
// Get the current nginx.conf
276+
data, found, err := unstructured.NestedString(u.Object, "data", "nginx.conf")
277+
if err != nil || !found {
278+
return err
279+
}
280+
281+
// Generate the updated nginx.conf with TLS directives
282+
updatedConf := cpr.generateNginxConfWithTLS(data)
283+
284+
// Set the updated nginx.conf back
285+
return unstructured.SetNestedField(u.Object, updatedConf, "data", "nginx.conf")
286+
}
287+
}
288+
289+
// generateNginxConfWithTLS injects TLS directives into nginx configuration
290+
func (cpr *consolePluginReconciler) generateNginxConfWithTLS(baseConf string) string {
291+
// Build TLS directives
292+
tlsDirectives := cpr.buildNginxTLSDirectives()
293+
294+
// If no TLS directives to add, return original
295+
if tlsDirectives == "" {
296+
return baseConf
297+
}
298+
299+
// Inject TLS directives into the server block
300+
// Find "server {" and inject after it
301+
lines := strings.Split(baseConf, "\n")
302+
var result strings.Builder
303+
304+
for _, line := range lines {
305+
result.WriteString(line)
306+
result.WriteString("\n")
307+
308+
// After "server {", inject TLS directives
309+
if strings.Contains(line, "server {") {
310+
// Add TLS directives with proper indentation
311+
result.WriteString(tlsDirectives)
312+
}
313+
}
314+
315+
return result.String()
316+
}
317+
318+
// buildNginxTLSDirectives generates nginx TLS directives from environment variables
319+
func (cpr *consolePluginReconciler) buildNginxTLSDirectives() string {
320+
var directives strings.Builder
321+
322+
// Convert Go TLS version to nginx ssl_protocols
323+
if cpr.tlsMinVersion != "" {
324+
protocols := cpr.convertTLSVersionToNginx(cpr.tlsMinVersion)
325+
directives.WriteString(fmt.Sprintf(" ssl_protocols %s;\n", protocols))
326+
}
327+
328+
// NOTE: Cipher suites are intentionally NOT configured here.
329+
// TLS 1.3 has secure cipher suites by default, and configuring them
330+
// requires different nginx directives (ssl_conf_command vs ssl_ciphers).
331+
// Relying on nginx's secure defaults is simpler and less error-prone.
332+
if cpr.tlsCipherSuites != "" {
333+
cpr.logger.Debugw("TLS cipher suites provided but not applied (using nginx defaults)",
334+
"reason", "TLS 1.3 uses secure defaults, avoids ssl_ciphers/ssl_conf_command complexity",
335+
)
336+
}
337+
338+
// Add ECDH curves if provided
339+
if cpr.tlsCurvePreferences != "" {
340+
// Convert comma-separated to colon-separated
341+
curves := strings.ReplaceAll(cpr.tlsCurvePreferences, ",", ":")
342+
directives.WriteString(fmt.Sprintf(" ssl_ecdh_curve %s;\n", curves))
343+
}
344+
345+
return directives.String()
346+
}
347+
348+
// convertTLSVersionToNginx converts Go TLS version names to nginx protocol names
349+
func (cpr *consolePluginReconciler) convertTLSVersionToNginx(minVersion string) string {
350+
// Map Go TLS constants to nginx protocols
351+
switch minVersion {
352+
case "VersionTLS13":
353+
return "TLSv1.3"
354+
case "VersionTLS12":
355+
return "TLSv1.2 TLSv1.3"
356+
case "VersionTLS11":
357+
return "TLSv1.1 TLSv1.2 TLSv1.3"
358+
case "VersionTLS10":
359+
return "TLSv1 TLSv1.1 TLSv1.2 TLSv1.3"
360+
default:
361+
// Fail-safe: use modern defaults
362+
cpr.logger.Warnw("Unknown TLS version, using safe default",
363+
"providedVersion", minVersion,
364+
"defaultTo", "TLSv1.2 TLSv1.3",
365+
)
366+
return "TLSv1.2 TLSv1.3"
367+
}
368+
}

0 commit comments

Comments
 (0)