diff --git a/helm/configurations/values-dev.yaml b/helm/configurations/values-dev.yaml index 5164f1ac..4f65aa82 100644 --- a/helm/configurations/values-dev.yaml +++ b/helm/configurations/values-dev.yaml @@ -14,6 +14,8 @@ components: image: docker.io/reanahub/reana-workflow-controller environment: REANA_RUNTIME_KUBERNETES_KEEP_ALIVE_JOBS_WITH_STATUSES: failed + REANA_OPENSEARCH_USE_SSL: false + REANA_OPENSEARCH_ENABLED: false # Set to true to enable live logs reana_workflow_engine_cwl: image: docker.io/reanahub/reana-workflow-engine-cwl reana_workflow_engine_yadage: @@ -31,3 +33,34 @@ components: pgbouncer: enabled: true + +# OpenSearch configuration for dev environment +opensearch: + enabled: false # Set to true to enable live logs + tls: + generate: false + singleNode: true + config: + opensearch.yml: | + cluster.name: reana-opensearch + network.host: 0.0.0.0 + plugins.security.disabled: true + securityConfig: + enabled: false + internalUsersSecret: + rolesSecret: + rolesMappingSecret: + resources: + requests: + cpu: "500m" + memory: "2Gi" + extraEnvs: + - name: DISABLE_INSTALL_DEMO_CONFIG + value: "false" + - name: OPENSEARCH_INITIAL_ADMIN_PASSWORD + valueFrom: + secretKeyRef: + name: reana-opensearch-secrets + key: OPENSEARCH_INITIAL_ADMIN_PASSWORD + secretMounts: [] + customSecurityConfig: diff --git a/helm/reana/Chart.yaml b/helm/reana/Chart.yaml index 6a893f96..b03c7291 100644 --- a/helm/reana/Chart.yaml +++ b/helm/reana/Chart.yaml @@ -35,3 +35,7 @@ dependencies: condition: traefik.enabled tags: - ingress + - name: opensearch + version: 2.22.1 + repository: https://opensearch-project.github.io/helm-charts/ + condition: opensearch.enabled diff --git a/helm/reana/README.md b/helm/reana/README.md index fdfee412..cf75a19e 100644 --- a/helm/reana/README.md +++ b/helm/reana/README.md @@ -98,6 +98,18 @@ This Helm automatically prefixes all names using the release name to avoid colli | `reana_hostname` | REANA hostname (e.g. reana.example.org) | None | | `namespace_runtime` | Namespace in which the REANA runtime pods (workflow engines, jobs etc...) will run | `.Release.Namespace` | | `naming_scheme` | REANA component naming scheme | None | +| `opensearch.*` | Pass any value from [OpenSearch Helm chart values](https://github.com/opensearch-project/helm-charts/tree/main/charts/opensearch#configuration) here | - | +| `opensearch.enabled` | Enable OpenSearch | false | +| `opensearch.tls.generate` | Enable the generation of a self-signed TLS certificates for OpenSearch | true | +| `opensearch.tls.ca.cn` | OpenSearch root CA certificate common name (CN) | reana.io | +| `opensearch.tls.ca.ttl` | OpenSearch root CA certificate TTL in days | 365 | +| `opensearch.tls.cert.cn` | OpenSearch node certificate common name (CN) | reana-opensearch-master.default.svc.cluster.local | +| `opensearch.tls.cert.ttl` | OpenSearch node certificate TTL in days | 180 | +| `opensearch.tls.admin.cn` | OpenSearch admin certificate common name (CN) | opensearch-admin.reana.io | +| `opensearch.tls.admin.ttl` | OpenSearch admin certificate TTL in days | 180 | +| `opensearch.customSecurityConfig.internalUsers` | Provide YAML users configuration for `internal_users.yaml` file; see [documentation](https://opensearch.org/docs/latest/security/configuration/yaml/#internal_usersyml) | None | +| `opensearch.customSecurityConfig.roles` | Provide YAML roles configuration for `roles.yaml` file; see [documentation](https://opensearch.org/docs/latest/security/configuration/yaml/#rolesyml) | None | +| `opensearch.customSecurityConfig.rolesMapping` | Provide YAML roles mapping configuration for `roles_mapping.yaml` file; see [documentation](https://opensearch.org/docs/latest/security/configuration/yaml/#roles_mappingyml) | None | | `pgbouncer.enabled` | Instantiate PgBouncer inside the cluster to pool database connections | false | | `pgbouncer.image` | [PgBouncer image](https://hub.docker.com/r/bitnami/pgbouncer/) to use | `bitnami/pgbouncer:1.23.1` | | `pgbouncer.pool_mode` | Pool mode to use (session, transaction, statement) | transaction | diff --git a/helm/reana/templates/reana-workflow-controller.yaml b/helm/reana/templates/reana-workflow-controller.yaml index 73776964..1a9e52ca 100644 --- a/helm/reana/templates/reana-workflow-controller.yaml +++ b/helm/reana/templates/reana-workflow-controller.yaml @@ -83,6 +83,11 @@ spec: mountPath: {{ $workspace_path._1 }} {{- end }} {{- end }} + {{- if $opensearchTlsEnabled }} + - name: {{ include "reana.prefix" . }}-opensearch-tls-secrets + mountPath: /code/certs + readOnly: true + {{- end }} envFrom: - configMapRef: name: {{ include "reana.prefix" . }}-database-config @@ -216,6 +221,13 @@ spec: secretKeyRef: name: {{ include "reana.prefix" . }}-db-secrets key: password + {{- if $opensearchEnabled }} + - name: REANA_OPENSEARCH_PASSWORD + valueFrom: + secretKeyRef: + name: {{ include "reana.prefix" . }}-opensearch-secrets + key: REANA_OPENSEARCH_PASSWORD + {{- end }} - name: job-status-consumer image: {{ .Values.components.reana_workflow_controller.image }} imagePullPolicy: {{ .Values.components.reana_workflow_controller.imagePullPolicy }} @@ -287,6 +299,14 @@ spec: hostPath: path: {{ .Values.shared_storage.hostpath.root_path }} {{- end }} + {{- if $opensearchTlsEnabled }} + - name: {{ include "reana.prefix" . }}-opensearch-tls-secrets + secret: + secretName: {{ include "reana.prefix" . }}-opensearch-tls-secrets + items: + - key: ca.crt + path: ca.crt + {{- end }} {{- if .Values.debug.enabled }} - name: reana-code hostPath: diff --git a/helm/reana/templates/secrets.yaml b/helm/reana/templates/secrets.yaml index b211ab5c..73a3798d 100644 --- a/helm/reana/templates/secrets.yaml +++ b/helm/reana/templates/secrets.yaml @@ -76,3 +76,89 @@ data: tls.crt: {{ $cert.Cert | b64enc | quote }} tls.key: {{ $cert.Key | b64enc | quote }} {{- end }} +--- +{{- if and .Values.opensearch.enabled .Values.opensearch.tls.generate }} +{{- $prefix := include "reana.prefix" . }} +{{- $tlsSecretName := printf "%s-%s" $prefix "opensearch-tls-secrets" }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ $tlsSecretName }} + namespace: {{ .Release.Namespace }} +type: kubernetes.io/tls +data: + {{- $idx := lookup "v1" "Secret" .Release.Namespace $tlsSecretName -}} + {{- if $idx }} + tls.crt: {{ index $idx.data "tls.crt" }} + tls.key: {{ index $idx.data "tls.key" }} + admin.crt: {{ index $idx.data "admin.crt" }} + admin.key: {{ index $idx.data "admin.key" }} + ca.crt: {{ index $idx.data "ca.crt" }} + {{ else }} + {{- $ca := genCA .Values.opensearch.tls.ca.cn (.Values.opensearch.tls.ca.ttl | int) }} + {{- $cert := genSignedCert .Values.opensearch.tls.cert.cn nil nil (.Values.opensearch.tls.cert.ttl | int) $ca }} + {{- $certAdmin := genSignedCert .Values.opensearch.tls.admin.cn nil nil (.Values.opensearch.tls.admin.ttl | int) $ca }} + tls.crt: {{ $cert.Cert | b64enc | quote }} + tls.key: {{ $cert.Key | b64enc | quote }} + admin.crt: {{ $certAdmin.Cert | b64enc | quote }} + admin.key: {{ $certAdmin.Key | b64enc | quote }} + ca.crt: {{ $ca.Cert | b64enc | quote }} + {{- end }} +{{- end }} +--- +{{- if and .Values.opensearch.enabled .Values.opensearch.customSecurityConfig }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "reana.prefix" . }}-opensearch-config-secrets + namespace: {{ .Release.Namespace }} +type: kubernetes.io/opaque +stringData: + {{- if .Values.opensearch.customSecurityConfig.internalUsers }} + internal_users.yml: | + --- + # This is the internal user database + # The hash value is a bcrypt hash and can be generated with plugin/tools/hash.sh + _meta: + type: "internalusers" + config_version: 2 + {{ .Values.opensearch.customSecurityConfig.internalUsers | toYaml | nindent 4 }} + {{- end }} + {{- if .Values.opensearch.customSecurityConfig.rolesMapping }} + roles_mapping.yml: | + --- + # In this file users, backendroles and hosts can be mapped to Security roles. + # Permissions for OpenSearch roles are configured in roles.yml + _meta: + type: "rolesmapping" + config_version: 2 + {{ .Values.opensearch.customSecurityConfig.rolesMapping | toYaml | nindent 4 }} + {{- end }} + {{- if .Values.opensearch.customSecurityConfig.roles }} + roles.yml: | + --- + _meta: + type: "roles" + config_version: 2 + # The security REST API access role is used to assign specific users access to change the security settings through the REST API. + security_rest_api_access: + reserved: true + {{ .Values.opensearch.customSecurityConfig.roles | toYaml | nindent 4 }} + {{- end }} +{{- end }} +--- +{{- if .Values.opensearch.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "reana.prefix" . }}-opensearch-secrets + namespace: {{ .Release.Namespace }} + annotations: + "helm.sh/resource-policy": keep +type: Opaque +data: + REANA_OPENSEARCH_PASSWORD: {{ .Values.components.reana_workflow_controller.environment.REANA_OPENSEARCH_PASSWORD | default "reana" | b64enc }} + {{- if not .Values.opensearch.securityConfig.enabled }} + OPENSEARCH_INITIAL_ADMIN_PASSWORD: {{ .Values.opensearch.initialAdminPassword | default "reana" | b64enc }} # dev environment only + {{- end }} +{{- end }} diff --git a/helm/reana/values.yaml b/helm/reana/values.yaml index 4189eea5..23dcaff4 100644 --- a/helm/reana/values.yaml +++ b/helm/reana/values.yaml @@ -112,6 +112,11 @@ components: environment: SHARED_VOLUME_PATH: /var/reana REANA_JOB_STATUS_CONSUMER_PREFETCH_COUNT: 10 + REANA_OPENSEARCH_ENABLED: false + REANA_OPENSEARCH_USE_SSL: true + REANA_OPENSEARCH_CA_CERTS: "/code/certs/ca.crt" + REANA_OPENSEARCH_USER: reana + REANA_OPENSEARCH_PASSWORD: "" # Set this value in the Helm command reana_workflow_engine_cwl: image: docker.io/reanahub/reana-workflow-engine-cwl:0.9.3 environment: {} @@ -189,3 +194,167 @@ quota: # backward compatibility disk_update: "0 3 * * *" # everyday at 3am termination_update_policy: "" + +# OpenSearch chart values.yaml +opensearch: + enabled: false + clusterName: "reana-opensearch" + masterService: "reana-opensearch-master" + tls: + generate: true + ca: + cn: "reana.io" + ttl: 365 + cert: + cn: "reana-opensearch-master.default.svc.cluster.local" + ttl: 180 + admin: + cn: "opensearch-admin.reana.io" + ttl: 180 + singleNode: true # advanced storage configuration needed if set to false + config: + opensearch.yml: | + cluster.name: reana-opensearch + network.host: 0.0.0.0 + plugins: + security: + nodes_dn: + - "CN={{ .Values.tls.cert.cn }}" + authcz: + admin_dn: + - "CN={{ .Values.tls.admin.cn }}" + ssl: + transport: + pemcert_filepath: certs/tls.crt + pemkey_filepath: certs/tls.key + pemtrustedcas_filepath: certs/ca.crt + enforce_hostname_verification: false + http: + enabled: true + pemcert_filepath: certs/tls.crt + pemkey_filepath: certs/tls.key + pemtrustedcas_filepath: certs/ca.crt + allow_default_init_securityindex: true + check_snapshot_restore_write_privileges: true + enable_snapshot_restore_privilege: true + ssl_cert_reload_enabled: true # https://opensearch.org/docs/latest/security/access-control/api/#reload-transport-certificates + restapi: + roles_enabled: + - all_access + - security_rest_api_access + system_indices: + enabled: true + indices: + [ + ".opendistro-alerting-config", + ".opendistro-alerting-alert*", + ".opendistro-anomaly-results*", + ".opendistro-anomaly-detector*", + ".opendistro-anomaly-checkpoints", + ".opendistro-anomaly-detection-state", + ".opendistro-reports-*", + ".opendistro-notifications-*", + ".opendistro-notebooks", + ".opendistro-asynchronous-search-response*", + ] + extraEnvs: + - name: DISABLE_INSTALL_DEMO_CONFIG + value: "true" + secretMounts: + - name: reana-opensearch-tls-secrets + secretName: reana-opensearch-tls-secrets + path: /usr/share/opensearch/config/certs + resources: + requests: + cpu: "1000m" + memory: "4Gi" + persistence: + enabled: false + securityConfig: + enabled: true + internalUsersSecret: "reana-opensearch-config-secrets" + rolesSecret: "reana-opensearch-config-secrets" + rolesMappingSecret: "reana-opensearch-config-secrets" + extraVolumes: + - name: reana-opensearch-volume + hostPath: + path: /var/reana + # You can instead configure infrastructure volume: + # - name: reana-opensearch-volume + # persistentVolumeClaim: + # claimName: reana-infrastructure-persistent-volume + # readOnly: false + # Or shared volume: + # - name: reana-opensearch-volume + # persistentVolumeClaim: + # claimName: reana-shared-persistent-volume + # readOnly: false + extraVolumeMounts: + - mountPath: /usr/share/opensearch/data + subPath: opensearch + name: reana-opensearch-volume + # Configure REANA and FluentBit users and roles for job log collection + customSecurityConfig: + internalUsers: + reana: + hash: "" # Required. To generate hash, run plugins/opensearch-security/tools/hash.sh -p ; supply in Helm command flags + reserved: false + backend_roles: + - readall + description: REANA user + fluentbit: + hash: "" # Required. To generate hash, run plugins/opensearch-security/tools/hash.sh -p ; supply in Helm command flags + reserved: false + backend_roles: + - fluentbit + description: FluentBit user + roles: + fluentbit: + reserved: true + hidden: false + description: Provide the minimum permissions for fluentbit + cluster_permissions: + - cluster_monitor + - cluster_composite_ops + - indices:admin/template/get + - indices:admin/template/put + - cluster:admin/ingest/pipeline/put + - cluster:admin/ingest/pipeline/get + - indices:data/write/bulk* + index_permissions: + - index_patterns: + - fluentbit-* + fls: [] + masked_fields: [] + allowed_actions: + - crud + - create_index + tenant_permissions: [] + static: true + rolesMapping: + fluentbit: + hosts: [] + users: [] + reserved: false + hidden: false + backend_roles: + - fluentbit + and_backend_roles: [] + own_index: + hosts: [] + users: + - "*" + reserved: false + hidden: false + backend_roles: [] + and_backend_roles: [] + description: Allow full access to an index named like the username + readall: + hosts: [] + users: + - "reana" + reserved: false + hidden: false + backend_roles: + - readall + and_backend_roles: []