Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
d45f8fb
wip: add run-securityadmin job
labrenbe Aug 14, 2025
c489b44
configure tls on run-securityadmin
labrenbe Aug 15, 2025
ffa0585
add tls secret class to crd
labrenbe Aug 19, 2025
aaa560f
Merge remote-tracking branch 'origin/main' into feat/run-securityadmi…
labrenbe Aug 19, 2025
4d7496c
add tls volume to sts
labrenbe Aug 20, 2025
7f805b8
add tls config to opensearch.yml
labrenbe Aug 21, 2025
c6db525
disable security demo install
labrenbe Aug 22, 2025
1c3e672
Merge remote-tracking branch 'origin/main' into feat/run-securityadmi…
labrenbe Oct 24, 2025
bbbdbb6
wip amend integration tests
labrenbe Oct 27, 2025
1aeb4db
Merge remote-tracking branch 'origin/main' into feat/tls-support
labrenbe Oct 27, 2025
ab42f5a
fix smoke test
labrenbe Oct 28, 2025
97681a3
restore properties file
labrenbe Oct 28, 2025
815d243
mount tls volume in default directory of official image
labrenbe Oct 28, 2025
95986a5
use tls feature in all integration tests
labrenbe Oct 28, 2025
910a58d
use OPENSEARCH_PATH_CONF for tls config
labrenbe Oct 28, 2025
9252b06
Merge remote-tracking branch 'origin/main' into feat/tls-support
labrenbe Oct 28, 2025
beb2aff
fix incorrectly resolved merge conflict
labrenbe Oct 28, 2025
383e358
Merge remote-tracking branch 'origin/main' into feat/tls-support
labrenbe Nov 4, 2025
25745d1
wip: adress feedback on pr
labrenbe Nov 6, 2025
bcb5542
Merge remote-tracking branch 'origin/main' into feat/tls-support
labrenbe Nov 6, 2025
8257b95
address feedback on PR
labrenbe Nov 13, 2025
bd86ebc
Merge remote-tracking branch 'origin/main' into feat/tls-support
labrenbe Nov 13, 2025
36120a8
add changelog entry
labrenbe Nov 13, 2025
0294f91
rename CRD fields based on decision
labrenbe Nov 17, 2025
cb97dee
Merge remote-tracking branch 'origin/main' into feat/tls-support
labrenbe Nov 28, 2025
7c6e1d9
Merge branch 'main' into feat/tls-support
siegfriedweber Dec 3, 2025
cfc730a
address feedback on PR
labrenbe Dec 9, 2025
d94777e
Merge remote-tracking branch 'origin/main' into feat/tls-support
labrenbe Dec 9, 2025
ce4e355
address more feedback on PR
labrenbe Dec 10, 2025
4b007f1
remove duplicate SecretClassName length check
labrenbe Dec 10, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ All notable changes to this project will be documented in this file.
### Added

- Add the role group as a node attribute ([#63]).
- Allow the configuration of TLS for the HTTP and TRANSPORT ports with the operator ([#55]).

[#55]: https://github.com/stackabletech/opensearch-operator/pull/55
[#63]: https://github.com/stackabletech/opensearch-operator/pull/63

## [25.11.0] - 2025-11-07
Expand Down
51 changes: 50 additions & 1 deletion deploy/helm/opensearch-operator/crds/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,42 @@ spec:
generates in the [operator documentation](https://docs.stackable.tech/home/nightly/opensearch/).
properties:
clusterConfig:
default: {}
default:
tls:
internalSecretClass: tls
serverSecretClass: tls
description: Configuration that applies to all roles and role groups
properties:
tls:
default:
internalSecretClass: tls
serverSecretClass: tls
description: TLS configuration options for the server (REST API) and internal communication (transport).
properties:
internalSecretClass:
default: tls
description: |-
Only affects internal communication (transport). Used for mutual verification between OpenSearch nodes.
This setting controls:
- Which cert the servers should use to authenticate themselves against other servers
- Which ca.crt to use when validating the other server
maxLength: 253
minLength: 1
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
type: string
serverSecretClass:
default: tls
description: |-
Only affects client connections to the REST API.
This setting controls:
- If TLS encryption is used at all
- Which cert the servers should use to authenticate themselves against the client
maxLength: 253
minLength: 1
nullable: true
pattern: ^[a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*$
type: string
type: object
vectorAggregatorConfigMapName:
description: |-
Name of the Vector aggregator [discovery ConfigMap](https://docs.stackable.tech/home/nightly/concepts/service_discovery).
Expand Down Expand Up @@ -305,6 +338,14 @@ spec:
type: string
nullable: true
type: array
requestedSecretLifetime:
description: |-
Request secret (currently only autoTls certificates) lifetime from the secret operator, e.g. `7d`, or `30d`.
This can be shortened by the `maxCertificateLifetime` setting on the SecretClass issuing the TLS certificate.

Defaults to 1d.
nullable: true
type: string
resources:
default:
cpu:
Expand Down Expand Up @@ -654,6 +695,14 @@ spec:
type: string
nullable: true
type: array
requestedSecretLifetime:
description: |-
Request secret (currently only autoTls certificates) lifetime from the secret operator, e.g. `7d`, or `30d`.
This can be shortened by the `maxCertificateLifetime` setting on the SecretClass issuing the TLS certificate.

Defaults to 1d.
nullable: true
type: string
resources:
default:
cpu:
Expand Down
25 changes: 0 additions & 25 deletions docs/modules/opensearch/examples/getting_started/opensearch.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,6 @@ spec:
opensearch.yml:
plugins.security.allow_default_init_securityindex: "true"
plugins.security.restapi.roles_enabled: all_access
plugins.security.ssl.transport.enabled: "true"
plugins.security.ssl.transport.pemcert_filepath: /stackable/opensearch/config/tls/tls.crt
plugins.security.ssl.transport.pemkey_filepath: /stackable/opensearch/config/tls/tls.key
plugins.security.ssl.transport.pemtrustedcas_filepath: /stackable/opensearch/config/tls/ca.crt
plugins.security.ssl.http.enabled: "true"
plugins.security.ssl.http.pemcert_filepath: /stackable/opensearch/config/tls/tls.crt
plugins.security.ssl.http.pemkey_filepath: /stackable/opensearch/config/tls/tls.key
plugins.security.ssl.http.pemtrustedcas_filepath: /stackable/opensearch/config/tls/ca.crt
podOverrides:
spec:
containers:
Expand All @@ -30,25 +22,8 @@ spec:
- name: security-config
mountPath: /stackable/opensearch/config/opensearch-security
readOnly: true
- name: tls
mountPath: /stackable/opensearch/config/tls
readOnly: true
volumes:
- name: security-config
secret:
secretName: opensearch-security-config
defaultMode: 0o660
- name: tls
ephemeral:
volumeClaimTemplate:
metadata:
annotations:
secrets.stackable.tech/class: tls
secrets.stackable.tech/scope: node,pod,service=simple-opensearch,service=simple-opensearch-nodes-default,service=simple-opensearch-nodes-default-headless
spec:
storageClassName: secrets.stackable.tech
accessModes:
- ReadWriteOnce
resources:
requests:
storage: "1"
40 changes: 40 additions & 0 deletions docs/modules/opensearch/pages/usage-guide/security.adoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
= Security
:description: Configure TLS encryption for OpenSearch with the Stackable Operator.

== TLS

The internal and client communication at the REST API can be encrypted with TLS.
This requires the xref:secret-operator:index.adoc[Secret Operator] to be running in the Kubernetes cluster providing certificates.
The used certificates can be changed in a cluster-wide config and are configured using xref:secret-operator:secretclass.adoc[SecretClasses].
TLS encryption on the REST API may be disabled, while it is always enabled for the internal communication between nodes using the `transport` port.

[source,yaml]
----
---
apiVersion: opensearch.stackable.tech/v1alpha1
kind: OpenSearchCluster
metadata:
name: opensearch
spec:
image:
productVersion: 3.1.0
clusterConfig:
tls:
serverSecretClass: tls # <1>
internalSecretClass: opensearch-internal-tls # <2>
nodes:
config:
requestedSecretLifetime: 7d # <3>
roleGroups:
default:
replicas: 3
----
<1> The `spec.clusterConfig.tls.serverSecretClass` refers to the client-to-server encryption at the REST API.
Defaults to the `tls` SecretClass and can be disabled by setting `serverSecretClass` to `null`.
<2> The `spec.clusterConfig.tls.internalSecretClass` refers to the internal encryption between OpenSearch nodes using mTLS (transport).
Defaults to the `tls` SecretClass and can't be disabled.
<3> The lifetime for autoTls certificates generated by the secret operator.
Only a lifetime up to the `maxCertificateLifetime` setting in the SecretClass is applied.

Important: The operator sets the configuration `plugins.security.nodes_dn` to `["CN=generated certificate for pod"]` which provides weak authentication between nodes.
If you want to increase security and use certificates which identify the OpenSearch nodes specifically, you must also adapt the `plugins.security.nodes_dn` setting via configOverrides.
1 change: 1 addition & 0 deletions docs/modules/opensearch/partials/nav.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
** xref:opensearch:usage-guide/logging.adoc[]
** xref:opensearch:usage-guide/opensearch-dashboards.adoc[]
** xref:opensearch:usage-guide/scaling.adoc[]
** xref:opensearch:usage-guide/security.adoc[]
** xref:opensearch:usage-guide/operations/index.adoc[]
*** xref:opensearch:usage-guide/operations/cluster-operations.adoc[]
*** xref:opensearch:usage-guide/operations/pod-placement.adoc[]
Expand Down
14 changes: 10 additions & 4 deletions rust/operator-binary/src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ use update_status::update_status;
use validate::validate;

use crate::{
crd::{
NodeRoles,
v1alpha1::{self},
},
crd::{NodeRoles, v1alpha1},
framework::{
HasName, HasUid, NameIsValidLabelValue,
product_logging::framework::{ValidatedContainerLogConfigChoice, VectorContainerLogConfig},
Expand Down Expand Up @@ -137,6 +134,7 @@ pub struct ValidatedOpenSearchConfig {
pub listener_class: ListenerClassName,
pub logging: ValidatedLogging,
pub node_roles: NodeRoles,
pub requested_secret_lifetime: Duration,
pub resources: OpenSearchNodeResources,
pub termination_grace_period_seconds: i64,
}
Expand Down Expand Up @@ -172,9 +170,11 @@ pub struct ValidatedCluster {
pub uid: Uid,
pub role_config: GenericRoleConfig,
pub role_group_configs: BTreeMap<RoleGroupName, OpenSearchRoleGroupConfig>,
pub tls_config: v1alpha1::OpenSearchTls,
}

impl ValidatedCluster {
#[allow(clippy::too_many_arguments)]
pub fn new(
image: ResolvedProductImage,
product_version: ProductVersion,
Expand All @@ -183,6 +183,7 @@ impl ValidatedCluster {
uid: impl Into<Uid>,
role_config: GenericRoleConfig,
role_group_configs: BTreeMap<RoleGroupName, OpenSearchRoleGroupConfig>,
tls_config: v1alpha1::OpenSearchTls,
) -> Self {
let uid = uid.into();
ValidatedCluster {
Expand All @@ -199,6 +200,7 @@ impl ValidatedCluster {
uid,
role_config,
role_group_configs,
tls_config,
}
}

Expand Down Expand Up @@ -378,6 +380,7 @@ mod tests {
kvp::LabelValue,
product_logging::spec::AutomaticContainerLogConfig,
role_utils::GenericRoleConfig,
shared::time::Duration,
};
use uuid::uuid;

Expand Down Expand Up @@ -503,6 +506,7 @@ mod tests {
),
]
.into(),
v1alpha1::OpenSearchTls::default(),
)
}

Expand All @@ -522,6 +526,8 @@ mod tests {
vector_container: None,
},
node_roles: NodeRoles(node_roles.to_vec()),
requested_secret_lifetime: Duration::from_str("1d")
.expect("should be a valid duration"),
resources: OpenSearchNodeResources::default(),
termination_grace_period_seconds: 120,
},
Expand Down
4 changes: 4 additions & 0 deletions rust/operator-binary/src/controller/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ mod tests {
kvp::LabelValue,
product_logging::spec::AutomaticContainerLogConfig,
role_utils::GenericRoleConfig,
shared::time::Duration,
};
use uuid::uuid;

Expand Down Expand Up @@ -197,6 +198,7 @@ mod tests {
),
]
.into(),
v1alpha1::OpenSearchTls::default(),
)
}

Expand All @@ -216,6 +218,8 @@ mod tests {
vector_container: None,
},
node_roles: NodeRoles(node_roles.to_vec()),
requested_secret_lifetime: Duration::from_str("1d")
.expect("should be a valid duration"),
resources: OpenSearchNodeResources::default(),
termination_grace_period_seconds: 120,
},
Expand Down
Loading