diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d36d802..b360df21 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,20 @@ - Added `license.mountPath` to configure where the license volume is mounted - Added `license.optional` to configure the license volume as optional if needed - Added `license.readOnly` to configure the read/write mode of the license volume mount +- Added new configuration properties for GraphDB Tomcat connector SSL/TLS + - Added `configuration.tls.keystore` to configure a keystore with its properties + - Added `configuration.tls.truststore` to configure a truststore with its properties + - Added `configuration.tls.certificateRevocationList` to configure a certificate revocation list +- Added new configuration properties for configuring GraphDB cluster security (SSL/TLS) + - Added `cluster.tls.mode` to configure cluster security mode + - Added `cluster.tls.privateKey` to configure a private key with its properties + - Added `cluster.tls.certificate` to configure a certificate + - Added `cluster.tls.keystore` to configure a keystore with its properties + - Added `cluster.tls.truststore` to configure a truststore with its properties + - Added `cluster.tls.rootCerts` to configure root certificates to be trusted + - Added `cluster.tls.certificateChain` to configure a certificate chain + - Added `cluster.tls.certificateRevocationList` to configure a certificate revocation list +- Updated jobs and scripts to use `https` or `http` depending on whether the Tomcat connector security is configured ### Updated @@ -16,6 +30,11 @@ mount. This allows kubelet to update the license when the Secret has been updated. - Changed the license volume mount as read-only by default with `license.readOnly` +### Fixed + +- Removed the `quotes` tag from graphdb and proxy `configmap-properties` and `secret-properties` templates + which caused invalid rendering of extra properties. + ## Version 11.2.2 ### New @@ -56,7 +75,7 @@ ### Improvement - Added GraphDB configuration examples -- Added GraphDB security configration examples +- Added GraphDB security configuration examples ## Version 11.1.4 diff --git a/README.md b/README.md index 115618c0..2c8720c3 100644 --- a/README.md +++ b/README.md @@ -335,6 +335,29 @@ IMPORTANT: This is generated by helm-docs, do not attempt modifying it on hand a | cluster.jobs.createCluster.enabled | bool | `true` | | | cluster.jobs.patchCluster.enabled | bool | `true` | | | cluster.jobs.scaleCluster.enabled | bool | `true` | | +| cluster.tls.certificate.certificateKey | string | `"certificate.pem"` | | +| cluster.tls.certificate.existingSecret | string | `""` | | +| cluster.tls.certificateChain.certificateChainKey | string | `"certChain.pem"` | | +| cluster.tls.certificateChain.existingSecret | string | `""` | | +| cluster.tls.certificateRevocationList.certificateRevocationListKey | string | `"crl.pem"` | | +| cluster.tls.certificateRevocationList.existingSecret | string | `""` | | +| cluster.tls.keystore.existingSecret | string | `""` | | +| cluster.tls.keystore.keyAlias | string | `"mykey"` | | +| cluster.tls.keystore.keystoreKey | string | `"keystore.jks"` | | +| cluster.tls.keystore.keystorePasswordKey | string | `"pass"` | | +| cluster.tls.keystore.keystoreProvider | string | `"SUN"` | | +| cluster.tls.keystore.keystoreType | string | `"JKS"` | | +| cluster.tls.mode | string | `"DEFAULT"` | | +| cluster.tls.privateKey.existingSecret | string | `""` | | +| cluster.tls.privateKey.privateKeyKey | string | `"privatekey.pem"` | | +| cluster.tls.privateKey.privateKeyPasswordKey | string | `"pass"` | | +| cluster.tls.rootCerts.existingSecret | string | `""` | | +| cluster.tls.rootCerts.rootCertsKey | string | `"rootCerts.pem"` | | +| cluster.tls.truststore.existingSecret | string | `""` | | +| cluster.tls.truststore.truststoreKey | string | `"truststore.jks"` | | +| cluster.tls.truststore.truststorePasswordKey | string | `"pass"` | | +| cluster.tls.truststore.truststoreProvider | string | `"SUN"` | | +| cluster.tls.truststore.truststoreType | string | `"JKS"` | | | cluster.token.existingSecret | string | `""` | | | cluster.token.secret | string | `"s3cr37"` | | | cluster.token.secretKey | string | `""` | | @@ -352,6 +375,19 @@ IMPORTANT: This is generated by helm-docs, do not attempt modifying it on hand a | configuration.logback.existingConfigmap | string | `""` | | | configuration.properties | object | `{}` | | | configuration.secretProperties | object | `{}` | | +| configuration.tls.certificateRevocationList.certificateRevocationListKey | string | `"crl.pem"` | | +| configuration.tls.certificateRevocationList.existingSecret | string | `""` | | +| configuration.tls.keystore.existingSecret | string | `""` | | +| configuration.tls.keystore.keyAlias | string | `"mykey"` | | +| configuration.tls.keystore.keystoreKey | string | `"keystore.jks"` | | +| configuration.tls.keystore.keystorePasswordKey | string | `"pass"` | | +| configuration.tls.keystore.keystoreProvider | string | `"SUN"` | | +| configuration.tls.keystore.keystoreType | string | `"JKS"` | | +| configuration.tls.truststore.existingSecret | string | `""` | | +| configuration.tls.truststore.truststoreKey | string | `"truststore.jks"` | | +| configuration.tls.truststore.truststorePasswordKey | string | `"pass"` | | +| configuration.tls.truststore.truststoreProvider | string | `"SUN"` | | +| configuration.tls.truststore.truststoreType | string | `"JKS"` | | | containerPorts.http | int | `7200` | | | containerPorts.rpc | int | `7300` | | | dnsConfig | object | `{}` | | diff --git a/files/scripts/graphdb.sh b/files/scripts/graphdb.sh index c7a1caf0..9aed1ab7 100755 --- a/files/scripts/graphdb.sh +++ b/files/scripts/graphdb.sh @@ -21,12 +21,12 @@ function createCluster { echo "Creating cluster" response=$(mktemp) - curl -o "$response" -isSL -m "${timeout}" -X POST \ + curl -k -o "$response" -isSL -m "${timeout}" -X POST \ -d @"$configLocation" \ --header "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" \ --header 'Content-Type: application/json' \ --header 'Accept: */*' \ - "http://${GRAPHDB_POD_NAME}-0.${GRAPHDB_SERVICE_NAME}:${GRAPHDB_SERVICE_PORT}/rest/cluster/config" + "${GRAPHDB_PROTOCOL}://${GRAPHDB_POD_NAME}-0.${GRAPHDB_SERVICE_NAME}:${GRAPHDB_SERVICE_PORT}/rest/cluster/config" if grep -q 'HTTP/1.1 201' "$response"; then echo "Cluster creation successful!" @@ -47,7 +47,7 @@ function waitService { local max_attempts=100 echo "Waiting for ${address}" - until curl --output /dev/null -fsSL -m 5 -H "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" --silent --fail "${address}"; do + until curl -k --output /dev/null -fsSL -m 5 -H "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" --silent --fail "${address}"; do if [[ ${attempt_counter} -eq ${max_attempts} ]];then echo "Max attempts reached" exit 1 @@ -65,7 +65,7 @@ function waitAllNodes { for (( c=node_count; c>0; c )) do c=$((c-1)) - waitService "http://${GRAPHDB_POD_NAME}-$c.${GRAPHDB_SERVICE_NAME}:${GRAPHDB_SERVICE_PORT}/rest/repositories" + waitService "${GRAPHDB_PROTOCOL}://${GRAPHDB_POD_NAME}-$c.${GRAPHDB_SERVICE_NAME}:${GRAPHDB_SERVICE_PORT}/rest/repositories" done } @@ -83,11 +83,11 @@ function createRepositoryFromFile { echo "Provisioning repository ${repositoryName}" response=$( - curl -X POST --connect-timeout 60 --retry 3 --retry-all-errors --retry-delay 10 \ + curl -k -X POST --connect-timeout 60 --retry 3 --retry-all-errors --retry-delay 10 \ -F config=@"${filename}" \ -H "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" \ -H 'Content-Type: multipart/form-data' \ - "http://${GRAPHDB_POD_NAME}-0.${GRAPHDB_SERVICE_NAME}:${GRAPHDB_SERVICE_PORT}/rest/repositories" + "${GRAPHDB_PROTOCOL}://${GRAPHDB_POD_NAME}-0.${GRAPHDB_SERVICE_NAME}:${GRAPHDB_SERVICE_PORT}/rest/repositories" ) if [ -z "$response" ]; then diff --git a/files/scripts/update-cluster.sh b/files/scripts/update-cluster.sh index c21283eb..a0efaa8d 100644 --- a/files/scripts/update-cluster.sh +++ b/files/scripts/update-cluster.sh @@ -9,16 +9,16 @@ function patchCluster { local timeout=$2 local response - waitService "http://${GRAPHDB_PROXY_SERVICE_NAME}:${GRAPHDB_PROXY_SERVICE_PORT}/proxy/ready" + waitService "${GRAPHDB_PROTOCOL}://${GRAPHDB_PROXY_SERVICE_NAME}:${GRAPHDB_PROXY_SERVICE_PORT}/proxy/ready" echo "Patching cluster" response=$(mktemp) - curl -o "$response" -isSL -m "$timeout" -X PATCH \ + curl -k -o "$response" -isSL -m "$timeout" -X PATCH \ --header "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ -d @"$configLocation" \ - "http://${GRAPHDB_PROXY_SERVICE_NAME}:${GRAPHDB_PROXY_SERVICE_PORT}/rest/cluster/config" + "${GRAPHDB_PROTOCOL}://${GRAPHDB_PROXY_SERVICE_NAME}:${GRAPHDB_PROXY_SERVICE_PORT}/rest/cluster/config" if grep -q 'HTTP/1.1 200' "$response"; then echo "Patch successful" @@ -65,16 +65,16 @@ function removeNodes { done nodes=\{\"nodes\":\[${nodes}\]\} - waitService "http://${GRAPHDB_PROXY_SERVICE_NAME}:${GRAPHDB_PROXY_SERVICE_PORT}/proxy/ready" + waitService "${GRAPHDB_PROTOCOL}://${GRAPHDB_PROXY_SERVICE_NAME}:${GRAPHDB_PROXY_SERVICE_PORT}/proxy/ready" echo "Scaling the cluster down" response=$(mktemp) - curl -o "$response" -isSL -m 15 -X DELETE \ + curl -k -o "$response" -isSL -m 15 -X DELETE \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" \ -d "${nodes}" \ - "http://${GRAPHDB_PROXY_SERVICE_NAME}:${GRAPHDB_PROXY_SERVICE_PORT}/rest/cluster/config/node" + "${GRAPHDB_PROTOCOL}://${GRAPHDB_PROXY_SERVICE_NAME}:${GRAPHDB_PROXY_SERVICE_PORT}/rest/cluster/config/node" if grep -q 'HTTP/1.1 200' "$response"; then echo "Scaling down successful." @@ -113,16 +113,16 @@ function addNodes { done nodes=\{\"nodes\":\[${nodes}\]\} - waitService "http://${GRAPHDB_PROXY_SERVICE_NAME}:${GRAPHDB_PROXY_SERVICE_PORT}/proxy/ready" + waitService "${GRAPHDB_PROTOCOL}://${GRAPHDB_PROXY_SERVICE_NAME}:${GRAPHDB_PROXY_SERVICE_PORT}/proxy/ready" echo "Scaling the cluster up" response=$(mktemp) - curl -o "$response" -isSL -m "${timeout}" -X POST \ + curl -k -o "$response" -isSL -m "${timeout}" -X POST \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" \ -d "${nodes}" \ - "http://${GRAPHDB_PROXY_SERVICE_NAME}:${GRAPHDB_PROXY_SERVICE_PORT}/rest/cluster/config/node" + "${GRAPHDB_PROTOCOL}://${GRAPHDB_PROXY_SERVICE_NAME}:${GRAPHDB_PROXY_SERVICE_PORT}/rest/cluster/config/node" if grep -q 'HTTP/1.1 200' "$response"; then echo "Scaling successful." @@ -141,14 +141,14 @@ function addNodes { } function deleteCluster { - waitService "http://${GRAPHDB_POD_NAME}-0.${GRAPHDB_SERVICE_NAME}:${GRAPHDB_SERVICE_PORT}/rest/repositories" + waitService "${GRAPHDB_PROTOCOL}://${GRAPHDB_POD_NAME}-0.${GRAPHDB_SERVICE_NAME}:${GRAPHDB_SERVICE_PORT}/rest/repositories" local response response=$(mktemp) - curl -o "$response" -isSL -m 15 -X DELETE \ + curl -k -o "$response" -isSL -m 15 -X DELETE \ --header "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" \ --header 'Accept: */*' \ - "http://${GRAPHDB_POD_NAME}-0.${GRAPHDB_SERVICE_NAME}:${GRAPHDB_SERVICE_PORT}/rest/cluster/config?force=false" + "${GRAPHDB_PROTOCOL}://${GRAPHDB_POD_NAME}-0.${GRAPHDB_SERVICE_NAME}:${GRAPHDB_SERVICE_PORT}/rest/cluster/config?force=false" if grep -q 'HTTP/1.1 200' "$response"; then echo "Cluster deletion successful!" @@ -163,13 +163,13 @@ function deleteCluster { } function getNodeCountInCurrentCluster { - local node_address="http://${GRAPHDB_POD_NAME}-0.${GRAPHDB_SERVICE_NAME}:${GRAPHDB_SERVICE_PORT}" + local node_address="${GRAPHDB_PROTOCOL}://${GRAPHDB_POD_NAME}-0.${GRAPHDB_SERVICE_NAME}:${GRAPHDB_SERVICE_PORT}" waitService "${node_address}/rest/repositories" local response response=$(mktemp) - curl -o "$response" -isSL -m 15 -X GET \ + curl -k -o "$response" -isSL -m 15 -X GET \ --header 'Content-Type: application/json' \ --header "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" \ --header 'Accept: */*' \ @@ -183,7 +183,7 @@ function waitService { local attempt_counter=0 local max_attempts=100 - until curl --output /dev/null -fsSL -m 5 -H "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" --silent --fail "${address}"; do + until curl -k --output /dev/null -fsSL -m 5 -H "Authorization: Basic ${GRAPHDB_AUTH_TOKEN}" --silent --fail "${address}"; do if [[ ${attempt_counter} -eq ${max_attempts} ]]; then echo "Max attempts reached" exit 1 diff --git a/templates/_helpers.tpl b/templates/_helpers.tpl index d55768e1..dd35eaca 100644 --- a/templates/_helpers.tpl +++ b/templates/_helpers.tpl @@ -57,8 +57,9 @@ Renders the HTTP address of each GraphDB node that is part of the cluster, joine {{- $namespace := include "graphdb.namespace" . -}} {{- $cluster_domain := .Values.global.clusterDomain -}} {{- $service_http_port := .Values.headlessService.ports.http -}} + {{- $protocol := ternary "https" "http" (ne .Values.configuration.tls.keystore.existingSecret "") }} {{- range $i, $node_index := until (int .Values.replicas) -}} - http://{{ $pod_name }}-{{ $node_index }}.{{ $service_name }}.{{ $namespace }}.svc.{{ $cluster_domain }}:{{ $service_http_port }} + {{ $protocol }}://{{ $pod_name }}-{{ $node_index }}.{{ $service_name }}.{{ $namespace }}.svc.{{ $cluster_domain }}:{{ $service_http_port }} {{- if gt (sub (int $.Values.replicas) 1) $node_index -}} {{- ", " -}} {{- end -}} diff --git a/templates/graphdb/configmap-properties.yaml b/templates/graphdb/configmap-properties.yaml index f7ba9104..e4d12078 100644 --- a/templates/graphdb/configmap-properties.yaml +++ b/templates/graphdb/configmap-properties.yaml @@ -22,11 +22,61 @@ data: {{- if eq (int .Values.replicas) 1}} graphdb.external-url={{ include "graphdb.external-url" . }} {{- end }} + + {{- with .Values.configuration.tls }} + {{- if .keystore.existingSecret }} + graphdb.connector.SSLEnabled = true + graphdb.connector.scheme = https + graphdb.connector.secure = true + graphdb.connector.keystoreFile=/etc/graphdb/connector-keystore/connector-keystore.jks + graphdb.connector.keyAlias={{ .keystore.keyAlias }} + graphdb.connector.keystoreProvider={{ .keystore.keystoreProvider }} + graphdb.connector.keystoreType={{ .keystore.keystoreType }} + {{- end }} + {{- if .truststore.existingSecret }} + graphdb.connector.truststoreFile=/etc/graphdb/connector-truststore/connector-truststore.jks + graphdb.connector.truststoreProvider={{ .truststore.truststoreProvider }} + graphdb.connector.truststoreType={{ .truststore.truststoreType }} + {{- end }} + {{- if .certificateRevocationList.existingSecret}} + graphdb.connector.certificateRevocationListFile=/etc/graphdb/connector-certificate-revocation-list/connector-certificate-revocation-list.pem + {{- end }} + {{- end }} + {{- with .Values.cluster.tls }} + graphdb.raft.security.mode={{ .mode }} + {{- if .privateKey.existingSecret }} + graphdb.raft.security.certificateKeyFile=/etc/graphdb/cluster-private-key/cluster-private-key.pem + {{- end }} + {{- if .certificate.existingSecret }} + graphdb.raft.security.certificateFile=/etc/graphdb/cluster-certificate/cluster-certificate.pem + {{- end }} + {{- if .certificateChain.existingSecret }} + graphdb.raft.security.certificateChainFile=/etc/graphdb/cluster-certificate-chain/cluster-certificate-chain.pem + {{- end }} + {{- if .keystore.existingSecret }} + graphdb.raft.security.keystoreFile=/etc/graphdb/cluster-keystore/cluster-keystore.jks + graphdb.raft.security.keyAlias={{ .keystore.keyAlias }} + graphdb.raft.security.keystoreProvider={{ .keystore.keystoreProvider }} + graphdb.raft.security.keystoreType={{ .keystore.keystoreType }} + {{- end }} + {{- if .truststore.existingSecret }} + graphdb.raft.security.truststoreFile=/etc/graphdb/cluster-truststore/cluster-truststore.jks + graphdb.raft.security.truststoreProvider={{ .truststore.truststoreProvider }} + graphdb.raft.security.truststoreType={{ .truststore.truststoreType }} + {{- end }} + {{- if .rootCerts.existingSecret }} + graphdb.raft.security.rootCerts=/etc/graphdb/cluster-root-certs/cluster-root-certs.pem + {{- end }} + {{- if .certificateRevocationList.existingSecret }} + graphdb.raft.security.certificateRevocationListFile=/etc/graphdb/cluster-certificate-revocation-list/cluster-certificate-revocation-list.pem + {{- end }} + {{- end }} + {{- if .Values.configuration.properties }} ##### Overrides from values.yaml ##### {{- range $key, $val := .Values.configuration.properties -}} {{- if ne $val nil }} - {{ $key }}={{ tpl ($val | toString) $ | quote }} + {{ $key }}={{ tpl ($val | toString) $ }} {{- end }} {{- end -}} {{- end -}} diff --git a/templates/graphdb/secret-properties.yaml b/templates/graphdb/secret-properties.yaml index 54e13ba5..444ef0ed 100644 --- a/templates/graphdb/secret-properties.yaml +++ b/templates/graphdb/secret-properties.yaml @@ -20,7 +20,7 @@ stringData: ##### Secrets overrides from values.yaml ##### {{- range $key, $val := .Values.configuration.secretProperties -}} {{- if ne $val nil }} - {{ $key }}={{ tpl ($val | toString) $ | quote }} + {{ $key }}={{ tpl ($val | toString) $ }} {{- end }} {{- end -}} {{- end -}} diff --git a/templates/graphdb/statefulset.yaml b/templates/graphdb/statefulset.yaml index 3aca1d86..024f5b17 100644 --- a/templates/graphdb/statefulset.yaml +++ b/templates/graphdb/statefulset.yaml @@ -127,6 +127,90 @@ spec: secret: secretName: {{ (tpl .Values.security.initialUsers.existingSecret .) | default (include "graphdb.fullname.secret.initial-users" .) }} {{- end }} + {{- with .Values.configuration.tls }} + {{- if .keystore.existingSecret }} + - name: graphdb-connector-keystore + secret: + secretName: {{ .keystore.existingSecret }} + items: + - key: {{ .keystore.keystoreKey }} + path: connector-keystore.jks + {{- end }} + {{- if .truststore.existingSecret }} + - name: graphdb-connector-truststore + secret: + secretName: {{ .truststore.existingSecret }} + items: + - key: {{ .truststore.truststoreKey }} + path: connector-truststore.jks + {{- end }} + {{- if .certificateRevocationList.existingSecret }} + - name: graphdb-connector-certificate-revocation-list + secret: + secretName: {{ .certificateRevocationList.existingSecret }} + items: + - key: {{ .certificateRevocationList.certificateRevocationListKey }} + path: connector-certificate-revocation-list.pem + {{- end }} + {{- end }} + {{- with .Values.cluster.tls }} + {{- if .keystore.existingSecret }} + - name: graphdb-cluster-keystore + secret: + secretName: {{ .keystore.existingSecret }} + items: + - key: {{ .keystore.keystoreKey }} + path: cluster-keystore.jks + {{- end }} + {{- if .truststore.existingSecret }} + - name: graphdb-cluster-truststore + secret: + secretName: {{ .truststore.existingSecret }} + items: + - key: {{ .truststore.truststoreKey }} + path: cluster-truststore.jks + {{- end }} + {{- if .privateKey.existingSecret }} + - name: graphdb-cluster-private-key + secret: + secretName: {{ .privateKey.existingSecret }} + items: + - key: {{ .privateKey.privateKeyKey }} + path: cluster-private-key.pem + {{- end }} + {{- if .certificate.existingSecret }} + - name: graphdb-cluster-certificate + secret: + secretName: {{ .certificate.existingSecret }} + items: + - key: {{ .certificate.certificateKey }} + path: cluster-certificate.pem + {{- end }} + {{- if .certificateChain.existingSecret }} + - name: graphdb-cluster-certificate-chain + secret: + secretName: {{ .certificateChain.existingSecret }} + items: + - key: {{ .certificateChain.certificateChainKey }} + path: cluster-certificate-chain.pem + {{- end }} + {{- if .rootCerts.existingSecret }} + - name: graphdb-cluster-root-certs + secret: + secretName: {{ .rootCerts.existingSecret }} + items: + - key: {{ .rootCerts.rootCertsKey }} + path: cluster-root-certs.pem + {{- end }} + {{- if .certificateRevocationList.existingSecret }} + - name: graphdb-cluster-certificate-revocation-list + secret: + secretName: {{ .certificateRevocationList.existingSecret }} + items: + - key: {{ .certificateRevocationList.certificateRevocationListKey }} + path: cluster-certificate-revocation-list.pem + {{- end }} + {{- end }} {{- with .Values.extraVolumes }} {{- tpl (toYaml .) $ | nindent 8 }} {{- end }} @@ -337,9 +421,49 @@ spec: {{- with .Values.extraEnvFrom }} {{- tpl (toYaml .) $ | nindent 12 }} {{- end }} - {{- with .Values.extraEnv }} - env: {{- tpl (toYaml .) $ | nindent 12 }} - {{- end }} + env: + {{- with .Values.configuration.tls }} + {{- if .keystore.existingSecret }} + - name: graphdb.connector.keystorePass + valueFrom: + secretKeyRef: + name: {{ .keystore.existingSecret }} + key: {{ .keystore.keystorePasswordKey }} + {{- end }} + {{- if .truststore.existingSecret }} + - name: graphdb.connector.truststorePass + valueFrom: + secretKeyRef: + name: {{ .truststore.existingSecret }} + key: {{ .truststore.truststorePasswordKey }} + {{- end }} + {{- end }} + {{- with .Values.cluster.tls }} + {{- if .keystore.existingSecret }} + - name: graphdb.raft.security.keystorePass + valueFrom: + secretKeyRef: + name: {{ .keystore.existingSecret }} + key: {{ .keystore.keystorePasswordKey }} + {{- end }} + {{- if .truststore.existingSecret }} + - name: graphdb.raft.security.truststorePass + valueFrom: + secretKeyRef: + name: {{ .truststore.existingSecret }} + key: {{ .truststore.truststorePasswordKey }} + {{- end }} + {{- if .privateKey.existingSecret }} + - name: graphdb.raft.security.certificateKeyPassword + valueFrom: + secretKeyRef: + name: {{ .privateKey.existingSecret }} + key: {{ .privateKey.privateKeyPasswordKey }} + {{- end }} + {{- end }} + {{- with .Values.extraEnv }} + {{- tpl (toYaml .) $ | nindent 12 }} + {{- end }} volumeMounts: - name: {{ .Values.persistence.volumeClaimTemplate.name }} mountPath: /opt/graphdb/home @@ -359,6 +483,50 @@ spec: - name: {{ .Values.import.volumeMount.volumeClaimTemplate.name }} mountPath: /opt/graphdb/home/graphdb-import {{- end }} + {{- with .Values.configuration.tls }} + {{- if .keystore.existingSecret }} + - name: graphdb-connector-keystore + mountPath: /etc/graphdb/connector-keystore + {{- end }} + {{- if .truststore.existingSecret }} + - name: graphdb-connector-truststore + mountPath: /etc/graphdb/connector-truststore + {{- end }} + {{- if .certificateRevocationList.existingSecret }} + - name: graphdb-connector-certificate-revocation-list + mountPath: /etc/graphdb/connector-certificate-revocation-list + {{- end }} + {{- end }} + {{- with .Values.cluster.tls }} + {{- if .keystore.existingSecret }} + - name: graphdb-cluster-keystore + mountPath: /etc/graphdb/cluster-keystore + {{- end }} + {{- if .truststore.existingSecret }} + - name: graphdb-cluster-truststore + mountPath: /etc/graphdb/cluster-truststore + {{- end }} + {{- if .privateKey.existingSecret }} + - name: graphdb-cluster-private-key + mountPath: /etc/graphdb/cluster-private-key + {{- end }} + {{- if .certificate.existingSecret }} + - name: graphdb-cluster-certificate + mountPath: /etc/graphdb/cluster-certificate + {{- end }} + {{- if .certificateChain.existingSecret }} + - name: graphdb-cluster-certificate-chain + mountPath: /etc/graphdb/cluster-certificate-chain + {{- end }} + {{- if .rootCerts.existingSecret }} + - name: graphdb-cluster-root-certs + mountPath: /etc/graphdb/cluster-root-certs + {{- end }} + {{- if .certificateRevocationList.existingSecret }} + - name: graphdb-cluster-certificate-revocation-list + mountPath: /etc/graphdb/cluster-certificate-revocation-list + {{- end }} + {{- end }} {{- with .Values.extraVolumeMounts }} {{- tpl (toYaml .) $ | nindent 12 }} {{- end }} diff --git a/templates/jobs/job-create-cluster.yaml b/templates/jobs/job-create-cluster.yaml index ca4a5ccc..a5a5ceab 100644 --- a/templates/jobs/job-create-cluster.yaml +++ b/templates/jobs/job-create-cluster.yaml @@ -71,6 +71,8 @@ spec: value: {{ include "graphdb.fullname.service.headless" . }} - name: GRAPHDB_SERVICE_PORT value: {{ .Values.headlessService.ports.http | quote }} + - name: GRAPHDB_PROTOCOL + value: {{ ternary "https" "http" (ne .Values.configuration.tls.keystore.existingSecret "") }} - name: GRAPHDB_AUTH_TOKEN valueFrom: secretKeyRef: diff --git a/templates/jobs/job-patch-cluster.yaml b/templates/jobs/job-patch-cluster.yaml index 80e0fe05..2445a248 100644 --- a/templates/jobs/job-patch-cluster.yaml +++ b/templates/jobs/job-patch-cluster.yaml @@ -75,6 +75,8 @@ spec: value: {{ include "graphdb-proxy.fullname" . }} - name: GRAPHDB_PROXY_SERVICE_PORT value: {{ .Values.proxy.headlessService.ports.http | quote }} + - name: GRAPHDB_PROTOCOL + value: {{ ternary "https" "http" (ne .Values.configuration.tls.keystore.existingSecret "") }} - name: GRAPHDB_AUTH_TOKEN valueFrom: secretKeyRef: diff --git a/templates/jobs/job-provision-repositories.yaml b/templates/jobs/job-provision-repositories.yaml index 70e540ad..c50c8716 100644 --- a/templates/jobs/job-provision-repositories.yaml +++ b/templates/jobs/job-provision-repositories.yaml @@ -71,6 +71,8 @@ spec: value: {{ include "graphdb.fullname.service.headless" . }} - name: GRAPHDB_SERVICE_PORT value: {{ .Values.headlessService.ports.http | quote }} + - name: GRAPHDB_PROTOCOL + value: {{ ternary "https" "http" (ne .Values.configuration.tls.keystore.existingSecret "") }} - name: GRAPHDB_AUTH_TOKEN valueFrom: secretKeyRef: diff --git a/templates/jobs/job-scale-down-cluster.yaml b/templates/jobs/job-scale-down-cluster.yaml index 623be45b..28ff4179 100644 --- a/templates/jobs/job-scale-down-cluster.yaml +++ b/templates/jobs/job-scale-down-cluster.yaml @@ -73,6 +73,8 @@ spec: value: {{ include "graphdb-proxy.fullname" . }} - name: GRAPHDB_PROXY_SERVICE_PORT value: {{ .Values.proxy.headlessService.ports.http | quote }} + - name: GRAPHDB_PROTOCOL + value: {{ ternary "https" "http" (ne .Values.configuration.tls.keystore.existingSecret "") }} - name: GRAPHDB_AUTH_TOKEN valueFrom: secretKeyRef: diff --git a/templates/jobs/job-scale-up-cluster.yaml b/templates/jobs/job-scale-up-cluster.yaml index b7770230..a855156b 100644 --- a/templates/jobs/job-scale-up-cluster.yaml +++ b/templates/jobs/job-scale-up-cluster.yaml @@ -74,6 +74,8 @@ spec: value: {{ include "graphdb-proxy.fullname" . }} - name: GRAPHDB_PROXY_SERVICE_PORT value: {{ .Values.proxy.headlessService.ports.http | quote }} + - name: GRAPHDB_PROTOCOL + value: {{ ternary "https" "http" (ne .Values.configuration.tls.keystore.existingSecret "") }} - name: GRAPHDB_AUTH_TOKEN valueFrom: secretKeyRef: diff --git a/templates/proxy/configmap-properties.yaml b/templates/proxy/configmap-properties.yaml index 8f572855..a7bcd4f3 100644 --- a/templates/proxy/configmap-properties.yaml +++ b/templates/proxy/configmap-properties.yaml @@ -16,11 +16,61 @@ data: # See https://graphdb.ontotext.com/documentation/ for supported properties graphdb.connector.port={{ .Values.proxy.containerPorts.http }} graphdb.proxy.hosts={{ include "graphdb-proxy.cluster.nodes" . }} + + {{- with .Values.configuration.tls }} + {{- if .keystore.existingSecret }} + graphdb.connector.SSLEnabled = true + graphdb.connector.scheme = https + graphdb.connector.secure = true + graphdb.connector.keystoreFile=/etc/graphdb/connector-keystore/connector-keystore.jks + graphdb.connector.keyAlias={{ .keystore.keyAlias }} + graphdb.connector.keystoreProvider={{ .keystore.keystoreProvider }} + graphdb.connector.keystoreType={{ .keystore.keystoreType }} + {{- end }} + {{- if .truststore.existingSecret }} + graphdb.connector.truststoreFile=/etc/graphdb/connector-truststore/connector-truststore.jks + graphdb.connector.truststoreProvider={{ .truststore.truststoreProvider }} + graphdb.connector.truststoreType={{ .truststore.truststoreType }} + {{- end }} + {{- if .certificateRevocationList.existingSecret}} + graphdb.connector.certificateRevocationListFile=/etc/graphdb/connector-certificate-revocation-list/connector-certificate-revocation-list.pem + {{- end }} + {{- end }} + {{- with .Values.cluster.tls }} + graphdb.raft.security.mode={{ .mode }} + {{- if .privateKey.existingSecret }} + graphdb.raft.security.certificateKeyFile=/etc/graphdb/cluster-private-key/cluster-private-key.pem + {{- end }} + {{- if .certificate.existingSecret }} + graphdb.raft.security.certificateFile=/etc/graphdb/cluster-certificate/cluster-certificate.pem + {{- end }} + {{- if .certificateChain.existingSecret }} + graphdb.raft.security.certificateChainFile=/etc/graphdb/cluster-certificate-chain/cluster-certificate-chain.pem + {{- end }} + {{- if .keystore.existingSecret }} + graphdb.raft.security.keystoreFile=/etc/graphdb/cluster-keystore/cluster-keystore.jks + graphdb.raft.security.keyAlias={{ .keystore.keyAlias }} + graphdb.raft.security.keystoreProvider={{ .keystore.keystoreProvider }} + graphdb.raft.security.keystoreType={{ .keystore.keystoreType }} + {{- end }} + {{- if .truststore.existingSecret }} + graphdb.raft.security.truststoreFile=/etc/graphdb/cluster-truststore/cluster-truststore.jks + graphdb.raft.security.truststoreProvider={{ .truststore.truststoreProvider }} + graphdb.raft.security.truststoreType={{ .truststore.truststoreType }} + {{- end }} + {{- if .rootCerts.existingSecret }} + graphdb.raft.security.rootCerts=/etc/graphdb/cluster-root-certs/cluster-root-certs.pem + {{- end }} + {{- if .certificateRevocationList.existingSecret }} + graphdb.raft.security.certificateRevocationListFile=/etc/graphdb/cluster-certificate-revocation-list/cluster-certificate-revocation-list.pem + {{- end }} + {{- end }} + {{- if .Values.proxy.configuration.properties }} ##### Overrides from values.yaml ##### {{- range $key, $val := .Values.proxy.configuration.properties -}} {{- if ne $val nil }} - {{ $key }}={{ tpl ($val | toString) $ | quote }} + {{ $key }}={{ tpl ($val | toString) $ }} {{- end }} {{- end -}} {{- end -}} diff --git a/templates/proxy/secret-properties.yaml b/templates/proxy/secret-properties.yaml index f2c079c5..968f66b3 100644 --- a/templates/proxy/secret-properties.yaml +++ b/templates/proxy/secret-properties.yaml @@ -21,7 +21,7 @@ stringData: ##### Secrets overrides from values.yaml ##### {{- range $key, $val := .Values.proxy.configuration.secretProperties -}} {{- if ne $val nil }} - {{ $key }}={{ tpl ($val | toString) $ | quote }} + {{ $key }}={{ tpl ($val | toString) $ }} {{- end }} {{- end -}} {{- end -}} diff --git a/templates/proxy/statefulset.yaml b/templates/proxy/statefulset.yaml index 71eaf102..3156e942 100644 --- a/templates/proxy/statefulset.yaml +++ b/templates/proxy/statefulset.yaml @@ -95,6 +95,90 @@ spec: configMap: name: {{ tpl .Values.proxy.configuration.logback.existingConfigmap . }} {{- end }} + {{- with .Values.configuration.tls }} + {{- if .keystore.existingSecret }} + - name: graphdb-connector-keystore + secret: + secretName: {{ .keystore.existingSecret }} + items: + - key: {{ .keystore.keystoreKey }} + path: connector-keystore.jks + {{- end }} + {{- if .truststore.existingSecret }} + - name: graphdb-connector-truststore + secret: + secretName: {{ .truststore.existingSecret }} + items: + - key: {{ .truststore.truststoreKey }} + path: connector-truststore.jks + {{- end }} + {{- if .certificateRevocationList.existingSecret }} + - name: graphdb-connector-certificate-revocation-list + secret: + secretName: {{ .certificateRevocationList.existingSecret }} + items: + - key: {{ .certificateRevocationList.certificateRevocationListKey }} + path: connector-certificate-revocation-list.pem + {{- end }} + {{- end }} + {{- with .Values.cluster.tls }} + {{- if .keystore.existingSecret }} + - name: graphdb-cluster-keystore + secret: + secretName: {{ .keystore.existingSecret }} + items: + - key: {{ .keystore.keystoreKey }} + path: cluster-keystore.jks + {{- end }} + {{- if .truststore.existingSecret }} + - name: graphdb-cluster-truststore + secret: + secretName: {{ .truststore.existingSecret }} + items: + - key: {{ .truststore.truststoreKey }} + path: cluster-truststore.jks + {{- end }} + {{- if .privateKey.existingSecret }} + - name: graphdb-cluster-private-key + secret: + secretName: {{ .privateKey.existingSecret }} + items: + - key: {{ .privateKey.privateKeyKey }} + path: cluster-private-key.pem + {{- end }} + {{- if .certificate.existingSecret }} + - name: graphdb-cluster-certificate + secret: + secretName: {{ .certificate.existingSecret }} + items: + - key: {{ .certificate.certificateKey }} + path: cluster-certificate.pem + {{- end }} + {{- if .certificateChain.existingSecret }} + - name: graphdb-cluster-certificate-chain + secret: + secretName: {{ .certificateChain.existingSecret }} + items: + - key: {{ .certificateChain.certificateChainKey }} + path: cluster-certificate-chain.pem + {{- end }} + {{- if .rootCerts.existingSecret }} + - name: graphdb-cluster-root-certs + secret: + secretName: {{ .rootCerts.existingSecret }} + items: + - key: {{ .rootCerts.rootCertsKey }} + path: cluster-root-certs.pem + {{- end }} + {{- if .certificateRevocationList.existingSecret }} + - name: graphdb-cluster-certificate-revocation-list + secret: + secretName: {{ .certificateRevocationList.existingSecret }} + items: + - key: {{ .certificateRevocationList.certificateRevocationListKey }} + path: cluster-certificate-revocation-list.pem + {{- end }} + {{- end }} {{- with .Values.proxy.extraVolumes }} {{- tpl (toYaml .) $ | nindent 8 }} {{- end }} @@ -277,8 +361,48 @@ spec: {{- with .Values.proxy.extraEnvFrom }} {{- tpl (toYaml .) $ | nindent 12 }} {{- end }} + env: + {{- with .Values.configuration.tls }} + {{- if .keystore.existingSecret }} + - name: graphdb.connector.keystorePass + valueFrom: + secretKeyRef: + name: {{ .keystore.existingSecret }} + key: {{ .keystore.keystorePasswordKey }} + {{- end }} + {{- if .truststore.existingSecret }} + - name: graphdb.connector.truststorePass + valueFrom: + secretKeyRef: + name: {{ .truststore.existingSecret }} + key: {{ .truststore.truststorePasswordKey }} + {{- end }} + {{- end }} + {{- with .Values.cluster.tls }} + {{- if .keystore.existingSecret }} + - name: graphdb.raft.security.keystorePass + valueFrom: + secretKeyRef: + name: {{ .keystore.existingSecret }} + key: {{ .keystore.keystorePasswordKey }} + {{- end }} + {{- if .truststore.existingSecret }} + - name: graphdb.raft.security.truststorePass + valueFrom: + secretKeyRef: + name: {{ .truststore.existingSecret }} + key: {{ .truststore.truststorePasswordKey }} + {{- end }} + {{- if .privateKey.existingSecret }} + - name: graphdb.raft.security.certificateKeyPassword + valueFrom: + secretKeyRef: + name: {{ .privateKey.existingSecret }} + key: {{ .privateKey.privateKeyPasswordKey }} + {{- end }} + {{- end }} {{- with .Values.proxy.extraEnv }} - env: {{- tpl (toYaml .) $ | nindent 12 }} + {{- tpl (toYaml .) $ | nindent 12 }} {{- end }} ports: - name: http @@ -296,6 +420,50 @@ spec: mountPath: /opt/graphdb/home/conf/logback.xml subPath: {{ .Values.proxy.configuration.logback.configmapKey }} {{- end }} + {{- with .Values.configuration.tls }} + {{- if .keystore.existingSecret }} + - name: graphdb-connector-keystore + mountPath: /etc/graphdb/connector-keystore/ + {{- end }} + {{- if .truststore.existingSecret }} + - name: graphdb-connector-truststore + mountPath: /etc/graphdb/connector-truststore/ + {{- end }} + {{- if .certificateRevocationList.existingSecret }} + - name: graphdb-connector-certificate-revocation-list + mountPath: /etc/graphdb/connector-certificate-revocation-list/ + {{- end }} + {{- end }} + {{- with .Values.cluster.tls }} + {{- if .keystore.existingSecret }} + - name: graphdb-cluster-keystore + mountPath: /etc/graphdb/cluster-keystore/ + {{- end }} + {{- if .truststore.existingSecret }} + - name: graphdb-cluster-truststore + mountPath: /etc/graphdb/cluster-truststore/ + {{- end }} + {{- if .privateKey.existingSecret }} + - name: graphdb-cluster-private-key + mountPath: /etc/graphdb/cluster-private-key/ + {{- end }} + {{- if .certificate.existingSecret }} + - name: graphdb-cluster-certificate + mountPath: /etc/graphdb/cluster-certificate/ + {{- end }} + {{- if .certificateChain.existingSecret }} + - name: graphdb-cluster-certificate-chain + mountPath: /etc/graphdb/cluster-certificate-chain/ + {{- end }} + {{- if .rootCerts.existingSecret }} + - name: graphdb-cluster-root-certs + mountPath: /etc/graphdb/cluster-root-certs/ + {{- end }} + {{- if .certificateRevocationList.existingSecret }} + - name: graphdb-cluster-certificate-revocation-list + mountPath: /etc/graphdb/cluster-certificate-revocation-list/ + {{- end }} + {{- end }} {{- with .Values.proxy.extraVolumeMounts }} {{- toYaml . | nindent 12 }} {{- end }} diff --git a/values.yaml b/values.yaml index 021cbb79..3500d6cd 100644 --- a/values.yaml +++ b/values.yaml @@ -209,6 +209,69 @@ configuration: # The value is processed as a Helm template. javaArguments: "" + # Configuring the GraphDB embedded Tomcat server security properties. + # GraphDB uses the Java implementation of SSL, which requires a configured key in the Java keystore. + # There are 2 ways to configure the security of the GraphDB instance: + # - By providing a keystore and its corresponding properties. + # - By providing keystore and truststore and their corresponding properties - used to configure mTLS. + # Only truststore can also be provided without needing to configure a keystone + # in cases where GraphDB should trust an external service. + # + # NOTE + # Since the GraphDB container and proxy container probes also have to use https + # they need to be manually configured e.g.: + # startupProbe: + # httpGet: + # scheme: HTTPS # Add scheme + # Configurations for the liveness and readiness probes need to be added as well. + # + # If the GraphDB instance is configured with SSL, the cluster security properties will + # default to the values defined in the connector unless explicitly specified otherwise! + # Tomcat docs: https://tomcat.apache.org/tomcat-9.0-doc/config/http.html#SSL_Support_-_Connector_-_NIO_and_NIO2_(deprecated) + # Official GraphDB docs: https://graphdb.ontotext.com/documentation/10.7/encryption.html#configuring-graphdb-instance-with-ssl + tls: + # If keystore secret is provided enables connector security by setting the following GraphDB properties: + # graphdb.connector.SSLEnabled = true + # graphdb.connector.scheme = https + # graphdb.connector.secure = true + keystore: + # The value is processed as a Helm template + existingSecret: "" + # Key in the existing Secret that holds the keystore file where you have stored the + # server certificate and key to be loaded. + keystoreKey: keystore.jks + # Key in the existing Secret that holds the password to use to access the keystore containing + # the server's private key and certificate. If not specified, a default of "changeit" will be used. + keystorePasswordKey: pass + # The alias used for the server key and certificate in the keystore. + keyAlias: mykey + # The name of the keystore provider to be used for the server certificate. + # If not explicitly defined, it will be created. + keystoreProvider: SUN + # The type of keystore file to be used for the server certificate. + # If not explicitly defined, it will be created. + keystoreType: JKS + + truststore: + # The value is processed as a Helm template + existingSecret: "" + # Key in the existing Secret that holds the trust store file to use to validate client certificates. + truststoreKey: truststore.jks + # Key in the existing Secret that holds the password to access the trust store. + truststorePasswordKey: pass + # The name of the truststore provider to be used for the server certificate. + # If not explicitly defined, it will be created. + truststoreProvider: SUN + # The type of key store used for the trust store. + # If not explicitly defined, it will be created. + truststoreType: JKS + + certificateRevocationList: + # The value is processed as a Helm template + existingSecret: "" + # Key in the existing Secret that holds the certificate revocation list file. + certificateRevocationListKey: crl.pem + # Configurations for GraphDB's Logback # Ref: https://graphdb.ontotext.com/documentation/10.7/diagnosing-and-reporting-critical-errors.html#logs # @@ -330,6 +393,106 @@ cluster: # Timeout for cURL queries used for the cluster creation and update. clusterCreationTimeout: 60 + # There are 3 combinations of TLS assets that could be provided in order to set up cluster security: + # - Using JSSE: + # By providing keystore and truststore and their corresponding properties. + # - Using OpenSSL: + # By providing certificate file, certificate chain and private key and their corresponding properties. + # - Using a certificate without chain path: + # By providing certificate file and private key and their corresponding properties. + # + # If the TLS assets for all scenarios are provided at once it will result in an error! + tls: + # There are 3 types of security mode configurations + # - NONE + # Unsecured communication will be used for the gRPC client-server communications. + # If mode is not specified it will use this configuration by default. + # - DEFAULT + # TLS encryption will be used if the TLS assets for configuring the security communications are found. + # - TLS + # TLS encryption will be enforced for the cluster communication. + # + # TLS assets need to be provided and If not properly configured the server will fail to start! + # Most of the possible properties can be seen from the official tomcat connector documentation without + # the graphdb.raft.security prefix. + # Tomcat docs: https://tomcat.apache.org/tomcat-9.0-doc/config/http.html#SSL_Support_-_Certificate + # Official GraphDB docs: https://graphdb.ontotext.com/documentation/10.7/directories-and-config-properties.html#cluster-properties + mode: DEFAULT + + privateKey: + # The value is processed as a Helm template + existingSecret: "" + # Key in the existing Secret that holds the file that contains the server private key. + # The format is PEM-encoded. + privateKeyKey: privatekey.pem + # The key in the existing Secret that holds the password used to access the private key associated + # with the server certificate from the specified file. + privateKeyPasswordKey: pass + + certificate: + # The value is processed as a Helm template + existingSecret: "" + # Key in the existing Secret that holds the file that contains the server certificate. + # The format is PEM-encoded. + certificateKey: certificate.pem + + certificateChain: + # The value is processed as a Helm template + existingSecret: "" + # Key in the existing Secret that holds the file that contains the certificate chain associated with + # the server certificate used. + # The format is PEM-encoded. + certificateChainKey: certChain.pem + + keystore: + # The value is processed as a Helm template + existingSecret: "" + # Key in the existing Secret that holds the keystore file where you have stored the + # server certificate and key to be loaded. + keystoreKey: keystore.jks + # Key in the existing Secret that holds the password to use to access the keystore containing + # the server's private key and certificate. If not specified, a default of "changeit" will be used. + keystorePasswordKey: pass + # The alias used for the server key and certificate in the keystore. + keyAlias: mykey + # The name of the keystore provider to be used for the server certificate. + # If it isn't set the list of registered providers is traversed in preference + # order and the first provider that supports the keystoreType is used. + keystoreProvider: SUN + # The type of keystore file to be used for the server certificate. + # If not set a default value of "JKS" is used. + keystoreType: JKS + + truststore: + # The value is processed as a Helm template + existingSecret: "" + # Key in the existing Secret that holds the trust store file to use to validate client certificates. + truststoreKey: truststore.jks + # Key in the existing Secret that holds the password to access the trust store. + truststorePasswordKey: pass + # The name of the truststore provider to be used for the server certificate. + # If it isn't set the list of registered providers is traversed in preference + # order and the first provider that supports the truststoreProvider is used. + truststoreProvider: SUN + # The type of key store used for the trust store. + # If not set a default value of "JKS" is used. + truststoreType: JKS + + # Specifies the root certificates that the system should trust when establishing security connections. + rootCerts: + # The value is processed as a Helm template + existingSecret: "" + # Key in the existing Secret that holds the root certs file. + rootCertsKey: rootCerts.pem + + # Determines a list of digital certificates that have been revoked by the issuing certificate authority (CA) + # before their actual or assigned expiration date. + certificateRevocationList: + # The value is processed as a Helm template + existingSecret: "" + # Key in the existing Secret that holds the certificate revocation list file. + certificateRevocationListKey: crl.pem + # Cluster configuration parameters. # Changing the parameters would trigger a Job that patches the configuration. # Ref: https://graphdb.ontotext.com/documentation/10.7/creating-a-cluster.html#creation-parameters