diff --git a/helm/charts/nats/files/config/config.yaml b/helm/charts/nats/files/config/config.yaml index a6ce3e1e..cc1849a8 100644 --- a/helm/charts/nats/files/config/config.yaml +++ b/helm/charts/nats/files/config/config.yaml @@ -75,9 +75,13 @@ gateway: ######################################## {{- with .monitor }} {{- if .enabled }} +{{- if .tls.enabled }} +https_port: {{ .port }} +{{- else }} http_port: {{ .port }} {{- end }} {{- end }} +{{- end }} ######################################## # profiling diff --git a/helm/charts/nats/files/config/tls.yaml b/helm/charts/nats/files/config/tls.yaml index e658453d..26aee015 100644 --- a/helm/charts/nats/files/config/tls.yaml +++ b/helm/charts/nats/files/config/tls.yaml @@ -1,7 +1,16 @@ +# tls {{- with .tls }} {{- if .secretName }} {{- $dir := trimSuffix "/" .dir }} -cert_file: {{ printf "%s/%s" $dir .cert }} -key_file: {{ printf "%s/%s" $dir .key }} +cert_file: {{ printf "%s/%s" $dir (.cert | default "tls.crt") | quote }} +key_file: {{ printf "%s/%s" $dir (.key | default "tls.key") | quote }} +{{- end }} +{{- end }} + +# tlsCA +{{- with $.Values.tlsCA }} +{{- if and .enabled (or .configMapName .secretName) }} +{{- $dir := trimSuffix "/" .dir }} +ca_file: {{ printf "%s/%s" $dir (.key | default "ca.crt") | quote }} {{- end }} {{- end }} diff --git a/helm/charts/nats/files/headless-service.yaml b/helm/charts/nats/files/headless-service.yaml index ee076023..da6552b3 100644 --- a/helm/charts/nats/files/headless-service.yaml +++ b/helm/charts/nats/files/headless-service.yaml @@ -17,8 +17,6 @@ spec: {{- $tlsEnabled := false }} {{- if hasKey $configProtocol "tls" }} {{- $tlsEnabled = $configProtocol.tls.enabled }} - {{- else if eq $protocol "monitor" }} - {{- $tlsEnabled = $.Values.config.nats.tls.enabled }} {{- end }} {{- $appProtocol := or (eq $protocol "websocket") (eq $protocol "monitor") | ternary ($tlsEnabled | ternary "https" "http") ($tlsEnabled | ternary "tls" "tcp") }} - {{ dict "name" $protocol "port" $configProtocol.port "targetPort" $protocol "appProtocol" $appProtocol | toYaml | nindent 4 }} diff --git a/helm/charts/nats/files/nats-box/contexts-secret/context.yaml b/helm/charts/nats/files/nats-box/contexts-secret/context.yaml index 5abeac41..97e4671b 100644 --- a/helm/charts/nats/files/nats-box/contexts-secret/context.yaml +++ b/helm/charts/nats/files/nats-box/contexts-secret/context.yaml @@ -15,7 +15,7 @@ url: nats://{{ .Values.headlessService.name }} creds: /etc/nats-contents/{{ $contextName }}.creds {{- else if .secretName }} {{- $dir := trimSuffix "/" .dir }} -creds: {{ $dir }}/{{ .key }} +creds: {{ printf "%s/%s" $dir (.key | default "nats.creds") | quote }} {{- end }} {{- end }} @@ -25,7 +25,7 @@ creds: {{ $dir }}/{{ .key }} nkey: /etc/nats-contents/{{ $contextName }}.nk {{- else if .secretName }} {{- $dir := trimSuffix "/" .dir }} -nkey: {{ $dir }}/{{ .key }} +nkey: {{ printf "%s/%s" $dir (.key | default "nats.nk") | quote }} {{- end }} {{- end }} @@ -33,8 +33,16 @@ nkey: {{ $dir }}/{{ .key }} {{- with .tls }} {{- if .secretName }} {{- $dir := trimSuffix "/" .dir }} -cert: {{ $dir }}/{{ .cert | default "tls.crt" }} -key: {{ $dir }}/{{ .key | default "tls.key" }} +cert: {{ printf "%s/%s" $dir (.cert | default "tls.crt") | quote }} +key: {{ printf "%s/%s" $dir (.key | default "tls.key") | quote }} +{{- end }} +{{- end }} + +# tlsCA +{{- with $.Values.tlsCA }} +{{- if and .enabled (or .configMapName .secretName) }} +{{- $dir := trimSuffix "/" .dir }} +ca: {{ printf "%s/%s" $dir (.key | default "ca.crt") | quote }} {{- end }} {{- end }} diff --git a/helm/charts/nats/files/nats-box/deployment/container.yaml b/helm/charts/nats/files/nats-box/deployment/container.yaml index 12b897e4..9c99959f 100644 --- a/helm/charts/nats/files/nats-box/deployment/container.yaml +++ b/helm/charts/nats/files/nats-box/deployment/container.yaml @@ -26,12 +26,17 @@ command: args: - trap true INT TERM; sleep infinity & wait volumeMounts: +# contexts secret - name: contexts mountPath: /etc/nats-contexts +# contents secret {{- if .hasContentsSecret }} - name: contents mountPath: /etc/nats-contents {{- end }} +# tlsCA +{{- include "nats.tlsCAVolumeMount" $ }} +# secrets {{- range (include "natsBox.secretNames" $ | fromJson).secretNames }} - name: {{ .name | quote }} mountPath: {{ .dir | quote }} diff --git a/helm/charts/nats/files/nats-box/deployment/pod-template.yaml b/helm/charts/nats/files/nats-box/deployment/pod-template.yaml index 9fff9d06..47e6fbbb 100644 --- a/helm/charts/nats/files/nats-box/deployment/pod-template.yaml +++ b/helm/charts/nats/files/nats-box/deployment/pod-template.yaml @@ -27,6 +27,8 @@ spec: secret: secretName: {{ .Values.natsBox.contentsSecret.name }} {{- end }} + # tlsCA + {{- include "nats.tlsCAVolume" $ | nindent 2 }} # secrets {{- range (include "natsBox.secretNames" $ | fromJson).secretNames }} - name: {{ .name | quote }} diff --git a/helm/charts/nats/files/service.yaml b/helm/charts/nats/files/service.yaml index 17fae482..db08fe5b 100644 --- a/helm/charts/nats/files/service.yaml +++ b/helm/charts/nats/files/service.yaml @@ -16,8 +16,6 @@ spec: {{- $tlsEnabled := false }} {{- if hasKey $configProtocol "tls" }} {{- $tlsEnabled = $configProtocol.tls.enabled }} - {{- else if eq $protocol "monitor" }} - {{- $tlsEnabled = $.Values.config.nats.tls.enabled }} {{- end }} {{- $appProtocol := or (eq $protocol "websocket") (eq $protocol "monitor") | ternary ($tlsEnabled | ternary "https" "http") ($tlsEnabled | ternary "tls" "tcp") }} - {{ merge (dict "name" $protocol "targetPort" $protocol "appProtocol" $appProtocol) (omit $servicePort "enabled") (dict "port" $configProtocol.port) | toYaml | nindent 4 }} diff --git a/helm/charts/nats/files/stateful-set/nats-container.yaml b/helm/charts/nats/files/stateful-set/nats-container.yaml index ea6301c3..b89d20e0 100644 --- a/helm/charts/nats/files/stateful-set/nats-container.yaml +++ b/helm/charts/nats/files/stateful-set/nats-container.yaml @@ -65,12 +65,15 @@ livenessProbe: {{- end }} volumeMounts: +# nats config - name: config mountPath: /etc/nats-config +# PID volume {{- if .Values.reloader.enabled }} - name: pid mountPath: /var/run/nats {{- end}} +# JetStream PVC {{- with .Values.config.jetstream }} {{- if and .enabled .fileStore.enabled .fileStore.pvc.enabled }} {{- with .fileStore }} @@ -79,12 +82,16 @@ volumeMounts: {{- end }} {{- end }} {{- end }} +# resolver PVC {{- with .Values.config.resolver }} {{- if and .enabled .pvc.enabled }} - name: {{ .pvc.name }} mountPath: {{ .dir | quote }} {{- end }} {{- end }} +# tlsCA +{{- include "nats.tlsCAVolumeMount" $ }} +# secrets {{- range (include "nats.secretNames" $ | fromJson).secretNames }} - name: {{ .name | quote }} mountPath: {{ .dir | quote }} diff --git a/helm/charts/nats/files/stateful-set/pod-template.yaml b/helm/charts/nats/files/stateful-set/pod-template.yaml index d58f91fd..afff14ed 100644 --- a/helm/charts/nats/files/stateful-set/pod-template.yaml +++ b/helm/charts/nats/files/stateful-set/pod-template.yaml @@ -49,6 +49,8 @@ spec: - name: pid emptyDir: {} {{- end }} + # tlsCA + {{- include "nats.tlsCAVolume" $ | nindent 2 }} # secrets {{- range (include "nats.secretNames" $ | fromJson).secretNames }} - name: {{ .name | quote }} diff --git a/helm/charts/nats/templates/_helpers.tpl b/helm/charts/nats/templates/_helpers.tpl index 2b154415..ba831397 100644 --- a/helm/charts/nats/templates/_helpers.tpl +++ b/helm/charts/nats/templates/_helpers.tpl @@ -181,6 +181,30 @@ imagePullPolicy: {{ .pullPolicy | default .global.image.pullPolicy }} {{- toJson (dict "secretNames" $secrets) }} {{- end }} +{{- define "nats.tlsCAVolume" -}} +{{- with .Values.tlsCA }} +{{- if and .enabled (or .configMapName .secretName) }} +- name: tls-ca +{{- if .configMapName }} + configMap: + name: {{ .configMapName | quote }} +{{- else if .secretName }} + secret: + secretName: {{ .secretName | quote }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} + +{{- define "nats.tlsCAVolumeMount" -}} +{{- with .Values.tlsCA }} +{{- if and .enabled (or .configMapName .secretName) }} +- name: tls-ca + mountPath: {{ .dir | quote }} +{{- end }} +{{- end }} +{{- end }} + {{/* translates env var map to list */}} diff --git a/helm/charts/nats/test/config_test.go b/helm/charts/nats/test/config_test.go index 49fb3846..ef0eba4b 100644 --- a/helm/charts/nats/test/config_test.go +++ b/helm/charts/nats/test/config_test.go @@ -542,233 +542,6 @@ config: RenderAndCheck(t, test, expected) } -func TestConfigTls(t *testing.T) { - t.Parallel() - test := DefaultTest() - test.Values = ` -config: - cluster: - enabled: true - tls: - enabled: true - secretName: cluster-tls - nats: - tls: - enabled: true - secretName: nats-tls - merge: - ca_file: /etc/my-ca/ca.crt - verify_cert_and_check_known_urls: true - patch: [{op: add, path: /verify_and_map, value: true}] - leafnodes: - enabled: true - tls: - enabled: true - secretName: leafnodes-tls - websocket: - enabled: true - tls: - enabled: true - secretName: websocket-tls - mqtt: - enabled: true - tls: - enabled: true - secretName: mqtt-tls - gateway: - enabled: true - tls: - enabled: true - secretName: gateway-tls -` - expected := DefaultResources(t, test) - expected.Conf.Value["cluster"] = map[string]any{ - "name": "nats", - "no_advertise": true, - "port": int64(6222), - "routes": []any{ - "tls://nats-0.nats-headless:6222", - "tls://nats-1.nats-headless:6222", - "tls://nats-2.nats-headless:6222", - }, - } - expected.Conf.Value["leafnodes"] = map[string]any{ - "port": int64(7422), - "no_advertise": true, - } - expected.Conf.Value["websocket"] = map[string]any{ - "port": int64(8080), - "compression": true, - } - expected.Conf.Value["mqtt"] = map[string]any{ - "port": int64(1883), - } - expected.Conf.Value["gateway"] = map[string]any{ - "port": int64(7222), - "name": "nats", - } - - replicas3 := int32(3) - expected.StatefulSet.Value.Spec.Replicas = &replicas3 - - volumes := expected.StatefulSet.Value.Spec.Template.Spec.Volumes - natsVm := expected.StatefulSet.Value.Spec.Template.Spec.Containers[0].VolumeMounts - reloaderVm := expected.StatefulSet.Value.Spec.Template.Spec.Containers[1].VolumeMounts - for _, protocol := range []string{"nats", "leafnodes", "websocket", "mqtt", "cluster", "gateway"} { - tls := map[string]any{ - "cert_file": "/etc/nats-certs/" + protocol + "/tls.crt", - "key_file": "/etc/nats-certs/" + protocol + "/tls.key", - } - if protocol == "nats" { - tls["ca_file"] = "/etc/my-ca/ca.crt" - tls["verify_cert_and_check_known_urls"] = true - tls["verify_and_map"] = true - expected.Conf.Value["tls"] = tls - } else { - expected.Conf.Value[protocol].(map[string]any)["tls"] = tls - } - - volumes = append(volumes, corev1.Volume{ - Name: protocol + "-tls", - VolumeSource: corev1.VolumeSource{ - Secret: &corev1.SecretVolumeSource{ - SecretName: protocol + "-tls", - }, - }, - }) - - natsVm = append(natsVm, corev1.VolumeMount{ - MountPath: "/etc/nats-certs/" + protocol, - Name: protocol + "-tls", - }) - - reloaderVm = append(reloaderVm, corev1.VolumeMount{ - MountPath: "/etc/nats-certs/" + protocol, - Name: protocol + "-tls", - }) - } - - expected.StatefulSet.Value.Spec.Template.Spec.Volumes = volumes - expected.StatefulSet.Value.Spec.Template.Spec.Containers[0].VolumeMounts = natsVm - expected.StatefulSet.Value.Spec.Template.Spec.Containers[1].VolumeMounts = reloaderVm - - // reloader certs are alphabetized - reloaderArgs := expected.StatefulSet.Value.Spec.Template.Spec.Containers[1].Args - for _, protocol := range []string{"cluster", "gateway", "leafnodes", "mqtt", "nats", "websocket"} { - if protocol == "nats" { - reloaderArgs = append(reloaderArgs, "-config", "/etc/my-ca/ca.crt") - } - reloaderArgs = append(reloaderArgs, "-config", "/etc/nats-certs/"+protocol+"/tls.crt", "-config", "/etc/nats-certs/"+protocol+"/tls.key") - } - - expected.StatefulSet.Value.Spec.Template.Spec.Containers[1].Args = reloaderArgs - - expected.StatefulSet.Value.Spec.Template.Spec.Containers[0].Ports = []corev1.ContainerPort{ - { - Name: "nats", - ContainerPort: 4222, - }, - { - Name: "leafnodes", - ContainerPort: 7422, - }, - { - Name: "websocket", - ContainerPort: 8080, - }, - { - Name: "mqtt", - ContainerPort: 1883, - }, - { - Name: "cluster", - ContainerPort: 6222, - }, - { - Name: "gateway", - ContainerPort: 7222, - }, - { - Name: "monitor", - ContainerPort: 8222, - }, - } - - expected.HeadlessService.Value.Spec.Ports = []corev1.ServicePort{ - { - Name: "nats", - Port: 4222, - TargetPort: intstr.FromString("nats"), - AppProtocol: &appProtocolTLS, - }, - { - Name: "leafnodes", - Port: 7422, - TargetPort: intstr.FromString("leafnodes"), - AppProtocol: &appProtocolTLS, - }, - { - Name: "websocket", - Port: 8080, - TargetPort: intstr.FromString("websocket"), - AppProtocol: &appProtocolHTTPS, - }, - { - Name: "mqtt", - Port: 1883, - TargetPort: intstr.FromString("mqtt"), - AppProtocol: &appProtocolTLS, - }, - { - Name: "cluster", - Port: 6222, - TargetPort: intstr.FromString("cluster"), - AppProtocol: &appProtocolTLS, - }, - { - Name: "gateway", - Port: 7222, - TargetPort: intstr.FromString("gateway"), - AppProtocol: &appProtocolTLS, - }, - { - Name: "monitor", - Port: 8222, - TargetPort: intstr.FromString("monitor"), - AppProtocol: &appProtocolHTTPS, - }, - } - - expected.Service.Value.Spec.Ports = []corev1.ServicePort{ - { - Name: "nats", - Port: 4222, - TargetPort: intstr.FromString("nats"), - AppProtocol: &appProtocolTLS, - }, - { - Name: "leafnodes", - Port: 7422, - TargetPort: intstr.FromString("leafnodes"), - AppProtocol: &appProtocolTLS, - }, - { - Name: "websocket", - Port: 8080, - TargetPort: intstr.FromString("websocket"), - AppProtocol: &appProtocolHTTPS, - }, - { - Name: "mqtt", - Port: 1883, - TargetPort: intstr.FromString("mqtt"), - AppProtocol: &appProtocolTLS, - }, - } - - RenderAndCheck(t, test, expected) -} - func TestConfigInclude(t *testing.T) { t.Parallel() test := DefaultTest() diff --git a/helm/charts/nats/test/tls_test.go b/helm/charts/nats/test/tls_test.go new file mode 100644 index 00000000..1dcae1b1 --- /dev/null +++ b/helm/charts/nats/test/tls_test.go @@ -0,0 +1,380 @@ +package test + +import ( + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/util/intstr" + "testing" +) + +func TestConfigTls(t *testing.T) { + t.Parallel() + test := DefaultTest() + test.Values = ` +config: + cluster: + enabled: true + tls: + enabled: true + secretName: cluster-tls + nats: + tls: + enabled: true + secretName: nats-tls + merge: + ca_file: /etc/my-ca/ca.crt + verify_cert_and_check_known_urls: true + patch: [{op: add, path: /verify_and_map, value: true}] + leafnodes: + enabled: true + tls: + enabled: true + secretName: leafnodes-tls + websocket: + enabled: true + tls: + enabled: true + secretName: websocket-tls + mqtt: + enabled: true + tls: + enabled: true + secretName: mqtt-tls + gateway: + enabled: true + tls: + enabled: true + secretName: gateway-tls + monitor: + tls: + enabled: true +` + expected := DefaultResources(t, test) + expected.Conf.Value["cluster"] = map[string]any{ + "name": "nats", + "no_advertise": true, + "port": int64(6222), + "routes": []any{ + "tls://nats-0.nats-headless:6222", + "tls://nats-1.nats-headless:6222", + "tls://nats-2.nats-headless:6222", + }, + } + expected.Conf.Value["leafnodes"] = map[string]any{ + "port": int64(7422), + "no_advertise": true, + } + expected.Conf.Value["websocket"] = map[string]any{ + "port": int64(8080), + "compression": true, + } + expected.Conf.Value["mqtt"] = map[string]any{ + "port": int64(1883), + } + expected.Conf.Value["gateway"] = map[string]any{ + "port": int64(7222), + "name": "nats", + } + expected.Conf.Value["https_port"] = expected.Conf.Value["http_port"] + delete(expected.Conf.Value, "http_port") + + replicas3 := int32(3) + expected.StatefulSet.Value.Spec.Replicas = &replicas3 + + volumes := expected.StatefulSet.Value.Spec.Template.Spec.Volumes + natsVm := expected.StatefulSet.Value.Spec.Template.Spec.Containers[0].VolumeMounts + reloaderVm := expected.StatefulSet.Value.Spec.Template.Spec.Containers[1].VolumeMounts + for _, protocol := range []string{"nats", "leafnodes", "websocket", "mqtt", "cluster", "gateway"} { + tls := map[string]any{ + "cert_file": "/etc/nats-certs/" + protocol + "/tls.crt", + "key_file": "/etc/nats-certs/" + protocol + "/tls.key", + } + if protocol == "nats" { + tls["ca_file"] = "/etc/my-ca/ca.crt" + tls["verify_cert_and_check_known_urls"] = true + tls["verify_and_map"] = true + expected.Conf.Value["tls"] = tls + } else { + expected.Conf.Value[protocol].(map[string]any)["tls"] = tls + } + + volumes = append(volumes, corev1.Volume{ + Name: protocol + "-tls", + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: protocol + "-tls", + }, + }, + }) + + natsVm = append(natsVm, corev1.VolumeMount{ + MountPath: "/etc/nats-certs/" + protocol, + Name: protocol + "-tls", + }) + + reloaderVm = append(reloaderVm, corev1.VolumeMount{ + MountPath: "/etc/nats-certs/" + protocol, + Name: protocol + "-tls", + }) + } + + expected.StatefulSet.Value.Spec.Template.Spec.Volumes = volumes + expected.StatefulSet.Value.Spec.Template.Spec.Containers[0].VolumeMounts = natsVm + expected.StatefulSet.Value.Spec.Template.Spec.Containers[1].VolumeMounts = reloaderVm + + // reloader certs are alphabetized + reloaderArgs := expected.StatefulSet.Value.Spec.Template.Spec.Containers[1].Args + for _, protocol := range []string{"cluster", "gateway", "leafnodes", "mqtt", "nats", "websocket"} { + if protocol == "nats" { + reloaderArgs = append(reloaderArgs, "-config", "/etc/my-ca/ca.crt") + } + reloaderArgs = append(reloaderArgs, "-config", "/etc/nats-certs/"+protocol+"/tls.crt", "-config", "/etc/nats-certs/"+protocol+"/tls.key") + } + + expected.StatefulSet.Value.Spec.Template.Spec.Containers[1].Args = reloaderArgs + + expected.StatefulSet.Value.Spec.Template.Spec.Containers[0].Ports = []corev1.ContainerPort{ + { + Name: "nats", + ContainerPort: 4222, + }, + { + Name: "leafnodes", + ContainerPort: 7422, + }, + { + Name: "websocket", + ContainerPort: 8080, + }, + { + Name: "mqtt", + ContainerPort: 1883, + }, + { + Name: "cluster", + ContainerPort: 6222, + }, + { + Name: "gateway", + ContainerPort: 7222, + }, + { + Name: "monitor", + ContainerPort: 8222, + }, + } + + expected.HeadlessService.Value.Spec.Ports = []corev1.ServicePort{ + { + Name: "nats", + Port: 4222, + TargetPort: intstr.FromString("nats"), + AppProtocol: &appProtocolTLS, + }, + { + Name: "leafnodes", + Port: 7422, + TargetPort: intstr.FromString("leafnodes"), + AppProtocol: &appProtocolTLS, + }, + { + Name: "websocket", + Port: 8080, + TargetPort: intstr.FromString("websocket"), + AppProtocol: &appProtocolHTTPS, + }, + { + Name: "mqtt", + Port: 1883, + TargetPort: intstr.FromString("mqtt"), + AppProtocol: &appProtocolTLS, + }, + { + Name: "cluster", + Port: 6222, + TargetPort: intstr.FromString("cluster"), + AppProtocol: &appProtocolTLS, + }, + { + Name: "gateway", + Port: 7222, + TargetPort: intstr.FromString("gateway"), + AppProtocol: &appProtocolTLS, + }, + { + Name: "monitor", + Port: 8222, + TargetPort: intstr.FromString("monitor"), + AppProtocol: &appProtocolHTTPS, + }, + } + + expected.Service.Value.Spec.Ports = []corev1.ServicePort{ + { + Name: "nats", + Port: 4222, + TargetPort: intstr.FromString("nats"), + AppProtocol: &appProtocolTLS, + }, + { + Name: "leafnodes", + Port: 7422, + TargetPort: intstr.FromString("leafnodes"), + AppProtocol: &appProtocolTLS, + }, + { + Name: "websocket", + Port: 8080, + TargetPort: intstr.FromString("websocket"), + AppProtocol: &appProtocolHTTPS, + }, + { + Name: "mqtt", + Port: 1883, + TargetPort: intstr.FromString("mqtt"), + AppProtocol: &appProtocolTLS, + }, + } + + RenderAndCheck(t, test, expected) +} + +func TestTlsCA(t *testing.T) { + t.Parallel() + for _, tt := range []struct { + name string + key string + dir string + secret bool + }{ + { + name: "ConfigMap", + secret: false, + }, + { + name: "Secret", + secret: true, + key: "my-ca.crt", + dir: "/etc/nats-ca-cert-custom", + }, + } { + t.Run(tt.name, func(t *testing.T) { + test := DefaultTest() + test.Values = ` +config: + nats: + tls: + enabled: true + secretName: nats-tls +tlsCA: + enabled: true` + if tt.secret { + test.Values += ` + secretName: nats-ca` + } else { + test.Values += ` + configMapName: nats-ca` + } + if tt.key != "" { + test.Values += ` + key: ` + tt.key + } + if tt.dir != "" { + test.Values += ` + dir: ` + tt.dir + } + expected := DefaultResources(t, test) + + key := tt.key + if key == "" { + key = "ca.crt" + } + dir := tt.dir + if dir == "" { + dir = "/etc/nats-ca-cert" + } + expected.Conf.Value["tls"] = map[string]any{ + "cert_file": "/etc/nats-certs/nats/tls.crt", + "key_file": "/etc/nats-certs/nats/tls.key", + "ca_file": dir + "/" + key, + } + + expected.NatsBoxContextsSecret.Value.StringData["default.json"] = `{ + "ca": "` + dir + "/" + key + `", + "url": "nats://` + test.FullName + `" +} +` + expected.Service.Value.Spec.Ports[0].AppProtocol = &appProtocolTLS + expected.HeadlessService.Value.Spec.Ports[0].AppProtocol = &appProtocolTLS + + // reloader certs are alphabetized + reloaderArgs := expected.StatefulSet.Value.Spec.Template.Spec.Containers[1].Args + reloaderArgs = append(reloaderArgs, + "-config", dir+"/"+key, + "-config", "/etc/nats-certs/nats/tls.crt", + "-config", "/etc/nats-certs/nats/tls.key") + expected.StatefulSet.Value.Spec.Template.Spec.Containers[1].Args = reloaderArgs + + tlsCAVol := corev1.Volume{ + Name: "tls-ca", + } + if tt.secret { + tlsCAVol.VolumeSource = corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: "nats-ca", + }, + } + } else { + tlsCAVol.VolumeSource = corev1.VolumeSource{ + ConfigMap: &corev1.ConfigMapVolumeSource{ + LocalObjectReference: corev1.LocalObjectReference{ + Name: "nats-ca", + }, + }, + } + } + + tlsCAVm := corev1.VolumeMount{ + Name: "tls-ca", + MountPath: dir, + } + + stsVols := expected.StatefulSet.Value.Spec.Template.Spec.Volumes + natsVm := expected.StatefulSet.Value.Spec.Template.Spec.Containers[0].VolumeMounts + reloaderVm := expected.StatefulSet.Value.Spec.Template.Spec.Containers[1].VolumeMounts + + stsVols = append(stsVols, tlsCAVol, corev1.Volume{ + Name: "nats-tls", + VolumeSource: corev1.VolumeSource{ + Secret: &corev1.SecretVolumeSource{ + SecretName: "nats-tls", + }, + }, + }) + + natsVm = append(natsVm, tlsCAVm, corev1.VolumeMount{ + MountPath: "/etc/nats-certs/nats", + Name: "nats-tls", + }) + + reloaderVm = append(reloaderVm, tlsCAVm, corev1.VolumeMount{ + MountPath: "/etc/nats-certs/nats", + Name: "nats-tls", + }) + + expected.StatefulSet.Value.Spec.Template.Spec.Volumes = stsVols + expected.StatefulSet.Value.Spec.Template.Spec.Containers[0].VolumeMounts = natsVm + expected.StatefulSet.Value.Spec.Template.Spec.Containers[1].VolumeMounts = reloaderVm + + natsBoxVols := expected.NatsBoxDeployment.Value.Spec.Template.Spec.Volumes + natsBoxVms := expected.NatsBoxDeployment.Value.Spec.Template.Spec.Containers[0].VolumeMounts + + natsBoxVols = append(natsBoxVols, tlsCAVol) + natsBoxVms = append(natsBoxVms, tlsCAVm) + + expected.NatsBoxDeployment.Value.Spec.Template.Spec.Volumes = natsBoxVols + expected.NatsBoxDeployment.Value.Spec.Template.Spec.Containers[0].VolumeMounts = natsBoxVms + + RenderAndCheck(t, test, expected) + }) + } +} diff --git a/helm/charts/nats/values.yaml b/helm/charts/nats/values.yaml index 277677f6..edf26be7 100644 --- a/helm/charts/nats/values.yaml +++ b/helm/charts/nats/values.yaml @@ -14,7 +14,7 @@ global: labels: {} ################################################################################ -# Naming options +# Common options ################################################################################ # override name of the chart nameOverride: @@ -23,6 +23,19 @@ fullnameOverride: # override the namespace that resources are installed into namespaceOverride: +# reference a common CA Certificate or Bundle in all nats config `tls` blocks and nats-box contexts +# note: `tls.verify` still must be set in the appropriate nats config `tls` blocks to require mTLS +tlsCA: + enabled: false + # set configMapName in order to mount an existing configMap to dir + configMapName: + # set secretName in order to mount an existing secretName to dir + secretName: + # directory to mount the configMap or secret to + dir: /etc/nats-ca-cert + # key in the configMap or secret that contains the CA Certificate or Bundle + key: ca.crt + ################################################################################ # NATS Stateful Set and associated resources ################################################################################ @@ -218,6 +231,10 @@ config: monitor: enabled: true port: 8222 + tls: + # config.nats.tls must be enabled also + # when enabled, HTTP monitoring will use tls certs from config.nats.tls + enabled: false profiling: enabled: false @@ -527,7 +544,7 @@ natsBox: # defaults to /etc/nats-certs/ dir: cert: tls.crt - key: tls.ca + key: tls.key # merge or patch the context # https://docs.nats.io/using-nats/nats-tools/nats_cli#nats-contexts