diff --git a/Makefile b/Makefile index af09b6ce00..83c7f2a34e 100644 --- a/Makefile +++ b/Makefile @@ -396,20 +396,14 @@ postgres-reset: c .PHONY: es-reset es-reset: c - ./dist/brig-index reset \ - --elasticsearch-index-prefix directory \ - --elasticsearch-server https://localhost:9200 \ - --elasticsearch-ca-cert ./libs/wire-subsystems/test/resources/elasticsearch-ca.pem \ - --elasticsearch-credentials ./libs/wire-subsystems/test/resources/elasticsearch-credentials.yaml > /dev/null - ./dist/brig-index reset \ - --elasticsearch-index-prefix directory2 \ - --elasticsearch-server https://localhost:9200 \ - --elasticsearch-ca-cert ./libs/wire-subsystems/test/resources/elasticsearch-ca.pem \ - --elasticsearch-credentials ./libs/wire-subsystems/test/resources/elasticsearch-credentials.yaml > /dev/null + ./dist/brig-index \ + -c ./services/brig/brig.integration.yaml reset \ + --elasticsearch-index-prefix directory > /dev/null + ./dist/brig-index \ + -c ./services/brig/brig.integration.yaml reset \ + --elasticsearch-index-prefix directory2 > /dev/null ./integration/scripts/integration-dynamic-backends-brig-index.sh \ - --elasticsearch-server https://localhost:9200 \ - --elasticsearch-ca-cert ./libs/wire-subsystems/test/resources/elasticsearch-ca.pem \ - --elasticsearch-credentials ./libs/wire-subsystems/test/resources/elasticsearch-credentials.yaml > /dev/null + -c ./services/brig/brig.integration.yaml > /dev/null .PHONY: rabbitmq-reset rabbitmq-reset: rabbit-clean @@ -427,20 +421,7 @@ db-migrate: c ./dist/gundeck-schema --keyspace gundeck_test2 --replication-factor 1 > /dev/null ./dist/spar-schema --keyspace spar_test2 --replication-factor 1 > /dev/null ./integration/scripts/integration-dynamic-backends-db-schemas.sh --replication-factor 1 > /dev/null - ./dist/brig-index reset \ - --elasticsearch-index-prefix directory \ - --elasticsearch-server https://localhost:9200 \ - --elasticsearch-ca-cert ./libs/wire-subsystems/test/resources/elasticsearch-ca.pem \ - --elasticsearch-credentials ./libs/wire-subsystems/test/resources/elasticsearch-credentials.yaml > /dev/null - ./dist/brig-index reset \ - --elasticsearch-index-prefix directory2 \ - --elasticsearch-server https://localhost:9200 \ - --elasticsearch-ca-cert ./libs/wire-subsystems/test/resources/elasticsearch-ca.pem \ - --elasticsearch-credentials ./libs/wire-subsystems/test/resources/elasticsearch-credentials.yaml > /dev/null - ./integration/scripts/integration-dynamic-backends-brig-index.sh \ - --elasticsearch-server https://localhost:9200 \ - --elasticsearch-ca-cert ./libs/wire-subsystems/test/resources/elasticsearch-ca.pem \ - --elasticsearch-credentials ./libs/wire-subsystems/test/resources/elasticsearch-credentials.yaml > /dev/null + make es-reset ################################# ## dependencies diff --git a/changelog.d/5-internal/brig-index-config-dedup b/changelog.d/5-internal/brig-index-config-dedup new file mode 100644 index 0000000000..cb01edc3ab --- /dev/null +++ b/changelog.d/5-internal/brig-index-config-dedup @@ -0,0 +1 @@ +De-duplicate brig-index configuration by reading connection settings (elasticsearch, cassandra, galley) from brig.yaml via the -c flag, instead of requiring them as CLI arguments. diff --git a/charts/elasticsearch-index/templates/_helpers.tpl b/charts/elasticsearch-index/templates/_helpers.tpl index a3581b09d5..890086b251 100644 --- a/charts/elasticsearch-index/templates/_helpers.tpl +++ b/charts/elasticsearch-index/templates/_helpers.tpl @@ -8,47 +8,12 @@ {{- (semverCompare ">= 1.24-0" (include "kubeVersion" .)) -}} {{- end -}} -{{- define "useCassandraTLS" -}} -{{ or (hasKey .cassandra "tlsCa") (hasKey .cassandra "tlsCaSecretRef") }} -{{- end -}} - -{{/* Return a Dict of TLS CA secret name and key -This is used to switch between provided secret (e.g. by cert-manager) and -created one (in case the CA is provided as PEM string.) +{{/* +NOTE: The following helpers are DEPRECATED. +This chart now uses brig's ConfigMap and Secret for configuration. +TLS settings should be configured via: + - elasticsearchTlsEnabled: true/false + - cassandraTlsEnabled: true/false + - secrets.elasticsearchCaSecretName: name of the secret (default: brig-elasticsearch-ca) + - secrets.cassandraCaSecretName: name of the secret (default: brig-cassandra) */}} - -{{- define "cassandraTlsSecretName" -}} -{{- if .cassandra.tlsCaSecretRef -}} -{{ .cassandra.tlsCaSecretRef.name }} -{{- else }} -{{- print "elasticsearch-index-migrate-cassandra-client-ca" -}} -{{- end -}} -{{- end -}} - -{{- define "cassandraTlsSecretKey" -}} -{{- if .cassandra.tlsCaSecretRef -}} -{{ .cassandra.tlsCaSecretRef.key }} -{{- else }} -{{- print "ca.pem" -}} -{{- end -}} -{{- end -}} - -{{- define "configureElasticsearchCa" -}} -{{ or (hasKey .elasticsearch "tlsCa") (hasKey .elasticsearch "tlsCaSecretRef") }} -{{- end -}} - -{{- define "elasticsearchTlsSecretName" -}} -{{- if .elasticsearch.tlsCaSecretRef -}} -{{ .elasticsearch.tlsCaSecretRef.name }} -{{- else }} -{{- printf "%s-ca" (include "fullname" .) -}} -{{- end -}} -{{- end -}} - -{{- define "elasticsearchTlsSecretKey" -}} -{{- if .elasticsearch.tlsCaSecretRef -}} -{{ .elasticsearch.tlsCaSecretRef.key }} -{{- else }} -{{- print "ca.pem" -}} -{{- end -}} -{{- end -}} diff --git a/charts/elasticsearch-index/templates/cassandra-secret.yaml b/charts/elasticsearch-index/templates/cassandra-secret.yaml deleted file mode 100644 index 93486dd962..0000000000 --- a/charts/elasticsearch-index/templates/cassandra-secret.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- if not (empty .Values.cassandra.tlsCa) }} -apiVersion: v1 -kind: Secret -metadata: - name: elasticsearch-index-migrate-cassandra-client-ca - labels: - app: elasticsearch-index-migrate-data - chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} - release: "{{ .Release.Name }}" - heritage: "{{ .Release.Service }}" -type: Opaque -data: - ca.pem: {{ .Values.cassandra.tlsCa | b64enc | quote }} -{{- end }} diff --git a/charts/elasticsearch-index/templates/create-index.yaml b/charts/elasticsearch-index/templates/create-index.yaml index 225ecf82c9..d67f459b5f 100644 --- a/charts/elasticsearch-index/templates/create-index.yaml +++ b/charts/elasticsearch-index/templates/create-index.yaml @@ -21,98 +21,65 @@ spec: chart: "{{.Chart.Name}}-{{.Chart.Version}}" spec: restartPolicy: OnFailure - {{- if or (eq (include "configureElasticsearchCa" .Values) "true") (hasKey .Values.secrets "elasticsearch") }} volumes: - {{- if hasKey .Values.secrets "elasticsearch" }} - - name: elasticsearch-index-secrets + - name: brig-config + configMap: + name: brig + - name: brig-secrets secret: - secretName: elasticsearch-index - {{- end }} - {{- if eq (include "configureElasticsearchCa" .Values) "true" }} + secretName: brig + {{- if .Values.elasticsearchTlsEnabled }} - name: elasticsearch-ca secret: - secretName: {{ include "elasticsearchTlsSecretName" .Values }} + secretName: {{ .Values.secrets.elasticsearchCaSecretName }} {{- end }} - {{- end }} initContainers: # Creates index in elasticsearch only when it doesn't exist. # Does nothing if the index exists. - name: brig-index-create image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" - {{- if or (eq (include "configureElasticsearchCa" .Values) "true") (hasKey .Values.secrets "elasticsearch") }} volumeMounts: - {{- if hasKey .Values.secrets "elasticsearch" }} - - name: "elasticsearch-index-secrets" - mountPath: "/etc/wire/elasticsearch-index/secrets" - {{- end }} - - {{- if eq (include "configureElasticsearchCa" .Values) "true" }} + - name: brig-config + mountPath: /etc/wire/brig/conf + - name: brig-secrets + mountPath: /etc/wire/brig/secrets + {{- if .Values.elasticsearchTlsEnabled }} - name: elasticsearch-ca - mountPath: "/certs/elasticsearch" + mountPath: "/etc/wire/brig/elasticsearch-ca" {{- end }} - {{- end }} {{- if eq (include "includeSecurityContext" .) "true" }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 12 }} {{- end }} args: + - --config-file + - /etc/wire/brig/conf/brig.yaml - create - - --elasticsearch-server - - "{{ .Values.elasticsearch.scheme }}://{{ required "missing elasticsearch-index.elasticsearch.host!" .Values.elasticsearch.host }}:{{ .Values.elasticsearch.port }}" - {{- if hasKey .Values.secrets "elasticsearch" }} - - --elasticsearch-credentials - - "/etc/wire/elasticsearch-index/secrets/elasticsearch-credentials.yaml" - {{- end }} - - --elasticsearch-index - - "{{ or (.Values.elasticsearch.additionalWriteIndex) (.Values.elasticsearch.index) }}" - - --elasticsearch-shards=5 - - --elasticsearch-replicas=2 - - --elasticsearch-refresh-interval=5 + - --elasticsearch-shards={{ default 5 .Values.elasticsearch.shards }} + - --elasticsearch-replicas={{ default 2 .Values.elasticsearch.replicas }} + - --elasticsearch-refresh-interval={{ default 5 .Values.elasticsearch.refreshInterval }} {{- if .Values.elasticsearch.delete_template }} - --delete-template - "{{ .Values.elasticsearch.delete_template }}" {{- end }} - {{- if eq (include "configureElasticsearchCa" .Values) "true" }} - - --elasticsearch-ca-cert - - /certs/elasticsearch/{{- include "elasticsearchTlsSecretKey" .Values}} - {{- end }} - {{- if .Values.elasticsearch.insecureSkipTlsVerify }} - - --elasticsearch-insecure-skip-tls-verify - {{- end }} containers: - name: brig-index-update-mapping image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ default "" .Values.imagePullPolicy | quote }} - {{- if or (eq (include "configureElasticsearchCa" .Values) "true") (hasKey .Values.secrets "elasticsearch") }} volumeMounts: - {{- if hasKey .Values.secrets "elasticsearch" }} - - name: "elasticsearch-index-secrets" - mountPath: "/etc/wire/elasticsearch-index/secrets" - {{- end }} - - {{- if eq (include "configureElasticsearchCa" .Values) "true" }} + - name: brig-config + mountPath: /etc/wire/brig/conf + - name: brig-secrets + mountPath: /etc/wire/brig/secrets + {{- if .Values.elasticsearchTlsEnabled }} - name: elasticsearch-ca - mountPath: "/certs/elasticsearch" + mountPath: "/etc/wire/brig/elasticsearch-ca" {{- end }} - {{- end }} {{- if eq (include "includeSecurityContext" .) "true" }} securityContext: {{- toYaml .Values.podSecurityContext | nindent 12 }} {{- end }} args: + - --config-file + - /etc/wire/brig/conf/brig.yaml - update-mapping - - --elasticsearch-server - - "{{ .Values.elasticsearch.scheme }}://{{ required "missing elasticsearch-index.elasticsearch.host!" .Values.elasticsearch.host }}:{{ .Values.elasticsearch.port }}" - {{- if hasKey .Values.secrets "elasticsearch" }} - - --elasticsearch-credentials - - "/etc/wire/elasticsearch-index/secrets/elasticsearch-credentials.yaml" - {{- end }} - - --elasticsearch-index - - "{{ or (.Values.elasticsearch.additionalWriteIndex) (.Values.elasticsearch.index) }}" - {{- if eq (include "configureElasticsearchCa" .Values) "true" }} - - --elasticsearch-ca-cert - - /certs/elasticsearch/{{- include "elasticsearchTlsSecretKey" .Values}} - {{- end }} - {{- if .Values.elasticsearch.insecureSkipTlsVerify }} - - --elasticsearch-insecure-skip-tls-verify - {{- end }} diff --git a/charts/elasticsearch-index/templates/elasticsearch-ca-secret.yaml b/charts/elasticsearch-index/templates/elasticsearch-ca-secret.yaml deleted file mode 100644 index 060d84e56a..0000000000 --- a/charts/elasticsearch-index/templates/elasticsearch-ca-secret.yaml +++ /dev/null @@ -1,14 +0,0 @@ -{{- if not (empty .Values.elasticsearch.tlsCa) }} -apiVersion: v1 -kind: Secret -metadata: - name: "{{ include "fullname" .}}-ca" - labels: - app: elasticsearch-index - chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} - release: "{{ .Release.Name }}" - heritage: "{{ .Release.Service }}" -type: Opaque -data: - ca.pem: {{ .Values.elasticsearch.tlsCa | b64enc | quote }} -{{- end }} diff --git a/charts/elasticsearch-index/templates/helpers.tpl b/charts/elasticsearch-index/templates/helpers.tpl deleted file mode 100644 index fb1ddbd472..0000000000 --- a/charts/elasticsearch-index/templates/helpers.tpl +++ /dev/null @@ -1,7 +0,0 @@ -{{/* -override default fullname template to remove the .Release.Name from the definition -*/}} -{{- define "fullname" -}} -{{- $name := default .Chart.Name .Values.nameOverride -}} -{{- printf "%s" $name | trunc 63 | trimSuffix "-" -}} -{{- end -}} \ No newline at end of file diff --git a/charts/elasticsearch-index/templates/migrate-data.yaml b/charts/elasticsearch-index/templates/migrate-data.yaml index 3bf41e02a6..8ff43833f9 100644 --- a/charts/elasticsearch-index/templates/migrate-data.yaml +++ b/charts/elasticsearch-index/templates/migrate-data.yaml @@ -27,62 +27,36 @@ spec: image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" imagePullPolicy: {{ default "" .Values.imagePullPolicy | quote }} args: + - --config-file + - /etc/wire/brig/conf/brig.yaml - migrate-data - - --elasticsearch-server - - "{{ .Values.elasticsearch.scheme }}://{{ required "missing elasticsearch-index.elasticsearch.host!" .Values.elasticsearch.host }}:{{ .Values.elasticsearch.port }}" - {{- if hasKey .Values.secrets "elasticsearch" }} - - --elasticsearch-credentials - - "/etc/wire/elasticsearch-index/secrets/elasticsearch-credentials.yaml" - {{- end }} - - --elasticsearch-index - - "{{ or (.Values.elasticsearch.additionalWriteIndex) (.Values.elasticsearch.index) }}" - - --cassandra-host - - "{{ required "missing elasticsearch-index.cassandra.host!" .Values.cassandra.host }}" - - --cassandra-port - - "{{ required "missing elasticsearch-index.cassandra.port!" .Values.cassandra.port }}" - - --cassandra-keyspace - - "{{ required "missing elasticsearch-index.cassandra.keyspace!" .Values.cassandra.keyspace }}" - - --galley-host - - "{{ required "missing elasticsearch-index.galley.host!" .Values.galley.host }}" - - --galley-port - - "{{ required "missing elasticsearch-index.galley.port!" .Values.galley.port }}" - {{- if eq (include "useCassandraTLS" .Values) "true" }} - - --cassandra-ca-cert - - /certs/cassandra/{{- include "cassandraTlsSecretKey" .Values }} - {{- end }} - {{- if eq (include "configureElasticsearchCa" .Values) "true" }} - - --elasticsearch-ca-cert - - /certs/elasticsearch/{{- include "elasticsearchTlsSecretKey" .Values}} - {{- end }} - {{- if .Values.elasticsearch.insecureSkipTlsVerify }} - - --elasticsearch-insecure-skip-tls-verify - {{- end }} volumeMounts: - {{- if hasKey .Values.secrets "elasticsearch" }} - - name: "elasticsearch-index-secrets" - mountPath: "/etc/wire/elasticsearch-index/secrets" + - name: brig-config + mountPath: /etc/wire/brig/conf + - name: brig-secrets + mountPath: /etc/wire/brig/secrets + {{- if .Values.cassandraTlsEnabled }} + - name: cassandra-ca + mountPath: "/etc/wire/brig/cassandra" {{- end }} - {{- if eq (include "useCassandraTLS" .Values) "true" }} - - name: elasticsearch-index-migrate-cassandra-client-ca - mountPath: "/certs/cassandra" - {{- end }} - {{- if eq (include "configureElasticsearchCa" .Values) "true" }} + {{- if .Values.elasticsearchTlsEnabled }} - name: elasticsearch-ca - mountPath: "/certs/elasticsearch" + mountPath: "/etc/wire/brig/elasticsearch-ca" {{- end }} volumes: - {{- if hasKey .Values.secrets "elasticsearch" }} - - name: elasticsearch-index-secrets + - name: brig-config + configMap: + name: brig + - name: brig-secrets secret: - secretName: elasticsearch-index - {{- end }} - {{- if eq (include "useCassandraTLS" .Values) "true" }} - - name: elasticsearch-index-migrate-cassandra-client-ca + secretName: brig + {{- if .Values.cassandraTlsEnabled }} + - name: cassandra-ca secret: - secretName: {{ include "cassandraTlsSecretName" .Values }} + secretName: {{ .Values.secrets.cassandraCaSecretName }} {{- end }} - {{- if eq (include "configureElasticsearchCa" .Values) "true" }} + {{- if .Values.elasticsearchTlsEnabled }} - name: elasticsearch-ca secret: - secretName: {{ include "elasticsearchTlsSecretName" .Values }} + secretName: {{ .Values.secrets.elasticsearchCaSecretName }} {{- end }} diff --git a/charts/elasticsearch-index/templates/secret.yaml b/charts/elasticsearch-index/templates/secret.yaml deleted file mode 100644 index cda93a046b..0000000000 --- a/charts/elasticsearch-index/templates/secret.yaml +++ /dev/null @@ -1,20 +0,0 @@ -{{- if hasKey .Values.secrets "elasticsearch" }} -apiVersion: v1 -kind: Secret -metadata: - name: elasticsearch-index - labels: - chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} - release: "{{ .Release.Name }}" - heritage: "{{ .Release.Service }}" - annotations: - "helm.sh/hook": pre-install,pre-upgrade - "helm.sh/hook-delete-policy": "before-hook-creation" -type: Opaque -data: - {{- with .Values.secrets }} - {{- if .elasticsearch }} - elasticsearch-credentials.yaml: {{ .elasticsearch | toYaml | b64enc }} - {{- end }} - {{- end }} -{{- end }} diff --git a/charts/elasticsearch-index/values.yaml b/charts/elasticsearch-index/values.yaml index a7c136f233..c069553cb2 100644 --- a/charts/elasticsearch-index/values.yaml +++ b/charts/elasticsearch-index/values.yaml @@ -1,32 +1,34 @@ # Default values for elasticsearch-index -elasticsearch: - scheme: http - #host: # elasticsearch-client|elasticsearch-ephemeral - port: 9200 - index: directory - delete_template: directory -# To enable TLS verification with a custom CA: -# tlsCa: # -# Or refer to an existing secret (containing the CA): -# tlsCaSecretRef: -# name: -# key: - insecureSkipTlsVerify: false -cassandra: - # host: - port: 9042 - keyspace: brig -# To enable TLS provide a CA: -# tlsCa: +# This chart uses brig's ConfigMap and Secret for configuration, which should be +# deployed before this chart. The brig ConfigMap contains elasticsearch, cassandra, +# and galley settings needed by brig-index. The brig Secret contains elasticsearch +# credentials if configured. # -# Or refer to an existing secret (containing the CA): -# tlsCaSecretRef: -# name: -# key: -galley: - host: galley - port: 8080 +# The following settings are specific to index creation and can be customized: +elasticsearch: + # Index creation settings (not read from brig.yaml) + shards: 5 + replicas: 2 + refreshInterval: 5 + delete_template: directory + +# TLS CA secret references (should match what's configured in brig chart) +# These secrets are created by the brig chart or provided externally. +secrets: + # Elasticsearch TLS CA secret name and key (matches brig's elasticsearch-ca secret) + elasticsearchCaSecretName: brig-elasticsearch-ca + elasticsearchCaSecretKey: ca.pem + # Cassandra TLS CA secret name and key (matches brig's cassandra-ca secret) + cassandraCaSecretName: brig-cassandra + cassandraCaSecretKey: ca.pem + +# Set to true if brig is configured with Elasticsearch TLS +elasticsearchTlsEnabled: false + +# Set to true if brig is configured with Cassandra TLS +cassandraTlsEnabled: false + image: repository: quay.io/wire/brig-index tag: do-not-use @@ -40,4 +42,24 @@ podSecurityContext: seccompProfile: type: RuntimeDefault -secrets: {} +# NOTE: The following settings are DEPRECATED and no longer used. +# Configuration is now read from brig's ConfigMap (brig.yaml) and brig's Secret. +# +# Old configuration structure (now deprecated): +# elasticsearch: +# scheme: http +# host: elasticsearch-client +# port: 9200 +# index: directory +# insecureSkipTlsVerify: false +# tlsCa or tlsCaSecretRef for custom TLS CA +# +# cassandra: +# host: cassandra +# port: 9042 +# keyspace: brig +# tlsCa or tlsCaSecretRef for TLS +# +# galley: +# host: galley +# port: 8080 diff --git a/charts/integration/templates/integration-integration.yaml b/charts/integration/templates/integration-integration.yaml index f59475280e..7ff25f7a9b 100644 --- a/charts/integration/templates/integration-integration.yaml +++ b/charts/integration/templates/integration-integration.yaml @@ -162,9 +162,8 @@ spec: --tls-ca-certificate-file /certs/cassandra/{{- include "cassandraTlsSecretKey" .Values.config }} {{ end }} - integration-dynamic-backends-brig-index.sh \ - --elasticsearch-server https://elastic:changeme@{{ .Values.config.elasticsearch.host }}:9200 \ - --elasticsearch-ca-cert /certs/elasticsearch/{{ .Values.config.elasticsearch.tlsCaSecretRef.key }} + # brig-index reads ES/Cassandra/Galley settings from brig.yaml + BRIG_CONFIG_FILE=/etc/wire/brig/conf/brig.yaml integration-dynamic-backends-brig-index.sh integration-dynamic-backends-ses.sh {{ .Values.config.sesEndpointUrl }} integration-dynamic-backends-s3.sh {{ .Values.config.s3EndpointUrl }} {{- range $name, $dynamicBackend := .Values.config.dynamicBackends }} diff --git a/deploy/dockerephemeral/db-migrate/brig-index.sh b/deploy/dockerephemeral/db-migrate/brig-index.sh index 32cf6ed878..e2ba26bc1e 100755 --- a/deploy/dockerephemeral/db-migrate/brig-index.sh +++ b/deploy/dockerephemeral/db-migrate/brig-index.sh @@ -4,4 +4,5 @@ until_ready() { until $1; do echo 'service not ready yet'; sleep 5; done } -until_ready "brig-index reset --elasticsearch-server http://elasticsearch:9200" +# Uses the brig.yaml configuration file for elasticsearch connection settings +until_ready "brig-index -c /etc/wire/brig/conf/brig.yaml reset --elasticsearch-index-prefix directory" diff --git a/docs/src/developer/reference/config-options.md b/docs/src/developer/reference/config-options.md index d72b8158fa..d2bef9af34 100644 --- a/docs/src/developer/reference/config-options.md +++ b/docs/src/developer/reference/config-options.md @@ -1473,7 +1473,7 @@ The ways differ regarding the kind of program: - *Services* expect a `cassandra.tlsCa: ` attribute in their config file. - *\*-schema CLI commands* accept a `--tls-ca-certificate-file ` parameter. -- *brig-index migrate-data* accepts a `--cassandra-ca-cert ` parameter. +- *brig-index* reads connection settings (including Cassandra TLS) from `brig.yaml` via the `-c` flag: `brig-index -c /path/to/brig.yaml ` When a CA PEM file is configured, all Cassandra connections are opened with TLS encryption i.e. there is no fallback to unencrypted connections. This ensures diff --git a/services/brig/brig.cabal b/services/brig/brig.cabal index 67449f7bb0..abeddda2a5 100644 --- a/services/brig/brig.cabal +++ b/services/brig/brig.cabal @@ -344,6 +344,7 @@ executable brig-index , imports , optparse-applicative , tinylog + , yaml executable brig-integration import: common-all diff --git a/services/brig/index/src/Main.hs b/services/brig/index/src/Main.hs index bf2412d475..8c89ade8bf 100644 --- a/services/brig/index/src/Main.hs +++ b/services/brig/index/src/Main.hs @@ -22,6 +22,8 @@ where import Brig.Index.Eval import Brig.Index.Options +import Brig.Options qualified as BrigOpts +import Data.Yaml qualified as Yaml import Imports import Options.Applicative import System.Exit @@ -29,10 +31,10 @@ import System.Logger.Class qualified as Log main :: IO () main = do - cmd <- execParser (info (helper <*> commandParser) desc) + (configFile, cmd) <- execParser (info (helper <*> mainParser) desc) lgr <- initLogger - runCommand lgr cmd - -- TODO: dump metrics in a suitable format (NOT json) + brigOpts <- loadBrigConfig configFile + runCommand lgr brigOpts cmd exitSuccess where desc = @@ -45,3 +47,32 @@ main = do . Log.setFormat Nothing . Log.setBufSize 0 $ Log.defSettings + +-- | Load brig configuration from YAML file +loadBrigConfig :: FilePath -> IO BrigOpts.Opts +loadBrigConfig configFile = + Yaml.decodeFileEither configFile >>= \case + Left e -> + fail $ + "Failed to parse configuration file " + <> configFile + <> ": " + <> show e + Right o -> pure o + +-- | Main parser: config file + command +mainParser :: Parser (FilePath, Command) +mainParser = + (,) + <$> configFileParser + <*> commandParser + +configFileParser :: Parser FilePath +configFileParser = + strOption + ( long "config-file" + <> short 'c' + <> help "Path to brig.yaml configuration file" + <> showDefault + <> value "/etc/wire/brig/conf/brig.yaml" + ) diff --git a/services/brig/src/Brig/Index/Eval.hs b/services/brig/src/Brig/Index/Eval.hs index ad58b6d53f..cfd858a48c 100644 --- a/services/brig/src/Brig/Index/Eval.hs +++ b/services/brig/src/Brig/Index/Eval.hs @@ -26,7 +26,6 @@ import Brig.Index.Options import Brig.Options import Brig.User.Search.Index import Cassandra (Client, runClient) -import Cassandra.Options import Cassandra.Util (defInitCassandra) import Control.Exception (throwIO) import Control.Lens @@ -103,28 +102,31 @@ type BrigIndexEffectStack = Final IO ] -runSem :: ESConnectionSettings -> CassandraSettings -> Endpoint -> Logger -> Sem BrigIndexEffectStack a -> IO a -runSem esConn cas galleyEndpoint logger action = do - mgr <- initHttpManagerWithTLSConfig esConn.esInsecureSkipVerifyTls esConn.esCaCert - mEsCreds :: Maybe Credentials <- for esConn.esCredentials initCredentials - casClient <- defInitCassandra (toCassandraOpts cas) logger +-- | Run polysemy effect stack with ES and Cassandra from brig options. +runSem :: Opts -> Logger -> Sem BrigIndexEffectStack a -> IO a +runSem brigOpts logger action = do + let esOpts = brigOpts.elasticsearch + mgr <- initHttpManagerWithTLSConfig esOpts.insecureSkipVerifyTls esOpts.caCert + mEsCreds :: Maybe Credentials <- for esOpts.credentials initCredentials + casClient <- defInitCassandra brigOpts.cassandra logger let bhEnv = BHEnv - { bhServer = toESServer esConn.esServer, + { bhServer = esOpts.url, bhManager = mgr, bhRequestHook = maybe pure (\creds -> ES.basicAuthHook (ES.EsUsername creds.username) (ES.EsPassword creds.password)) mEsCreds } + indexedUserStoreConfig = IndexedUserStoreConfig { conn = ESConn - { indexName = esConn.esIndex, + { indexName = esOpts.index, env = bhEnv }, additionalConn = Nothing } - reqId = (RequestId "brig-index") - migrationIndexName = fromMaybe defaultMigrationIndexName (esMigrationIndexName esConn) + reqId = RequestId "brig-index" + runFinal . embedToFinal . throwErrorToIOFinal @UsageError @@ -133,12 +135,12 @@ runSem esConn cas galleyEndpoint logger action = do . ignoreMetrics . runRpcWithHttp mgr reqId . throwErrorToIOFinal @ParseException - . interpretGalleyAPIAccessToRpc mempty galleyEndpoint + . interpretGalleyAPIAccessToRpc mempty brigOpts.galley . runEmbedded (runClient casClient) . interpretFederationDomainConfig casClient Nothing mempty . raiseUnder @(Embed Client) . throwErrorToIOFinal @MigrationException - . interpretIndexedUserMigrationStoreES bhEnv migrationIndexName + . interpretIndexedUserMigrationStoreES bhEnv defaultMigrationIndexName . throwErrorToIOFinal @IndexedUserStoreError . interpretIndexedUserStoreES indexedUserStoreConfig . interpretUserStoreCassandra casClient @@ -156,35 +158,38 @@ throwErrorToIOFinal action = do Left e -> embedFinal $ throwIO e Right a -> pure a -runCommand :: Logger -> Command -> IO () -runCommand l = \case - Create es galley -> do - e <- initIndex l (es ^. esConnection) galley - runIndexIO e $ createIndexIfNotPresent (mkCreateIndexSettings es) - Reset es galley -> do - e <- initIndex l (es ^. esConnection) galley - runIndexIO e $ resetIndex (mkCreateIndexSettings es) - Reindex es cas galley -> do - runSem (es ^. esConnection) cas galley l $ +-- | Run a brig-index command. Connection settings come from `Opts` (brig.yaml), +-- index-specific settings come from `Command` (CLI args). +runCommand :: Logger -> Opts -> Command -> IO () +runCommand l brigOpts = \case + Create idxSettings -> do + e <- initIndex l brigOpts + runIndexIO e $ createIndexIfNotPresent (mkCreateIndexSettings idxSettings) + Reset -> do + -- Reset uses the index from brig.yaml but only works on test indices + e <- initIndex l brigOpts + -- Use default index settings for reset + let defaultSettings = ElasticIndexSettings 1 (ES.ReplicaCount 1) 1 Nothing + runIndexIO e $ resetIndex (mkCreateIndexSettings defaultSettings) + Reindex -> do + runSem brigOpts l $ IndexedUserStoreBulk.syncAllUsers - ReindexSameOrNewer es cas galley -> do - runSem (es ^. esConnection) cas galley l $ + ReindexSameOrNewer -> do + runSem brigOpts l $ IndexedUserStoreBulk.forceSyncAllUsers - UpdateMapping esConn galley -> do - e <- initIndex l esConn galley + UpdateMapping -> do + e <- initIndex l brigOpts runIndexIO e updateMapping - Migrate es cas galley -> do - runSem (es ^. esConnection) cas galley l $ + Migrate -> do + runSem brigOpts l $ IndexedUserStoreBulk.migrateData ReindexFromAnotherIndex reindexSettings -> do - mgr <- - initHttpManagerWithTLSConfig - (reindexSettings ^. reindexEsConnection . to esInsecureSkipVerifyTls) - (reindexSettings ^. reindexEsConnection . to esCaCert) - mCreds <- for (reindexSettings ^. reindexEsConnection . to esCredentials) initCredentials - let bhEnv = initES (reindexSettings ^. reindexEsConnection . to esServer) mgr mCreds + let esOpts = brigOpts.elasticsearch + mgr <- initHttpManagerWithTLSConfig esOpts.insecureSkipVerifyTls esOpts.caCert + mCreds <- for esOpts.credentials initCredentials + let bhEnv = initES esOpts.url mgr mCreds ES.runBH bhEnv $ do - let src = reindexSettings ^. reindexEsConnection . to esIndex + let src = esOpts.index dest = view reindexDestIndex reindexSettings timeoutSeconds = view reindexTimeoutSeconds reindexSettings @@ -205,28 +210,16 @@ runCommand l = \case waitForTaskToComplete @ES.ReindexResponse timeoutSeconds taskNodeId Log.info l $ Log.msg ("Finished reindexing" :: ByteString) where - initES esURI mgr mCreds = - let env = ES.mkBHEnv (toESServer esURI) mgr + initES esUrl mgr mCreds = + let env = ES.mkBHEnv esUrl mgr in maybe env (\(creds :: Credentials) -> env {ES.bhRequestHook = ES.basicAuthHook (ES.EsUsername creds.username) (ES.EsPassword creds.password)}) mCreds -initIndex :: Logger -> ESConnectionSettings -> Endpoint -> IO IndexEnv -initIndex l esConn gly = do - mgr <- initHttpManagerWithTLSConfig esConn.esInsecureSkipVerifyTls esConn.esCaCert - let esOpts = - ElasticSearchOpts - { url = toESServer esConn.esServer, - index = esConn.esIndex, - credentials = esConn.esCredentials, - insecureSkipVerifyTls = esConn.esInsecureSkipVerifyTls, - caCert = esConn.esCaCert, - additionalWriteIndex = Nothing, - additionalWriteIndexUrl = Nothing, - additionalCredentials = Nothing, - additionalInsecureSkipVerifyTls = False, - additionalCaCert = Nothing - } - - mkIndexEnv esOpts l gly mgr +-- | Initialize index environment from brig options. +initIndex :: Logger -> Opts -> IO IndexEnv +initIndex l brigOpts = do + let esOpts = brigOpts.elasticsearch + mgr <- initHttpManagerWithTLSConfig esOpts.insecureSkipVerifyTls esOpts.caCert + mkIndexEnv esOpts l brigOpts.galley mgr waitForTaskToComplete :: forall a m. (ES.MonadBH m, MonadThrow m, FromJSON a) => Int -> ES.TaskNodeId -> m () waitForTaskToComplete timeoutSeconds taskNodeId = do diff --git a/services/brig/src/Brig/Index/Options.hs b/services/brig/src/Brig/Index/Options.hs index f72db00304..85e54dc48b 100644 --- a/services/brig/src/Brig/Index/Options.hs +++ b/services/brig/src/Brig/Index/Options.hs @@ -21,106 +21,61 @@ module Brig.Index.Options ( Command (..), - ElasticSettings, - ESConnectionSettings (..), - esConnection, + ElasticIndexSettings (..), esIndexShardCount, esIndexReplicas, esIndexRefreshInterval, esDeleteTemplate, - CassandraSettings, - toCassandraOpts, - cHost, - cPort, - cTlsCa, - cKeyspace, - localElasticSettings, - localCassandraSettings, commandParser, mkCreateIndexSettings, - toESServer, ReindexFromAnotherIndexSettings (..), reindexDestIndex, reindexTimeoutSeconds, - reindexEsConnection, ) where import Brig.Index.Types (CreateIndexSettings (..)) -import Cassandra qualified as C import Control.Lens -import Data.ByteString.Lens -import Data.Text qualified as Text import Data.Text.Strict.Lens import Data.Time.Clock (NominalDiffTime) import Database.Bloodhound qualified as ES import Imports import Options.Applicative -import URI.ByteString -import URI.ByteString.QQ -import Util.Options (CassandraOpts (..), Endpoint (..), FilePathSecrets) +-- | Commands for brig-index. Connection settings (ES, Cassandra, Galley) come from brig.yaml. +-- Index-specific settings (shards, replicas) come from CLI only where needed. data Command - = Create ElasticSettings Endpoint - | Reset ElasticSettings Endpoint - | Reindex ElasticSettings CassandraSettings Endpoint - | ReindexSameOrNewer ElasticSettings CassandraSettings Endpoint - | -- | 'ElasticSettings' has shards and other settings that are not needed here. - UpdateMapping ESConnectionSettings Endpoint - | Migrate ElasticSettings CassandraSettings Endpoint + = Create ElasticIndexSettings + | Reset + | Reindex + | ReindexSameOrNewer + | UpdateMapping + | Migrate | ReindexFromAnotherIndex ReindexFromAnotherIndexSettings deriving (Show) -data ESConnectionSettings = ESConnectionSettings - { esServer :: URIRef Absolute, - esIndex :: ES.IndexName, - esCaCert :: Maybe FilePath, - esInsecureSkipVerifyTls :: Bool, - esCredentials :: Maybe FilePathSecrets, - esMigrationIndexName :: Maybe ES.IndexName - } - deriving (Show) - -data ElasticSettings = ElasticSettings - { _esConnection :: ESConnectionSettings, - _esIndexShardCount :: Int, +-- | Index-specific settings that come from CLI. Connection settings come from brig.yaml. +data ElasticIndexSettings = ElasticIndexSettings + { _esIndexShardCount :: Int, _esIndexReplicas :: ES.ReplicaCount, _esIndexRefreshInterval :: NominalDiffTime, _esDeleteTemplate :: Maybe ES.TemplateName } deriving (Show) -data CassandraSettings = CassandraSettings - { _cHost :: String, - _cPort :: Word16, - _cKeyspace :: C.Keyspace, - _cTlsCa :: Maybe FilePath - } - deriving (Show) - +-- | Settings for ReindexFromAnotherIndex command. +-- ES connection settings come from brig.yaml; only destination index and timeout come from CLI. data ReindexFromAnotherIndexSettings = ReindexFromAnotherIndexSettings - { _reindexEsConnection :: ESConnectionSettings, - _reindexDestIndex :: ES.IndexName, + { _reindexDestIndex :: ES.IndexName, _reindexTimeoutSeconds :: Int } deriving (Show) -makeLenses ''ElasticSettings - -makeLenses ''CassandraSettings +makeLenses ''ElasticIndexSettings makeLenses ''ReindexFromAnotherIndexSettings -toCassandraOpts :: CassandraSettings -> CassandraOpts -toCassandraOpts cas = - CassandraOpts - { endpoint = Endpoint (Text.pack (cas ^. cHost)) (cas ^. cPort), - keyspace = C.unKeyspace (cas ^. cKeyspace), - filterNodesByDatacentre = Nothing, - tlsCa = cas ^. cTlsCa - } - -mkCreateIndexSettings :: ElasticSettings -> CreateIndexSettings +mkCreateIndexSettings :: ElasticIndexSettings -> CreateIndexSettings mkCreateIndexSettings es = CreateIndexSettings [ ES.NumberOfReplicas $ _esIndexReplicas es, @@ -129,120 +84,13 @@ mkCreateIndexSettings es = (_esIndexShardCount es) (_esDeleteTemplate es) -localElasticSettings :: ElasticSettings -localElasticSettings = - ElasticSettings - { _esConnection = - ESConnectionSettings - { esServer = [uri|https://localhost:9200|], - esIndex = ES.IndexName "directory_test", - esCaCert = Just "../../libs/wire-subsystems/test/resources/elasticsearch-ca.pem", - esInsecureSkipVerifyTls = False, - esCredentials = Just "../../libs/wire-subsystems/test/resources/elasticsearch-credentials.yaml", - esMigrationIndexName = Nothing - }, - _esIndexShardCount = 1, - _esIndexReplicas = ES.ReplicaCount 1, - _esIndexRefreshInterval = 1, - _esDeleteTemplate = Nothing - } - -localCassandraSettings :: CassandraSettings -localCassandraSettings = - CassandraSettings - { _cHost = "localhost", - _cPort = 9042, - _cKeyspace = C.Keyspace "brig_test", - _cTlsCa = Nothing - } - -elasticServerParser :: Parser (URIRef Absolute) -elasticServerParser = - option - url - ( long "elasticsearch-server" - <> metavar "URL" - <> help "Base URL of the Elasticsearch Server." - <> value localElasticSettings._esConnection.esServer - <> showDefaultWith (view unpackedChars . serializeURIRef') - ) - where - url = - eitherReader - (over _Left show . parseURI strictURIParserOptions . view packedChars) +-------------------------------------------------------------------------------- +-- Parsers -restrictedElasticSettingsParser :: Parser ElasticSettings -restrictedElasticSettingsParser = do - server <- elasticServerParser - prefix <- - strOption - ( long "elasticsearch-index-prefix" - <> metavar "PREFIX" - <> help "Elasticsearch Index Prefix. The actual index name will be PREFIX_test." - <> value "directory" - <> showDefault - ) - mCreds <- credentialsPathParser - mCaCert <- caCertParser - verifyCa <- verifyCaParser - pure $ - localElasticSettings - { _esConnection = - localElasticSettings._esConnection - { esServer = server, - esIndex = ES.IndexName (prefix <> "_test"), - esCredentials = mCreds, - esCaCert = mCaCert, - esInsecureSkipVerifyTls = verifyCa - } - } - -indexNameParser :: Parser ES.IndexName -indexNameParser = - ES.IndexName . view packed - <$> strOption - ( long "elasticsearch-index" - <> metavar "STRING" - <> help "Elasticsearch Index Name." - <> value (view (_IndexName . unpacked) localElasticSettings._esConnection.esIndex) - <> showDefault - ) - -connectionSettingsParser :: Parser ESConnectionSettings -connectionSettingsParser = - ESConnectionSettings - <$> elasticServerParser - <*> indexNameParser - <*> caCertParser - <*> verifyCaParser - <*> credentialsPathParser - <*> pure Nothing - -caCertParser :: Parser (Maybe FilePath) -caCertParser = - optional - ( option - str - ( long "elasticsearch-ca-cert" - <> metavar "FILE" - <> help "Path to CA Certitificate for TLS validation, system CA bundle is used when unspecified" - ) - ) - -verifyCaParser :: Parser Bool -verifyCaParser = - flag - False -- the default is False - True - ( long "elasticsearch-insecure-skip-tls-verify" - <> help "Skip TLS verification when connecting to Elasticsearch (not recommended)" - ) - -elasticSettingsParser :: Parser ElasticSettings -elasticSettingsParser = - ElasticSettings - <$> connectionSettingsParser - <*> indexShardCountParser +elasticIndexSettingsParser :: Parser ElasticIndexSettings +elasticIndexSettingsParser = + ElasticIndexSettings + <$> indexShardCountParser <*> indexReplicaCountParser <*> indexRefreshIntervalParser <*> templateParser @@ -287,55 +135,12 @@ elasticSettingsParser = ) ) -credentialsPathParser :: Parser (Maybe FilePathSecrets) -credentialsPathParser = - optional - ( strOption - ( long "elasticsearch-credentials" - <> metavar "FILE" - <> help "Location of a file containing the Elasticsearch credentials" - ) - ) - -cassandraSettingsParser :: Parser CassandraSettings -cassandraSettingsParser = - CassandraSettings - <$> strOption - ( long "cassandra-host" - <> metavar "HOST" - <> help "Cassandra Host." - <> value (_cHost localCassandraSettings) - <> showDefault - ) - <*> option - auto - ( long "cassandra-port" - <> metavar "PORT" - <> help "Cassandra Port." - <> value (_cPort localCassandraSettings) - <> showDefault - ) - <*> ( C.Keyspace . view packed - <$> strOption - ( long "cassandra-keyspace" - <> metavar "STRING" - <> help "Cassandra Keyspace." - <> value (view (cKeyspace . _Keyspace . unpacked) localCassandraSettings) - <> showDefault - ) - ) - <*> ( (optional . strOption) - ( long "cassandra-ca-cert" - <> metavar "FILE" - <> help "Location of a PEM encoded list of CA certificates to be used when verifying the Cassandra server's certificate" - ) - ) - +-- | Parser for ReindexFromAnotherIndex. +-- ES connection settings come from brig.yaml; only destination index and timeout from CLI. reindexToAnotherIndexSettingsParser :: Parser ReindexFromAnotherIndexSettings reindexToAnotherIndexSettingsParser = ReindexFromAnotherIndexSettings - <$> connectionSettingsParser - <*> ( ES.IndexName . view packed + <$> ( ES.IndexName . view packed <$> strOption ( long "destination-index" <> metavar "STRING" @@ -351,62 +156,43 @@ reindexToAnotherIndexSettingsParser = <> showDefault ) -galleyEndpointParser :: Parser Endpoint -galleyEndpointParser = - Endpoint - <$> strOption - ( long "galley-host" - <> help "Hostname or IP address of galley" - <> metavar "HOSTNAME" - <> value "localhost" - <> showDefault - ) - <*> option - auto - ( long "galley-port" - <> help "Port number of galley" - <> metavar "PORT" - <> value 8085 - <> showDefault - ) - commandParser :: Parser Command commandParser = hsubparser ( command "create" ( info - (Create <$> elasticSettingsParser <*> galleyEndpointParser) - (progDesc "Create the ES user index, if it doesn't already exist. ") + (Create <$> elasticIndexSettingsParser) + (progDesc "Create the ES user index, if it doesn't already exist.") ) <> command "update-mapping" ( info - (UpdateMapping <$> connectionSettingsParser <*> galleyEndpointParser) + (pure UpdateMapping) (progDesc "Update mapping of the user index.") ) <> command "reset" ( info - (Reset <$> restrictedElasticSettingsParser <*> galleyEndpointParser) - (progDesc "Delete and re-create the ES user index. Only works on a test index (directory_test).") + (pure Reset) + (progDesc "Delete and re-create the ES user index. Only works on a test index (index name ending with '_test').") ) <> command "reindex" ( info - (Reindex <$> elasticSettingsParser <*> cassandraSettingsParser <*> galleyEndpointParser) + (pure Reindex) (progDesc "Reindex all users from Cassandra if there is a new version.") ) <> command "reindex-if-same-or-newer" ( info - (ReindexSameOrNewer <$> elasticSettingsParser <*> cassandraSettingsParser <*> galleyEndpointParser) + (pure ReindexSameOrNewer) (progDesc "Reindex all users from Cassandra, even if the version has not changed.") ) <> command "migrate-data" ( info - (Migrate <$> elasticSettingsParser <*> cassandraSettingsParser <*> galleyEndpointParser) + (pure Migrate) (progDesc "Migrate data in elastic search") ) <> command @@ -418,18 +204,3 @@ commandParser = ) ) ) - -_IndexName :: Iso' ES.IndexName Text -_IndexName = iso (\(ES.IndexName n) -> n) ES.IndexName - -_Keyspace :: Iso' C.Keyspace Text -_Keyspace = iso C.unKeyspace C.Keyspace - -toESServer :: URIRef Absolute -> ES.Server -toESServer = - ES.Server - . view utf8 - . serializeURIRef' - . set pathL mempty - . set queryL mempty - . set fragmentL mempty