Skip to content

Commit 4e582cc

Browse files
Ninja243github-actions[bot]hoeftale
authored andcommitted
feat(elastic-operator): add ESO support via common chart
- Add common iits chart dependency, opt-in via common.externalSecret.enabled - Bump curl image used by backup job 8.12.1 → 8.13.0 - Add helm-unittest coverage - add values.schema.json - add ESO external-secret mode for elastic users and backup - rewrite changelog to "Keep a changelog" format. --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Alexander Hoeft <alexander.hoeft@iits-consulting.de>
1 parent a49110e commit 4e582cc

27 files changed

Lines changed: 990 additions & 47 deletions

charts/common/.helmignore

Lines changed: 0 additions & 2 deletions
This file was deleted.

charts/elastic-operator/.trivyignore

Whitespace-only changes.
Lines changed: 65 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,84 @@
11
# Changelog
22

3-
## Chart Versions
3+
All notable changes to this chart will be documented in this file.
44

5-
### 9.3.7
6-
- Changed elastic stack (appVersion) to version 9.3.7
5+
## [9.4.0] - 2026-08-19
6+
7+
### Added
8+
- ESO mode via the IITS `common` chart: setting `common.externalSecret.enabled=true` replaces the bash `generate-passwords` Job and the static basic-auth Secrets with a single ExternalSecrets `Password` generator plus a per-user push/pull round-trip against a configurable secret store (Vault). Disabled by default, so existing installs are unaffected.
9+
- Dependency on the IITS `common` chart `0.4.0`.
10+
- `common.externalSecret.secretStore` to point all ESO resources at a `ClusterSecretStore`/`SecretStore` (defaults to `kind: ClusterSecretStore`, `name: vault`).
11+
- Per-user Vault mapping through `auth.users.<user>.path` and optional `auth.users.<user>.property` (pack multiple users into one Vault secret).
12+
- `generatePasswords.spec` to configure the password generation policy (`length`, `digits`, `symbols`, `noUpper`, `allowRepeat`); `length` also feeds the bash job default.
13+
- `generatePasswords.refreshInterval` to control how often the per-user push/pull secrets reconcile in ESO mode.
14+
- ESO support for backup secure settings via `backup.path`: secure settings are pulled from Vault instead of being inlined.
15+
- `values.schema.json` for values validation, plus template-side `validation.yaml` guarding ESO configuration.
16+
- Helm unit tests covering elasticsearch, elasticsearch-users, external-secrets, generate-passwords, backup secure-settings, and validation.
17+
- `MIGRATION.md` section documenting how to migrate an existing install to ESO mode (pre-seeding Vault, preconditions, verification, and rollback).
18+
19+
### Changed
20+
- The Filebeat/Kibana `checksum/users` annotation that triggers a rollout on user-credential changes now adapts to the mode. In non-ESO mode it keeps the previous behavior (hashes the rendered Kubernetes user Secret). In ESO mode there is no Helm-generated Secret, so it hashes the `auth.users` values instead.
21+
- Moved OTC volume helpers into `_helpers.tpl`.
22+
23+
> **Note:** In ESO mode the `checksum/users` annotation is derived from chart values, not from the live secret content. Because passwords round-trip through Vault, changing a password directly in Vault will **not** roll Filebeat/Kibana. The pods keep using the previously injected value until they are restarted by another means (e.g. a chart value change or a manual rollout).
24+
25+
### [9.3.7] - 2026-08-11
26+
27+
### Changed
28+
- elastic stack (appVersion) to version 9.3.7
729
- Update serverTransport ingress CR to new version
830

9-
### 9.3.5
10-
- Changed operator version to 3.4.0
11-
- Changed elastic stack (appVersion) to version 9.3.5
31+
## [9.3.5] - 2026-06-23
32+
33+
### Changed
34+
- Updated the ECK operator (`eck-operator`) to `3.4.0`.
35+
- Updated the Elastic stack (`appVersion`) to `9.3.5`.
36+
37+
## [9.3.3] - 2026-05-04
38+
39+
### Changed
40+
- Updated the ECK operator (`eck-operator`) to `3.3.2`.
41+
- Updated the Elastic stack (`appVersion`) to `9.3.3`.
1242

13-
### 9.3.3
14-
- Changed operator version to 3.3.2
15-
- Changed elastic stack (appVersion) to version 9.3.3
43+
## [9.0.5-bitnamilegacy] - 2025-10-13
1644

17-
### 9.0.5-bitnamilegacy
45+
### Changed
46+
- Switched the Bitnami image used by the password-generation job to `docker.io/bitnamilegacy/kubectl` (temporary solution to keep the chart functional; migrate to another image in a later release).
1847

19-
- Changed Bitnami image for password generation job to `docker.io/bitnamilegacy/kubectl` (temporary solution to keep chart functional, migrate to other image in a later release)
48+
## [9.0.1] - 2025-05-28
2049

21-
### BREAKING CHANGE 9.0.1
50+
### Changed
51+
- [BREAKING] Updated the Elastic stack (`appVersion`) to `9.0.1`.
2252

23-
- app version update to 9.0.1
53+
> **Important:** The upgrade to `9.x` requires a specific upgrade path (the latest upgrade path can be found [here](https://www.elastic.co/docs/deploy-manage/upgrade/prepare-to-upgrade#prepare-upgrade-from-8.x)). Before installing `9.0.0`, you must first update to `8.18.1`, otherwise the upgrade will fail. Use version `8.18.1-fb-migr-filestream` from our stack for an easy upgrade.
2454
25-
> Important: The upgrade to version 9.x requires a specific upgrade path (the latest upgrade path can be found [here](https://www.elastic.co/docs/deploy-manage/upgrade/prepare-to-upgrade#prepare-upgrade-from-8.x)). Before installing version 9.0.0, a version update to 8.18.1 must be made, otherwise the upgrade will fail. Use version "8.18.1-fb-migr-filestream" from our stack for easy upgrading.
55+
## [8.18.1-fb-migr-filestream] - 2025-05-28
2656

27-
### 8.18.1-fb-migr-filestream
57+
### Added
58+
- Added the Filebeat `filestream` input and set the `take_over` tag as part of the migration from the deprecated `container` input.
2859

29-
> Important: In preparation for the upgrade to version 9.0.0, this update must be installed as part of the upgrade path. Otherwise Filebeat will not be functional after upgrading to v9.0.0.
60+
### Changed
61+
- The `container` input for Filebeat was deprecated in `7.16` and is fully disabled in `9.0.0` (see [elastic/beats#42295](https://github.com/elastic/beats/pull/42295)). Following the official [migration guide](https://www.elastic.co/docs/reference/beats/filebeat/migrate-to-filestream), the `take_over` tag lets Filebeat separate logs created by the `container` input from the `filestream` input, avoiding errors and duplicated data. In `9.0.0` the `take_over` tag will be removed to complete the migration.
3062

31-
The `container` input for Filebeat was deprecated in version `7.16` and is completely disabled by version `9.0.0` (see [#42295](https://github.com/elastic/beats/pull/42295)).
32-
Following the official [migration guide](https://www.elastic.co/docs/reference/beats/filebeat/migrate-to-filestream), in preparation for the migration from `container` input to `filestream`, a specific tag `take_over` must be set, so Filebeat can separate logs created by the container input from the filestream input. Otherwise an error is thrown and data may be duplicated.
63+
> **Important:** In preparation for the upgrade to `9.0.0`, this update must be installed as part of the upgrade path. Otherwise Filebeat will not be functional after upgrading to `9.0.0`.
3364
34-
- this Helm chart version adds the `filestream` input and sets the `take_over` tag as part of the migration
35-
- in version `9.0.0` the `take_over` tag will be removed to complete the migration
65+
## [8.18.1-fb-tolerations] - 2025-05-14
3666

37-
### 8.18.1-fb-tolerations
67+
### Fixed
68+
- Fixed a bug that caused tolerations rendering to fail for Filebeat.
3869

39-
- fixed a bug in the Helm chart that caused tolerations rendering to fail for Filebeat
70+
## [8.18.1] - 2025-05-07
4071

41-
### 8.18.1
72+
### Changed
73+
- Updated the Elastic stack (`appVersion`) to `8.18.1`.
74+
- Updated the Elastic operator to `3.0.0` in preparation for the `appVersion` upgrade to `9.0.0`.
4275

43-
- app version update to 8.18.1
44-
- elastic operator update to 3.0.0 in preparation for app version upgrade to 9.0.0
76+
[9.4.0]: https://github.com/iits-consulting/charts/compare/elastic-operator-9.3.7...elastic-operator-9.4.0
77+
[9.3.7]: https://github.com/iits-consulting/charts/compare/elastic-operator-9.3.5...elastic-operator-9.3.7
78+
[9.3.5]: https://github.com/iits-consulting/charts/compare/elastic-operator-9.3.3...elastic-operator-9.3.5
79+
[9.3.3]: https://github.com/iits-consulting/charts/compare/elastic-operator-9.0.5-bitnamilegacy...elastic-operator-9.3.3
80+
[9.0.5-bitnamilegacy]: https://github.com/iits-consulting/charts/compare/elastic-operator-9.0.1...elastic-operator-9.0.5-bitnamilegacy
81+
[9.0.1]: https://github.com/iits-consulting/charts/compare/elastic-operator-8.18.1-fb-migr-filestream...elastic-operator-9.0.1
82+
[8.18.1-fb-migr-filestream]: https://github.com/iits-consulting/charts/compare/elastic-operator-8.18.1-fb-tolerations...elastic-operator-8.18.1-fb-migr-filestream
83+
[8.18.1-fb-tolerations]: https://github.com/iits-consulting/charts/compare/elastic-operator-8.18.1...elastic-operator-8.18.1-fb-tolerations
84+
[8.18.1]: https://github.com/iits-consulting/charts/releases/tag/elastic-operator-8.18.1

charts/elastic-operator/Chart.lock

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,8 @@ dependencies:
22
- name: eck-operator
33
repository: https://helm.elastic.co
44
version: 3.4.0
5-
digest: sha256:b4787630154471f65ceeb12f65fa24616eab9470e61e089b8e656e42f05f74f1
6-
generated: "2026-06-15T15:20:27.865783+02:00"
5+
- name: common
6+
repository: https://charts.iits.tech
7+
version: 0.4.0
8+
digest: sha256:fd1b8c5dfa8ced4da0918e1d484db7f18efa2273ffb0b0caa8b60f71ba750243
9+
generated: "2026-06-23T13:59:30.065706+02:00"

charts/elastic-operator/Chart.yaml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
11
apiVersion: v2
22
name: elastic-operator
3-
version: 9.3.7
4-
appVersion: 9.3.7
3+
version: 9.4.0
4+
appVersion: 9.4.0
55
dependencies:
66
- name: eck-operator
77
repository: https://helm.elastic.co
88
version: 3.4.0
9+
- name: common
10+
repository: "https://charts.iits.tech"
11+
version: 0.4.0
912
description: |
1013
Elasticsearch + filebeat + kibana with default common used indexes and Index Lifecycle Management.
1114
It comes also with a backup functionality. This is the version using ECK-operator to deploy and monitor the stack.

charts/elastic-operator/MIGRATION.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,4 +62,4 @@ Generally updates should just work in-place. But:
6262
* **Template:** `elasticsearch-data-{{ $.Release.Name }}-es-default-{{ $i }}`
6363
* `elasticsearch-data-elastic-operator-es-default-0` (using default values)
6464
* `elasticsearch-data-elastic-operator-es-default-1` (using default values)
65-
65+

charts/elastic-operator/README.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# elastic-operator
22

3-
![Version: 9.3.7](https://img.shields.io/badge/Version-9.3.7-informational?style=flat-square) ![AppVersion: 9.3.7](https://img.shields.io/badge/AppVersion-9.3.7-informational?style=flat-square)
3+
![Version: 9.4.0](https://img.shields.io/badge/Version-9.4.0-informational?style=flat-square) ![AppVersion: 9.4.0](https://img.shields.io/badge/AppVersion-9.4.0-informational?style=flat-square)
44

55
Elasticsearch + filebeat + kibana with default common used indexes and Index Lifecycle Management.
66
It comes also with a backup functionality. This is the version using ECK-operator to deploy and monitor the stack.
@@ -9,6 +9,7 @@ It comes also with a backup functionality. This is the version using ECK-operato
99

1010
| Repository | Name | Version |
1111
|------------|------|---------|
12+
| https://charts.iits.tech | common | 0.4.0 |
1213
| https://helm.elastic.co | eck-operator | 3.4.0 |
1314

1415
## Values
@@ -34,11 +35,11 @@ It comes also with a backup functionality. This is the version using ECK-operato
3435
| auth.roles.custom_filebeat.indices[0].privileges[3] | string | `"view_index_metadata"` | |
3536
| auth.roles.custom_filebeat.indices[0].privileges[4] | string | `"manage_follow_index"` | |
3637
| auth.users.custom_elastalert.existingPassword | string | `""` | |
37-
| auth.users.custom_elastalert.roles[0] | string | `"custom_elastalert"` | |
38+
| auth.users.custom_elastalert.roles | list | `["custom_elastalert"]` | Required, if common.externalSecret.enabled. path: "REPLACE_ME" |
3839
| auth.users.custom_filebeat.existingPassword | string | `""` | |
39-
| auth.users.custom_filebeat.roles[0] | string | `"custom_filebeat"` | |
40+
| auth.users.custom_filebeat.roles | list | `["custom_filebeat"]` | field within the vault secret to read/write (default "password"). Override to pack several users into one vault secret distinguished by property. property: "filebeat_password" |
4041
| auth.users.custom_kibana_guest.existingPassword | string | `""` | |
41-
| auth.users.custom_kibana_guest.roles[0] | string | `"viewer"` | |
42+
| auth.users.custom_kibana_guest.roles | list | `["viewer"]` | Required, if common.externalSecret.enabled. path: "REPLACE_ME" |
4243
| backup.enabled | bool | `false` | |
4344
| backup.image.repository | string | `"docker.io/curlimages/curl"` | |
4445
| backup.image.tag | string | `"8.13.0"` | |
@@ -53,8 +54,10 @@ It comes also with a backup functionality. This is the version using ECK-operato
5354
| backup.repoName | string | `"elastic-backups"` | |
5455
| backup.repoType | string | `"s3"` | for Azure blob storage use "azure" |
5556
| backup.repositorySettings | string | `nil` | |
56-
| backup.secureSettings | string | `nil` | |
57+
| backup.secureSettings | string | `nil` | vault path for the secure settings, used only in ESO mode (common.externalSecret.enabled). The settings below are then pulled from this path instead of being inlined. path: "REPLACE_ME" In ESO mode (common.externalSecret.enabled) the value of each setting is the vault property to read (remoteKey), not the literal secret — leave empty to default the property to the setting name. |
5758
| backup.tolerations | list | `[]` | |
59+
| common.externalSecret.enabled | bool | `false` | Enable ESO mode. When true, the bash generate-passwords job and the static basic-auth Secrets are replaced by a single Password generator plus a per-user push/pull round-trip against the secretStore below. Per-user vault paths come from auth.users.<user>.path. |
60+
| common.externalSecret.secretStore | object | `{"kind":"ClusterSecretStore","name":"vault"}` | Sets the Store for all externalSecret resources from common chart |
5861
| eck-operator.securityContext.seccompProfile.type | string | `"RuntimeDefault"` | |
5962
| elasticsearch.config.cluster.max_shards_per_node | int | `30000` | |
6063
| elasticsearch.config.http.max_header_size | string | `"16kb"` | |
@@ -149,17 +152,20 @@ It comes also with a backup functionality. This is the version using ECK-operato
149152
| filebeat.volumes[1].hostPath.path | string | `"/var/log"` | |
150153
| filebeat.volumes[1].hostPath.type | string | `""` | |
151154
| filebeat.volumes[1].name | string | `"varlog"` | |
152-
| generatePasswords.enabled | bool | `true` | |
155+
| generatePasswords.deletionPolicy | string | `"Delete"` | ESO mode only: defines if secrets pushed to the secretStore are deleted or kept in the provider after the ESO pushSecret is deleted. |
156+
| generatePasswords.enabled | bool | `true` | Generate user passwords. In non-ESO mode this toggles the bash generate-passwords job. In ESO mode (common.externalSecret.enabled) it toggles the Password generator + push: true generates and round-trips through vault; false is BYO (pull-only, passwords pre-seeded in vault). |
153157
| generatePasswords.image.repository | string | `"docker.io/bitnamilegacy/kubectl"` | |
154158
| generatePasswords.image.tag | string | `"1.32.4"` | |
155159
| generatePasswords.image.userId | int | `100` | |
156160
| generatePasswords.nodeSelector | object | `{}` | |
161+
| generatePasswords.refreshInterval | string | `"1h"` | ESO mode only: how often the per-user push/pull secrets reconcile. Leave empty to use the common chart's per-resource defaults (push "1h", pull "1m"). |
157162
| generatePasswords.secrets[0].key | string | `"password"` | |
158163
| generatePasswords.secrets[0].name | string | `"{{ .Release.Name }}-user-custom-kibana-guest"` | |
159164
| generatePasswords.secrets[1].key | string | `"password"` | |
160165
| generatePasswords.secrets[1].name | string | `"{{ .Release.Name }}-user-custom-filebeat"` | |
161166
| generatePasswords.secrets[2].key | string | `"password"` | |
162167
| generatePasswords.secrets[2].name | string | `"{{ .Release.Name }}-user-custom-elastalert"` | |
168+
| generatePasswords.spec | object | `{"allowRepeat":true,"digits":5,"length":32,"noUpper":false,"symbols":0}` | Password generation policy. In ESO mode (common.externalSecret.enabled) this maps directly to the shared ExternalSecrets Password generator spec; length also feeds the bash job default. |
163169
| generatePasswords.tolerations | list | `[]` | |
164170
| ilm.image.repository | string | `"docker.io/curlimages/curl"` | |
165171
| ilm.image.tag | string | `"8.13.0"` | |

charts/elastic-operator/UPGRADE.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,50 @@
1+
# Upgrade to Version 9.4.0
2+
## Migrating to ESO mode (chart `9.4.0+`)
3+
4+
When `common.externalSecret.enabled: true`, vault becomes canonical for user passwords (and, when `backup.enabled`, for backup credentials). The bash `generate-passwords` Job and the Helm-rendered basic-auth Secrets are replaced by a single ExternalSecrets `Password` generator plus a per-user push/pull round-trip against the store in `common.externalSecret.secretStore`.
5+
6+
### Preconditions
7+
8+
* External Secrets Operator (ESO) is installed
9+
* A `ClusterSecretStore` (or `SecretStore`) for vault exists, referenced via `common.externalSecret.secretStore.{kind,name}`
10+
* Remove any `auth.users.<user>.existingPassword` values — they have no effect in ESO mode (vault is canonical) and the chart refuses to render while they are set.
11+
12+
### User passwords
13+
14+
Each user under `auth.users` is round-tripped through vault:
15+
16+
* `auth.users.<user>.path` — vault secret path for that user (**required** in ESO mode).
17+
* `auth.users.<user>.property` — field within that vault secret (default `password`); override it to pack several users into one vault secret.
18+
* The Kubernetes Secret key stays `password` (the filebeat/kibana env refs depend on it).
19+
20+
To preserve existing passwords across the flip, pre-seed vault first; otherwise the `Password` generator produces new values on first sync.
21+
22+
1. For each user in `auth.users`, write the existing password to `auth.users.<user>.path` in vault, under the field from `auth.users.<user>.property` (or `password` if unset).
23+
2. Flip `common.externalSecret.enabled: true` and sync.
24+
25+
With `generatePasswords.enabled: true`, the PushSecret uses `updatePolicy: IfNotExists`, so pre-seeded vault values survive (a rebuild never rotates them) and the ExternalSecret pulls them back into the K8s Secret. With `generatePasswords.enabled: false` the generator and push are skipped (pull-only / BYO), so passwords **must** be pre-seeded in vault by an external owner.
26+
27+
With Argo's default `prune: true` + `selfHeal: true`, the old Helm-rendered Secret is pruned and ESO recreates it automatically — expect a small gap during reconciliation.
28+
29+
### Backup credentials (when `backup.enabled`)
30+
31+
Backup credentials are externally managed (e.g. Terraform), so backup is pull-only — there is no push/round-trip for it. In ESO mode:
32+
33+
* `backup.path` — vault path the backup secure-settings secret is pulled from (**required** when `backup.secureSettings` is set).
34+
* `backup.secureSettings.<setting>` — the value is now the vault **property name** to read, not the literal secret; leave it empty to default the property to the setting name. The legacy `${vault:...}` webhook syntax is rejected.
35+
* `backup.repositorySettings.<key>` — these are not pulled from vault in ESO mode; replace any `${vault:...}` placeholders with the literal hardcoded value (the legacy webhook syntax is rejected).
36+
* `cce.elasticsearch.volumes[].{id,az,kmsId}` — a PersistentVolume cannot source values from a Secret, so set these as plain literals, not `${vault:...}` placeholders.
37+
38+
### Verify post-upgrade
39+
40+
* `kubectl get pushsecret,externalsecret -n <ns>` — all `Synced`
41+
* ECK-managed Elasticsearch reaches `Ready`
42+
* Downstream consumers (filebeat, falco, etc.) continue authenticating
43+
44+
### Rolling back
45+
46+
Set `common.externalSecret.enabled: false` and re-sync — chart reverts to the bash `generate-passwords` Job + Helm-rendered Secrets path. ESO CRs are pruned by Argo; the K8s Secrets they created stay until pruned or replaced by the Helm-rendered ones.
47+
148
# Upgrade to Version 9.3.7
249
from 9.3.5
350

charts/elastic-operator/templates/volumes/otc/_helper.tpl renamed to charts/elastic-operator/templates/_helpers.tpl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
{{- define "elasticOperator.elasticSearch.users.checksum" -}}
2+
{{- if .Values.common.externalSecret.enabled }}
3+
{{- .Values.auth.users | toYaml | sha256sum | substr 0 50 }}
4+
{{- else }}
5+
{{- include (print $.Template.BasePath "/eks-stack/elasticsearch-users.yaml") $ | sha256sum | substr 0 50 }}
6+
{{- end }}
7+
{{- end -}}
8+
9+
{{/* Elasticsearch data volumeClaimTemplate for OTC/CCE everest-provisioned storage */}}
110
{{- define "template.otcPVC" -}}
211
metadata:
312
name: elasticsearch-data # See: https://www.elastic.co/guide/en/cloud-on-k8s/master/k8s-volume-claim-templates.html#k8s_specifying_the_volume_claim_settings

0 commit comments

Comments
 (0)