diff --git a/CHANGELOG.md b/CHANGELOG.md index 52a6d74..e220346 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ 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]). [#63]: https://github.com/stackabletech/opensearch-operator/pull/63 diff --git a/deploy/helm/opensearch-operator/crds/crds.yaml b/deploy/helm/opensearch-operator/crds/crds.yaml index 12f3da0..14e6c14 100644 --- a/deploy/helm/opensearch-operator/crds/crds.yaml +++ b/deploy/helm/opensearch-operator/crds/crds.yaml @@ -29,9 +29,40 @@ 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 + 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 + type: string + type: object vectorAggregatorConfigMapName: description: |- Name of the Vector aggregator [discovery ConfigMap](https://docs.stackable.tech/home/nightly/concepts/service_discovery). @@ -303,6 +334,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: @@ -651,6 +690,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: diff --git a/docs/modules/opensearch/examples/getting_started/opensearch.yaml b/docs/modules/opensearch/examples/getting_started/opensearch.yaml index e98b45a..6def257 100644 --- a/docs/modules/opensearch/examples/getting_started/opensearch.yaml +++ b/docs/modules/opensearch/examples/getting_started/opensearch.yaml @@ -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: @@ -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" diff --git a/docs/modules/opensearch/pages/usage-guide/security.adoc b/docs/modules/opensearch/pages/usage-guide/security.adoc new file mode 100644 index 0000000..84131ee --- /dev/null +++ b/docs/modules/opensearch/pages/usage-guide/security.adoc @@ -0,0 +1,55 @@ += Security +:description: Configure TLS encryption, authentication, and Open Policy Agent (OPA) authorization for Kafka 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. 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. + +The `tls` secret is deployed from the xref:secret-operator:index.adoc[Secret Operator] and looks like this: + +[source,yaml] +---- +--- +apiVersion: secrets.stackable.tech/v1alpha1 +kind: SecretClass +metadata: + name: tls +spec: + backend: + autoTls: + ca: + secret: + name: secret-provisioner-tls-ca + namespace: default + autoGenerate: true + maxCertificateLifetime: 15d +---- + +You can create your own secrets and reference them e.g. in the `spec.clusterConfig.tls.serverSecretClass` or `spec.clusterConfig.tls.internalSecretClass` to use different certificates. diff --git a/rust/operator-binary/src/controller.rs b/rust/operator-binary/src/controller.rs index 832e488..843d349 100644 --- a/rust/operator-binary/src/controller.rs +++ b/rust/operator-binary/src/controller.rs @@ -30,7 +30,7 @@ use validate::validate; use crate::{ crd::{ NodeRoles, - v1alpha1::{self}, + v1alpha1::{self, OpenSearchTls}, }, framework::{ ClusterName, ControllerName, HasName, HasUid, ListenerClassName, NameIsValidLabelValue, @@ -131,6 +131,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, } @@ -166,9 +167,11 @@ pub struct ValidatedCluster { pub uid: Uid, pub role_config: GenericRoleConfig, pub role_group_configs: BTreeMap, + pub tls_config: OpenSearchTls, } impl ValidatedCluster { + #[allow(clippy::too_many_arguments)] pub fn new( image: ResolvedProductImage, product_version: ProductVersion, @@ -177,6 +180,7 @@ impl ValidatedCluster { uid: impl Into, role_config: GenericRoleConfig, role_group_configs: BTreeMap, + tls_config: OpenSearchTls, ) -> Self { let uid = uid.into(); ValidatedCluster { @@ -193,6 +197,7 @@ impl ValidatedCluster { uid, role_config, role_group_configs, + tls_config, } } @@ -372,13 +377,17 @@ mod tests { kvp::LabelValue, product_logging::spec::AutomaticContainerLogConfig, role_utils::GenericRoleConfig, + shared::time::Duration, }; use uuid::uuid; use super::{Context, OpenSearchRoleGroupConfig, ValidatedCluster, ValidatedLogging}; use crate::{ controller::{OpenSearchNodeResources, ValidatedOpenSearchConfig}, - crd::{NodeRoles, v1alpha1}, + crd::{ + NodeRoles, + v1alpha1::{self, OpenSearchTls}, + }, framework::{ ClusterName, ListenerClassName, NamespaceName, OperatorName, ProductVersion, RoleGroupName, builder::pod::container::EnvVarSet, @@ -494,6 +503,7 @@ mod tests { ), ] .into(), + OpenSearchTls::default(), ) } @@ -513,6 +523,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, }, diff --git a/rust/operator-binary/src/controller/build.rs b/rust/operator-binary/src/controller/build.rs index 43c3bda..e95ba33 100644 --- a/rust/operator-binary/src/controller/build.rs +++ b/rust/operator-binary/src/controller/build.rs @@ -68,6 +68,7 @@ mod tests { kvp::LabelValue, product_logging::spec::AutomaticContainerLogConfig, role_utils::GenericRoleConfig, + shared::time::Duration, }; use uuid::uuid; @@ -77,7 +78,10 @@ mod tests { ContextNames, OpenSearchNodeResources, OpenSearchRoleGroupConfig, ValidatedCluster, ValidatedContainerLogConfigChoice, ValidatedLogging, ValidatedOpenSearchConfig, }, - crd::{NodeRoles, v1alpha1}, + crd::{ + NodeRoles, + v1alpha1::{self, OpenSearchTls}, + }, framework::{ ClusterName, ControllerName, ListenerClassName, NamespaceName, OperatorName, ProductName, ProductVersion, RoleGroupName, builder::pod::container::EnvVarSet, @@ -191,6 +195,7 @@ mod tests { ), ] .into(), + OpenSearchTls::default(), ) } @@ -210,6 +215,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, }, diff --git a/rust/operator-binary/src/controller/build/node_config.rs b/rust/operator-binary/src/controller/build/node_config.rs index 9249042..279fa3d 100644 --- a/rust/operator-binary/src/controller/build/node_config.rs +++ b/rust/operator-binary/src/controller/build/node_config.rs @@ -62,12 +62,49 @@ pub const CONFIG_OPTION_PLUGINS_SECURITY_NODES_DN: &str = "plugins.security.node pub const CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_ENABLED: &str = "plugins.security.ssl.http.enabled"; +/// Path to the cert PEM file used for TLS on the HTTP PORT. +/// type: string +pub const CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_PEMCERT_FILEPATH: &str = + "plugins.security.ssl.http.pemcert_filepath"; + +/// Path to the key PEM file used for TLS on the HTTP PORT. +/// type: string +pub const CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_PEMKEY_FILEPATH: &str = + "plugins.security.ssl.http.pemkey_filepath"; + +/// Path to the trusted CAs PEM file used for TLS on the HTTP PORT. +/// type: string +pub const CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH: &str = + "plugins.security.ssl.http.pemtrustedcas_filepath"; + +/// Whether to enable TLS on internal node-to-node communication using the transport port. +/// type: boolean +pub const CONFIG_OPTION_PLUGINS_SECURITY_SSL_TRANSPORT_ENABLED: &str = + "plugins.security.ssl.transport.enabled"; + +/// Path to the cert PEM file used for TLS on the transport PORT. +/// type: string +pub const CONFIG_OPTION_PLUGINS_SECURITY_SSL_TRANSPORT_PEMCERT_FILEPATH: &str = + "plugins.security.ssl.transport.pemcert_filepath"; + +/// Path to the key PEM file used for TLS on the transport PORT. +/// type: string +pub const CONFIG_OPTION_PLUGINS_SECURITY_SSL_TRANSPORT_PEMKEY_FILEPATH: &str = + "plugins.security.ssl.transport.pemkey_filepath"; + +/// Path to the trusted CAs PEM file used for TLS on the transport PORT. +/// type: string +pub const CONFIG_OPTION_PLUGINS_SECURITY_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH: &str = + "plugins.security.ssl.transport.pemtrustedcas_filepath"; + +const DEFAULT_OPENSEARCH_HOME: &str = "/stackable/opensearch"; + /// Configuration of an OpenSearch node based on the cluster and role-group configuration pub struct NodeConfig { cluster: ValidatedCluster, role_group_name: RoleGroupName, role_group_config: OpenSearchRoleGroupConfig, - discovery_service_name: ServiceName, + pub discovery_service_name: ServiceName, } // Most functions are public because their configuration values could also be used in environment @@ -88,8 +125,29 @@ impl NodeConfig { } /// Creates the main OpenSearch configuration file in YAML format - pub fn static_opensearch_config_file_content(&self) -> String { - Self::to_yaml(self.static_opensearch_config()) + pub fn opensearch_config_file_content(&self) -> String { + Self::to_yaml(self.opensearch_config()) + } + + pub fn opensearch_config(&self) -> serde_json::Map { + let mut config = self.static_opensearch_config(); + + config.append(&mut self.tls_config()); + + for (setting, value) in self + .role_group_config + .config_overrides + .get(CONFIGURATION_FILE_OPENSEARCH_YML) + .into_iter() + .flatten() + { + config.insert(setting.to_owned(), json!(value)); + } + + // Ensure a deterministic result + config.sort_keys(); + + config } /// Creates the main OpenSearch configuration file as JSON map @@ -123,25 +181,62 @@ impl NodeConfig { json!(self.role_group_name), ); - for (setting, value) in self - .role_group_config - .config_overrides - .get(CONFIGURATION_FILE_OPENSEARCH_YML) - .into_iter() - .flatten() - { - config.insert(setting.to_owned(), json!(value)); - } + config + } - // Ensure a deterministic result - config.sort_keys(); + pub fn tls_config(&self) -> serde_json::Map { + let mut config = serde_json::Map::new(); + let opensearch_path_conf = self.opensearch_path_conf(); + + // TLS config for TRANSPORT port which is always enabled. + config.insert( + CONFIG_OPTION_PLUGINS_SECURITY_SSL_TRANSPORT_ENABLED.to_owned(), + json!("true".to_string()), + ); + config.insert( + CONFIG_OPTION_PLUGINS_SECURITY_SSL_TRANSPORT_PEMCERT_FILEPATH.to_owned(), + json!(format!("{opensearch_path_conf}/tls/internal/tls.crt")), + ); + config.insert( + CONFIG_OPTION_PLUGINS_SECURITY_SSL_TRANSPORT_PEMKEY_FILEPATH.to_owned(), + json!(format!("{opensearch_path_conf}/tls/internal/tls.key")), + ); + config.insert( + CONFIG_OPTION_PLUGINS_SECURITY_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH.to_owned(), + json!(format!("{opensearch_path_conf}/tls/internal/ca.crt")), + ); + + // TLS config for HTTP port (REST API) (optional). + if self.cluster.tls_config.server_secret_class.is_some() { + config.insert( + CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_ENABLED.to_owned(), + json!("true".to_string()), + ); + config.insert( + CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_PEMCERT_FILEPATH.to_owned(), + json!(format!("{opensearch_path_conf}/tls/server/tls.crt")), + ); + config.insert( + CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_PEMKEY_FILEPATH.to_owned(), + json!(format!("{opensearch_path_conf}/tls/server/tls.key")), + ); + config.insert( + CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH.to_owned(), + json!(format!("{opensearch_path_conf}/tls/server/ca.crt")), + ); + } else { + config.insert( + CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_ENABLED.to_owned(), + json!("false".to_string()), + ); + } config } /// Returns `true` if TLS is enabled on the HTTP port pub fn tls_on_http_port_enabled(&self) -> bool { - self.static_opensearch_config() + self.opensearch_config() .get(CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_ENABLED) .and_then(Self::value_as_bool) == Some(true) @@ -272,6 +367,23 @@ impl NodeConfig { String::new() } } + + /// Return content of the `OPENSEARCH_HOME` environment variable from envOverrides or default to `DEFAULT_OPENSEARCH_HOME` + pub fn opensearch_home(&self) -> String { + self.environment_variables() + .get(&EnvVarName::from_str_unsafe("OPENSEARCH_HOME")) + .and_then(|env_var| env_var.value.clone()) + .unwrap_or(DEFAULT_OPENSEARCH_HOME.to_owned()) + } + + /// Return content of the `OPENSEARCH_PATH_CONF` environment variable from envOverrides or default to `OPENSEARCH_HOME/config` + pub fn opensearch_path_conf(&self) -> String { + let opensearch_home = self.opensearch_home(); + self.environment_variables() + .get(&EnvVarName::from_str_unsafe("OPENSEARCH_PATH_CONF")) + .and_then(|env_var| env_var.value.clone()) + .unwrap_or(format!("{opensearch_home}/config")) + } } #[cfg(test)] @@ -288,13 +400,14 @@ mod tests { kvp::LabelValue, product_logging::spec::AutomaticContainerLogConfig, role_utils::GenericRoleConfig, + shared::time::Duration, }; use uuid::uuid; use super::*; use crate::{ controller::{ValidatedLogging, ValidatedOpenSearchConfig}, - crd::NodeRoles, + crd::{NodeRoles, v1alpha1::OpenSearchTls}, framework::{ ClusterName, ListenerClassName, NamespaceName, ProductVersion, RoleGroupName, product_logging::framework::ValidatedContainerLogConfigChoice, @@ -341,6 +454,8 @@ mod tests { v1alpha1::NodeRole::Ingest, v1alpha1::NodeRole::RemoteClusterClient, ]), + requested_secret_lifetime: Duration::from_str("1d") + .expect("should be a valid duration"), resources: Resources::default(), termination_grace_period_seconds: 30, }, @@ -383,6 +498,7 @@ mod tests { role_group_config.clone(), )] .into(), + OpenSearchTls::default(), ); NodeConfig::new( @@ -407,10 +523,18 @@ mod tests { "network.host: \"0.0.0.0\"\n", "node.attr.role-group: \"data\"\n", "plugins.security.nodes_dn: [\"CN=generated certificate for pod\"]\n", - "test: \"value\"" + "plugins.security.ssl.http.enabled: \"true\"\n", + "plugins.security.ssl.http.pemcert_filepath: \"/stackable/opensearch/config/tls/server/tls.crt\"\n", + "plugins.security.ssl.http.pemkey_filepath: \"/stackable/opensearch/config/tls/server/tls.key\"\n", + "plugins.security.ssl.http.pemtrustedcas_filepath: \"/stackable/opensearch/config/tls/server/ca.crt\"\n", + "plugins.security.ssl.transport.enabled: \"true\"\n", + "plugins.security.ssl.transport.pemcert_filepath: \"/stackable/opensearch/config/tls/internal/tls.crt\"\n", + "plugins.security.ssl.transport.pemkey_filepath: \"/stackable/opensearch/config/tls/internal/tls.key\"\n", + "plugins.security.ssl.transport.pemtrustedcas_filepath: \"/stackable/opensearch/config/tls/internal/ca.crt\"\n", + "test: \"value\"", ) .to_owned(), - node_config.static_opensearch_config_file_content() + node_config.opensearch_config_file_content() ); } @@ -428,7 +552,7 @@ mod tests { ..TestConfig::default() }); - assert!(!node_config_tls_undefined.tls_on_http_port_enabled()); + assert!(node_config_tls_undefined.tls_on_http_port_enabled()); assert!(node_config_tls_enabled.tls_on_http_port_enabled()); assert!(!node_config_tls_disabled.tls_on_http_port_enabled()); } diff --git a/rust/operator-binary/src/controller/build/role_builder.rs b/rust/operator-binary/src/controller/build/role_builder.rs index 454d7d5..aa99d21 100644 --- a/rust/operator-binary/src/controller/build/role_builder.rs +++ b/rust/operator-binary/src/controller/build/role_builder.rs @@ -230,6 +230,7 @@ mod tests { kvp::LabelValue, product_logging::spec::AutomaticContainerLogConfig, role_utils::GenericRoleConfig, + shared::time::Duration, }; use uuid::uuid; @@ -239,7 +240,10 @@ mod tests { ContextNames, OpenSearchRoleGroupConfig, ValidatedCluster, ValidatedContainerLogConfigChoice, ValidatedLogging, ValidatedOpenSearchConfig, }, - crd::{NodeRoles, v1alpha1}, + crd::{ + NodeRoles, + v1alpha1::{self, OpenSearchTls}, + }, framework::{ ClusterName, ControllerName, ListenerClassName, NamespaceName, OperatorName, ProductName, ProductVersion, RoleGroupName, builder::pod::container::EnvVarSet, @@ -276,6 +280,8 @@ mod tests { v1alpha1::NodeRole::Ingest, v1alpha1::NodeRole::RemoteClusterClient, ]), + requested_secret_lifetime: Duration::from_str("1d") + .expect("should be a valid duration"), resources: Resources::default(), termination_grace_period_seconds: 30, }, @@ -305,6 +311,7 @@ mod tests { role_group_config.clone(), )] .into(), + OpenSearchTls::default(), ); RoleBuilder::new(cluster, context_names) diff --git a/rust/operator-binary/src/controller/build/role_group_builder.rs b/rust/operator-binary/src/controller/build/role_group_builder.rs index 896c344..4213fa0 100644 --- a/rust/operator-binary/src/controller/build/role_group_builder.rs +++ b/rust/operator-binary/src/controller/build/role_group_builder.rs @@ -3,7 +3,10 @@ use std::{collections::BTreeMap, str::FromStr}; use stackable_operator::{ - builder::meta::ObjectMetaBuilder, + builder::{ + meta::ObjectMetaBuilder, + pod::volume::{SecretFormat, SecretOperatorVolumeSourceBuilder, VolumeBuilder}, + }, crd::listener::{self}, k8s_openapi::{ DeepMerge, @@ -23,6 +26,7 @@ use stackable_operator::{ VECTOR_CONFIG_FILE, calculate_log_volume_size_limit, create_vector_shutdown_file_command, remove_vector_shutdown_file_command, }, + shared::time::Duration, utils::COMMON_BASH_TRAP_FUNCTIONS, }; @@ -42,11 +46,12 @@ use crate::{ }, crd::v1alpha1, framework::{ - PersistentVolumeClaimName, RoleGroupName, ServiceAccountName, ServiceName, VolumeName, + PersistentVolumeClaimName, RoleGroupName, SecretClassName, ServiceAccountName, ServiceName, + VolumeName, builder::{ meta::ownerreference_from_resource, pod::{ - container::{EnvVarName, new_container_builder}, + container::new_container_builder, volume::{ListenerReference, listener_operator_volume_source_builder_build_pvc}, }, }, @@ -71,11 +76,12 @@ constant!(DATA_VOLUME_NAME: VolumeName = "data"); constant!(LISTENER_VOLUME_NAME: PersistentVolumeClaimName = "listener"); const LISTENER_VOLUME_DIR: &str = "/stackable/listener"; +constant!(TLS_SERVER_VOLUME_NAME: VolumeName = "tls-server"); +constant!(TLS_INTERNAL_VOLUME_NAME: VolumeName = "tls-internal"); + constant!(LOG_VOLUME_NAME: VolumeName = "log"); const LOG_VOLUME_DIR: &str = "/stackable/log"; -const DEFAULT_OPENSEARCH_HOME: &str = "/stackable/opensearch"; - /// Builder for role-group resources pub struct RoleGroupBuilder<'a> { service_account_name: ServiceAccountName, @@ -127,7 +133,7 @@ impl<'a> RoleGroupBuilder<'a> { data.insert( CONFIGURATION_FILE_OPENSEARCH_YML.to_owned(), - self.node_config.static_opensearch_config_file_content(), + self.node_config.opensearch_config_file_content(), ); if let ValidatedContainerLogConfigChoice::Automatic(log_config) = @@ -213,6 +219,8 @@ impl<'a> RoleGroupBuilder<'a> { /// Builds the [`PodTemplateSpec`] for the role-group [`StatefulSet`] fn build_pod_template(&self) -> PodTemplateSpec { let mut node_role_labels = Labels::new(); + let service_scopes = vec![self.node_config.discovery_service_name.clone()]; + for node_role in self.role_group_config.config.node_roles.iter() { node_role_labels.insert(Self::build_node_role_label(node_role)); } @@ -257,7 +265,7 @@ impl<'a> RoleGroupBuilder<'a> { self.resource_names.role_group_config_map() }; - let volumes = vec![ + let mut volumes = vec![ Volume { name: CONFIG_VOLUME_NAME.to_string(), config_map: Some(ConfigMapVolumeSource { @@ -286,8 +294,27 @@ impl<'a> RoleGroupBuilder<'a> { }), ..Volume::default() }, + self.build_tls_volume( + &TLS_INTERNAL_VOLUME_NAME.to_string(), + &self.cluster.tls_config.internal_secret_class, + vec![], + SecretFormat::TlsPem, + &self.role_group_config.config.requested_secret_lifetime, + Some(&LISTENER_VOLUME_NAME.to_string()), + ), ]; + if let Some(tls_http_secret_class_name) = &self.cluster.tls_config.server_secret_class { + volumes.push(self.build_tls_volume( + &TLS_SERVER_VOLUME_NAME.to_string(), + tls_http_secret_class_name, + service_scopes, + SecretFormat::TlsPem, + &self.role_group_config.config.requested_secret_lifetime, + Some(&LISTENER_VOLUME_NAME.to_string()), + )) + }; + // The PodBuilder is not used because it re-validates the values which are already // validated. For instance, it would be necessary to convert the // termination_grace_period_seconds into a Duration, the PodBuilder parses the Duration, @@ -393,21 +420,10 @@ impl<'a> RoleGroupBuilder<'a> { ..Probe::default() }; - let env_vars = self.node_config.environment_variables(); - - // Use `OPENSEARCH_HOME` from envOverrides or default to `DEFAULT_OPENSEARCH_HOME`. - let opensearch_home = env_vars - .get(&EnvVarName::from_str_unsafe("OPENSEARCH_HOME")) - .and_then(|env_var| env_var.value.clone()) - .unwrap_or(DEFAULT_OPENSEARCH_HOME.to_owned()); - // Use `OPENSEARCH_PATH_CONF` from envOverrides or default to `OPENSEARCH_HOME/config`, - // i.e. depend on `OPENSEARCH_HOME`. - let opensearch_path_conf = env_vars - .get(&EnvVarName::from_str_unsafe("OPENSEARCH_PATH_CONF")) - .and_then(|env_var| env_var.value.clone()) - .unwrap_or(format!("{opensearch_home}/config")); - - let volume_mounts = [ + let opensearch_home = self.node_config.opensearch_home(); + let opensearch_path_conf = self.node_config.opensearch_path_conf(); + + let mut volume_mounts = vec![ VolumeMount { mount_path: format!("{opensearch_path_conf}/{CONFIGURATION_FILE_OPENSEARCH_YML}"), name: CONFIG_VOLUME_NAME.to_string(), @@ -439,8 +455,21 @@ impl<'a> RoleGroupBuilder<'a> { name: LOG_VOLUME_NAME.to_string(), ..VolumeMount::default() }, + VolumeMount { + mount_path: format!("{opensearch_path_conf}/tls/internal"), + name: TLS_INTERNAL_VOLUME_NAME.to_string(), + ..VolumeMount::default() + }, ]; + if self.cluster.tls_config.server_secret_class.is_some() { + volume_mounts.push(VolumeMount { + mount_path: format!("{opensearch_path_conf}/tls/server"), + name: TLS_SERVER_VOLUME_NAME.to_string(), + ..VolumeMount::default() + }) + } + new_container_builder(&v1alpha1::Container::OpenSearch.to_container_name()) .image_from_product_image(&self.cluster.image) .command(vec![ @@ -468,7 +497,7 @@ impl<'a> RoleGroupBuilder<'a> { create_vector_shutdown_file_command = create_vector_shutdown_file_command(STACKABLE_LOG_DIR), )]) - .add_env_vars(env_vars.into()) + .add_env_vars(self.node_config.environment_variables().into()) .add_volume_mounts(volume_mounts) .expect("The mount paths are statically defined and there should be no duplicates.") .add_container_ports(vec![ @@ -628,6 +657,37 @@ impl<'a> RoleGroupBuilder<'a> { &self.role_group_name, ) } + + fn build_tls_volume( + &self, + volume_name: &String, + tls_secret_class_name: &SecretClassName, + service_scopes: Vec, + secret_format: SecretFormat, + requested_secret_lifetime: &Duration, + listener_scope: Option<&str>, + ) -> Volume { + let mut secret_volume_source_builder = + SecretOperatorVolumeSourceBuilder::new(tls_secret_class_name); + + for scope in service_scopes { + secret_volume_source_builder.with_service_scope(scope); + } + if let Some(listener_scope) = listener_scope { + secret_volume_source_builder.with_listener_volume_scope(listener_scope); + } + + VolumeBuilder::new(volume_name) + .ephemeral( + secret_volume_source_builder + .with_pod_scope() + .with_format(secret_format) + .with_auto_tls_cert_lifetime(*requested_secret_lifetime) + .build() + .expect("volume should be built without parse errors"), + ) + .build() + } } #[cfg(test)] @@ -648,6 +708,7 @@ mod tests { kvp::LabelValue, product_logging::spec::AutomaticContainerLogConfig, role_utils::GenericRoleConfig, + shared::time::Duration, }; use strum::IntoEnumIterator; use uuid::uuid; @@ -661,7 +722,10 @@ mod tests { ContextNames, OpenSearchRoleGroupConfig, ValidatedCluster, ValidatedContainerLogConfigChoice, ValidatedLogging, ValidatedOpenSearchConfig, }, - crd::{NodeRoles, v1alpha1}, + crd::{ + NodeRoles, + v1alpha1::{self, OpenSearchTls}, + }, framework::{ ClusterName, ConfigMapName, ControllerName, ListenerClassName, NamespaceName, OperatorName, ProductName, ProductVersion, RoleGroupName, ServiceAccountName, @@ -723,6 +787,8 @@ mod tests { v1alpha1::NodeRole::Ingest, v1alpha1::NodeRole::RemoteClusterClient, ]), + requested_secret_lifetime: Duration::from_str("1d") + .expect("should be a valid duration"), resources: Resources::default(), termination_grace_period_seconds: 30, }, @@ -745,6 +811,7 @@ mod tests { role_group_config.clone(), )] .into(), + OpenSearchTls::default(), ) } @@ -1019,6 +1086,14 @@ mod tests { { "mountPath": "/stackable/log", "name": "log" + }, + { + "mountPath": "/stackable/opensearch/config/tls/internal", + "name": "tls-internal" + }, + { + "mountPath": "/stackable/opensearch/config/tls/server", + "name": "tls-server", } ] }, @@ -1145,7 +1220,59 @@ mod tests { "sizeLimit": "30Mi" }, "name": "log" - } + }, + { + "ephemeral": { + "volumeClaimTemplate": { + "metadata": { + "annotations": { + "secrets.stackable.tech/backend.autotls.cert.lifetime": "1d", + "secrets.stackable.tech/class": "tls", + "secrets.stackable.tech/format": "tls-pem", + "secrets.stackable.tech/scope": "listener-volume=listener,pod" + } + }, + "spec": { + "accessModes": [ + "ReadWriteOnce" + ], + "resources": { + "requests": { + "storage": "1" + } + }, + "storageClassName": "secrets.stackable.tech" + } + } + }, + "name": "tls-internal" + }, + { + "ephemeral": { + "volumeClaimTemplate": { + "metadata": { + "annotations": { + "secrets.stackable.tech/backend.autotls.cert.lifetime": "1d", + "secrets.stackable.tech/class": "tls", + "secrets.stackable.tech/format": "tls-pem", + "secrets.stackable.tech/scope": "service=my-opensearch-cluster,listener-volume=listener,pod" + } + }, + "spec": { + "accessModes": [ + "ReadWriteOnce" + ], + "resources": { + "requests": { + "storage": "1" + } + }, + "storageClassName": "secrets.stackable.tech" + } + } + }, + "name": "tls-server" + }, ] } }, @@ -1237,7 +1364,7 @@ mod tests { "annotations": { "prometheus.io/path": "/_prometheus/metrics", "prometheus.io/port": "9200", - "prometheus.io/scheme": "http", + "prometheus.io/scheme": "https", "prometheus.io/scrape": "true" }, "labels": { diff --git a/rust/operator-binary/src/controller/validate.rs b/rust/operator-binary/src/controller/validate.rs index c23ff48..ac7e542 100644 --- a/rust/operator-binary/src/controller/validate.rs +++ b/rust/operator-binary/src/controller/validate.rs @@ -140,6 +140,7 @@ pub fn validate( uid, cluster.spec.nodes.role_config.clone(), role_group_configs, + cluster.spec.cluster_config.tls.clone(), )) } @@ -183,6 +184,7 @@ fn validate_role_group_config( listener_class: merged_role_group.config.config.listener_class, logging, node_roles: merged_role_group.config.config.node_roles, + requested_secret_lifetime: merged_role_group.config.config.requested_secret_lifetime, resources: merged_role_group.config.config.resources, termination_grace_period_seconds, }; @@ -274,11 +276,11 @@ mod tests { controller::{ContextNames, ValidatedCluster, ValidatedLogging, ValidatedOpenSearchConfig}, crd::{ NodeRoles, - v1alpha1::{self}, + v1alpha1::{self, OpenSearchTls}, }, framework::{ ClusterName, ConfigMapName, ControllerName, ListenerClassName, NamespaceName, - OperatorName, ProductName, ProductVersion, RoleGroupName, + OperatorName, ProductName, ProductVersion, RoleGroupName, SecretClassName, builder::pod::container::{EnvVarName, EnvVarSet}, product_logging::framework::{ ValidatedContainerLogConfigChoice, VectorContainerLogConfig, @@ -407,6 +409,8 @@ mod tests { ] .into() ), + requested_secret_lifetime: Duration::from_str("1d") + .expect("should be a valid duration"), resources: Resources { memory: MemoryLimits { limit: Some(Quantity("2Gi".to_owned())), @@ -492,6 +496,10 @@ mod tests { } )] .into(), + OpenSearchTls { + server_secret_class: Some(SecretClassName::from_str_unsafe("tls")), + internal_secret_class: SecretClassName::from_str_unsafe("tls") + }, )), result.ok() ); @@ -669,6 +677,7 @@ mod tests { image: serde_json::from_str(r#"{"productVersion": "3.1.0"}"#) .expect("should be a valid ProductImage structure"), cluster_config: v1alpha1::OpenSearchClusterConfig { + tls: OpenSearchTls::default(), vector_aggregator_config_map_name: Some(ConfigMapName::from_str_unsafe( "vector-aggregator", )), diff --git a/rust/operator-binary/src/crd/mod.rs b/rust/operator-binary/src/crd/mod.rs index 4803e70..d931e91 100644 --- a/rust/operator-binary/src/crd/mod.rs +++ b/rust/operator-binary/src/crd/mod.rs @@ -30,11 +30,12 @@ use crate::{ constant, framework::{ ClusterName, ConfigMapName, ContainerName, ListenerClassName, NameIsValidLabelValue, - ProductName, RoleName, role_utils::GenericProductSpecificCommonConfig, + ProductName, RoleName, SecretClassName, role_utils::GenericProductSpecificCommonConfig, }, }; constant!(DEFAULT_LISTENER_CLASS: ListenerClassName = "cluster-internal"); +constant!(TLS_DEFAULT_SECRET_CLASS: SecretClassName = "tls"); #[versioned( version(name = "v1alpha1"), @@ -80,6 +81,9 @@ pub mod versioned { #[derive(Clone, Debug, Default, Deserialize, Eq, JsonSchema, PartialEq, Serialize)] #[serde(rename_all = "camelCase")] pub struct OpenSearchClusterConfig { + /// TLS configuration options for the server (REST API) and internal communication (transport). + #[serde(default)] + pub tls: OpenSearchTls, /// Name of the Vector aggregator [discovery ConfigMap](DOCS_BASE_URL_PLACEHOLDER/concepts/service_discovery). /// It must contain the key `ADDRESS` with the address of the Vector aggregator. /// Follow the [logging tutorial](DOCS_BASE_URL_PLACEHOLDER/tutorials/logging-vector-aggregator) @@ -88,6 +92,26 @@ pub mod versioned { pub vector_aggregator_config_map_name: Option, } + #[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)] + #[serde(rename_all = "camelCase")] + pub struct OpenSearchTls { + /// 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 + #[serde( + default = "server_secret_class_default", + skip_serializing_if = "Option::is_none" + )] + pub server_secret_class: Option, + /// 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 + #[serde(default = "internal_secret_class_default")] + pub internal_secret_class: SecretClassName, + } + // The possible node roles are by default the built-in roles and the search role, see // https://github.com/opensearch-project/OpenSearch/blob/3.0.0/server/src/main/java/org/opensearch/cluster/node/DiscoveryNode.java#L609-L614. // @@ -168,6 +192,13 @@ pub mod versioned { /// documentation](DOCS_BASE_URL_PLACEHOLDER/opensearch/usage-guide/node-roles) for details. pub node_roles: NodeRoles, + /// 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. + #[fragment_attrs(serde(default))] + pub requested_secret_lifetime: Duration, + #[fragment_attrs(serde(default))] pub resources: Resources, } @@ -270,6 +301,9 @@ impl v1alpha1::OpenSearchConfig { v1alpha1::NodeRole::Data, v1alpha1::NodeRole::RemoteClusterClient, ])), + requested_secret_lifetime: Some( + Duration::from_str("1d").expect("should be a valid duration"), + ), resources: ResourcesFragment { memory: MemoryLimitsFragment { // An idle node already requires 2 Gi. @@ -299,6 +333,23 @@ impl v1alpha1::OpenSearchConfig { } } +impl Default for v1alpha1::OpenSearchTls { + fn default() -> Self { + v1alpha1::OpenSearchTls { + server_secret_class: server_secret_class_default(), + internal_secret_class: internal_secret_class_default(), + } + } +} + +fn server_secret_class_default() -> Option { + Some(TLS_DEFAULT_SECRET_CLASS.to_owned()) +} + +fn internal_secret_class_default() -> SecretClassName { + TLS_DEFAULT_SECRET_CLASS.to_owned() +} + #[derive(Clone, Debug, Default, Deserialize, JsonSchema, PartialEq, Serialize)] pub struct NodeRoles(pub Vec); diff --git a/rust/operator-binary/src/framework.rs b/rust/operator-binary/src/framework.rs index 3442b2e..f4f3cbf 100644 --- a/rust/operator-binary/src/framework.rs +++ b/rust/operator-binary/src/framework.rs @@ -512,7 +512,14 @@ attributed_string_type! { is_rfc_1123_label_name, is_valid_label_value } - +attributed_string_type! { + SecretClassName, + "The TLS SecretClass name", + "tls", + // The secret class name is used in an annotation on the tls volume. + (max_length = RFC_1123_SUBDOMAIN_MAX_LENGTH), + is_rfc_1123_dns_subdomain_name +} #[cfg(test)] mod tests { use std::str::FromStr; diff --git a/tests/templates/kuttl/external-access/opensearch.yaml.j2 b/tests/templates/kuttl/external-access/opensearch.yaml.j2 index 05df6b6..d366985 100644 --- a/tests/templates/kuttl/external-access/opensearch.yaml.j2 +++ b/tests/templates/kuttl/external-access/opensearch.yaml.j2 @@ -11,7 +11,6 @@ spec: productVersion: "{{ test_scenario['values']['opensearch'].split(',')[0] }}" pullPolicy: IfNotPresent {% if lookup('env', 'VECTOR_AGGREGATOR') %} - clusterConfig: vectorAggregatorConfigMapName: vector-aggregator-discovery {% endif %} nodes: @@ -25,45 +24,18 @@ spec: - cluster_manager listenerClass: test-external-stable-$NAMESPACE replicas: 1 - podOverrides: - spec: - volumes: - - name: tls - ephemeral: - volumeClaimTemplate: - metadata: - annotations: - secrets.stackable.tech/scope: node,pod,service=opensearch,service=opensearch-nodes-cluster-manager-headless data1: config: nodeRoles: - data listenerClass: test-external-unstable-$NAMESPACE replicas: 1 - podOverrides: - spec: - volumes: - - name: tls - ephemeral: - volumeClaimTemplate: - metadata: - annotations: - secrets.stackable.tech/scope: node,pod,service=opensearch-nodes-data1-headless data2: config: nodeRoles: - data listenerClass: test-cluster-internal-$NAMESPACE replicas: 1 - podOverrides: - spec: - volumes: - - name: tls - ephemeral: - volumeClaimTemplate: - metadata: - annotations: - secrets.stackable.tech/scope: node,pod,service=opensearch-nodes-data2-headless envOverrides: # Only required for the official image # The official image (built with https://github.com/opensearch-project/opensearch-build) @@ -81,14 +53,6 @@ spec: # not be created even if enough disk space would be available. cluster.routing.allocation.disk.threshold_enabled: "false" plugins.security.allow_default_init_securityindex: "true" - plugins.security.ssl.transport.enabled: "true" - plugins.security.ssl.transport.pemcert_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.crt - plugins.security.ssl.transport.pemkey_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.key - plugins.security.ssl.transport.pemtrustedcas_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/ca.crt - plugins.security.ssl.http.enabled: "true" - plugins.security.ssl.http.pemcert_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.crt - plugins.security.ssl.http.pemkey_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.key - plugins.security.ssl.http.pemtrustedcas_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/ca.crt podOverrides: spec: containers: @@ -97,27 +61,11 @@ spec: - name: security-config mountPath: {{ test_scenario['values']['opensearch_home'] }}/config/opensearch-security readOnly: true - - name: tls - mountPath: {{ test_scenario['values']['opensearch_home'] }}/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 - spec: - storageClassName: secrets.stackable.tech - accessModes: - - ReadWriteOnce - resources: - requests: - storage: "1" --- apiVersion: v1 kind: Secret diff --git a/tests/templates/kuttl/ldap/20_opensearch-security-config.yaml.j2 b/tests/templates/kuttl/ldap/20_opensearch-security-config.yaml.j2 index 6ee2c86..2ee2485 100644 --- a/tests/templates/kuttl/ldap/20_opensearch-security-config.yaml.j2 +++ b/tests/templates/kuttl/ldap/20_opensearch-security-config.yaml.j2 @@ -58,7 +58,7 @@ stringData: enable_ssl: true hosts: - openldap.$NAMESPACE.svc.cluster.local:1636 - pemtrustedcas_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/ca.crt + pemtrustedcas_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/internal/ca.crt userbase: ou=users,dc=stackable,dc=tech username_attribute: uid usersearch: (cn={0}) @@ -73,7 +73,7 @@ stringData: enable_ssl: true hosts: - openldap.$NAMESPACE.svc.cluster.local:1636 - pemtrustedcas_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/ca.crt + pemtrustedcas_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/internal/ca.crt userbase: ou=users,dc=stackable,dc=tech username_attribute: uid usersearch: (cn={0}) diff --git a/tests/templates/kuttl/ldap/21-install-opensearch.yaml.j2 b/tests/templates/kuttl/ldap/21-install-opensearch.yaml.j2 index a98249b..8312285 100644 --- a/tests/templates/kuttl/ldap/21-install-opensearch.yaml.j2 +++ b/tests/templates/kuttl/ldap/21-install-opensearch.yaml.j2 @@ -48,14 +48,6 @@ spec: # not be created even if enough disk space would be available. cluster.routing.allocation.disk.threshold_enabled: "false" plugins.security.allow_default_init_securityindex: "true" - plugins.security.ssl.transport.enabled: "true" - plugins.security.ssl.transport.pemcert_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.crt - plugins.security.ssl.transport.pemkey_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.key - plugins.security.ssl.transport.pemtrustedcas_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/ca.crt - plugins.security.ssl.http.enabled: "true" - plugins.security.ssl.http.pemcert_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.crt - plugins.security.ssl.http.pemkey_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.key - plugins.security.ssl.http.pemtrustedcas_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/ca.crt podOverrides: spec: containers: @@ -64,25 +56,8 @@ spec: - name: security-config mountPath: {{ test_scenario['values']['opensearch_home'] }}/config/opensearch-security readOnly: true - - name: tls - mountPath: {{ test_scenario['values']['opensearch_home'] }}/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=opensearch,service=opensearch-nodes-default-headless - spec: - storageClassName: secrets.stackable.tech - accessModes: - - ReadWriteOnce - resources: - requests: - storage: "1" diff --git a/tests/templates/kuttl/logging/20-install-opensearch.yaml.j2 b/tests/templates/kuttl/logging/20-install-opensearch.yaml.j2 index 164f957..b2a0805 100644 --- a/tests/templates/kuttl/logging/20-install-opensearch.yaml.j2 +++ b/tests/templates/kuttl/logging/20-install-opensearch.yaml.j2 @@ -50,15 +50,6 @@ spec: ROOT: level: INFO replicas: 1 - podOverrides: - spec: - volumes: - - name: tls - ephemeral: - volumeClaimTemplate: - metadata: - annotations: - secrets.stackable.tech/scope: node,pod,service=opensearch,service=opensearch-nodes-automatic-headless custom: config: logging: @@ -68,15 +59,6 @@ spec: custom: configMap: custom-log-config replicas: 1 - podOverrides: - spec: - volumes: - - name: tls - ephemeral: - volumeClaimTemplate: - metadata: - annotations: - secrets.stackable.tech/scope: node,pod,service=opensearch,service=opensearch-nodes-custom-headless configOverrides: opensearch.yml: # Disable memory mapping in this test; If memory mapping were activated, the kernel setting @@ -88,14 +70,6 @@ spec: # not be created even if enough disk space would be available. cluster.routing.allocation.disk.threshold_enabled: "false" plugins.security.allow_default_init_securityindex: "true" - 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: @@ -104,26 +78,10 @@ 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 - - name: tls - ephemeral: - volumeClaimTemplate: - metadata: - annotations: - secrets.stackable.tech/class: tls - spec: - storageClassName: secrets.stackable.tech - accessModes: - - ReadWriteOnce - resources: - requests: - storage: "1" --- apiVersion: v1 kind: Secret diff --git a/tests/templates/kuttl/metrics/20-install-opensearch.yaml.j2 b/tests/templates/kuttl/metrics/20-install-opensearch.yaml.j2 index 1ccd35e..0ba6c91 100644 --- a/tests/templates/kuttl/metrics/20-install-opensearch.yaml.j2 +++ b/tests/templates/kuttl/metrics/20-install-opensearch.yaml.j2 @@ -10,8 +10,12 @@ spec: {% endif %} productVersion: "{{ test_scenario['values']['opensearch'].split(',')[0] }}" pullPolicy: IfNotPresent -{% if lookup('env', 'VECTOR_AGGREGATOR') %} clusterConfig: +{% if test_scenario['values']['server-use-tls'] == 'false' %} + tls: + serverSecretClass: null +{% endif %} +{% if lookup('env', 'VECTOR_AGGREGATOR') %} vectorAggregatorConfigMapName: vector-aggregator-discovery {% endif %} nodes: @@ -38,14 +42,6 @@ spec: # not be created even if enough disk space would be available. cluster.routing.allocation.disk.threshold_enabled: "false" plugins.security.allow_default_init_securityindex: "true" - 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: @@ -54,28 +50,11 @@ 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=opensearch,service=opensearch-nodes-default-headless - spec: - storageClassName: secrets.stackable.tech - accessModes: - - ReadWriteOnce - resources: - requests: - storage: "1" --- apiVersion: v1 kind: Secret diff --git a/tests/templates/kuttl/opensearch-dashboards/10-install-opensearch.yaml.j2 b/tests/templates/kuttl/opensearch-dashboards/10-install-opensearch.yaml.j2 index f0e99a0..106afd9 100644 --- a/tests/templates/kuttl/opensearch-dashboards/10-install-opensearch.yaml.j2 +++ b/tests/templates/kuttl/opensearch-dashboards/10-install-opensearch.yaml.j2 @@ -10,8 +10,12 @@ spec: {% endif %} productVersion: "{{ test_scenario['values']['opensearch'].split(',')[0] }}" pullPolicy: IfNotPresent -{% if lookup('env', 'VECTOR_AGGREGATOR') %} clusterConfig: +{% if test_scenario['values']['server-use-tls'] == 'false' %} + tls: + serverSecretClass: null +{% endif %} +{% if lookup('env', 'VECTOR_AGGREGATOR') %} vectorAggregatorConfigMapName: vector-aggregator-discovery {% endif %} nodes: @@ -23,15 +27,6 @@ spec: config: listenerClass: external-unstable replicas: 1 - podOverrides: - spec: - volumes: - - name: tls - ephemeral: - volumeClaimTemplate: - metadata: - annotations: - secrets.stackable.tech/scope: node,pod,service=opensearch,service=opensearch-nodes-default-headless envOverrides: # Only required for the official image # The official image (built with https://github.com/opensearch-project/opensearch-build) @@ -49,14 +44,6 @@ spec: # not be created even if enough disk space would be available. cluster.routing.allocation.disk.threshold_enabled: "false" plugins.security.allow_default_init_securityindex: "true" - plugins.security.ssl.transport.enabled: "true" - plugins.security.ssl.transport.pemcert_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.crt - plugins.security.ssl.transport.pemkey_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.key - plugins.security.ssl.transport.pemtrustedcas_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/ca.crt - plugins.security.ssl.http.enabled: "true" - plugins.security.ssl.http.pemcert_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.crt - plugins.security.ssl.http.pemkey_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.key - plugins.security.ssl.http.pemtrustedcas_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/ca.crt podOverrides: spec: containers: @@ -65,27 +52,11 @@ spec: - name: security-config mountPath: {{ test_scenario['values']['opensearch_home'] }}/config/opensearch-security readOnly: true - - name: tls - mountPath: {{ test_scenario['values']['opensearch_home'] }}/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 - spec: - storageClassName: secrets.stackable.tech - accessModes: - - ReadWriteOnce - resources: - requests: - storage: "1" --- apiVersion: v1 kind: Secret diff --git a/tests/templates/kuttl/opensearch-dashboards/20-install-opensearch-dashboards.yaml.j2 b/tests/templates/kuttl/opensearch-dashboards/20-install-opensearch-dashboards.yaml.j2 index 14dc539..fbd2371 100644 --- a/tests/templates/kuttl/opensearch-dashboards/20-install-opensearch-dashboards.yaml.j2 +++ b/tests/templates/kuttl/opensearch-dashboards/20-install-opensearch-dashboards.yaml.j2 @@ -7,7 +7,11 @@ commands: --repo https://opensearch-project.github.io/helm-charts --version "{{ test_scenario['values']['opensearch'].split(',')[0] }}" --values 20_opensearch-dashboards-values.yaml +{% if test_scenario['values']['server-use-tls'] == 'true' %} --set opensearchHosts=https://opensearch.$NAMESPACE.svc.cluster.local:9200 +{% else %} + --set opensearchHosts=http://opensearch.$NAMESPACE.svc.cluster.local:9200 +{% endif %} --namespace $NAMESPACE --wait timeout: 600 diff --git a/tests/templates/kuttl/opensearch-dashboards/20_opensearch-dashboards-values.yaml.j2 b/tests/templates/kuttl/opensearch-dashboards/20_opensearch-dashboards-values.yaml.j2 index 3ef67a3..a9ce088 100644 --- a/tests/templates/kuttl/opensearch-dashboards/20_opensearch-dashboards-values.yaml.j2 +++ b/tests/templates/kuttl/opensearch-dashboards/20_opensearch-dashboards-values.yaml.j2 @@ -30,6 +30,25 @@ extraEnvs: secretKeyRef: name: opensearch-credentials key: kibanaserver +config: + opensearch_dashboards.yml: + opensearch: + username: kibanaserver + requestHeadersWhitelist: + - authorization + - securitytenant +{% if test_scenario['values']['server-use-tls'] == 'true' %} + ssl: + verificationMode: full + certificateAuthorities: [/stackable/opensearch-dashboards/config/tls/ca.crt] +{% endif %} + opensearch_security: + multitenancy: + enabled: true + tenants.preferred: [Private, Global] + readonly_mode.roles: [kibana_read_only] + cookie.secure: false +{% if test_scenario['values']['server-use-tls'] == 'true' %} extraVolumes: - name: tls ephemeral: @@ -45,12 +64,16 @@ extraVolumes: resources: requests: storage: "1" +{% endif %} +# The Helm chart sets the volume "config" and adds a volume mount at +# /usr/share/opensearch-dashboards/config. But in the Stackable image, the configuration directory +# is located in /stackable/opensearch-dashboards/config. extraVolumeMounts: +{% if test_scenario['values']['server-use-tls'] == 'true' %} +# The same is true for the TLS volume. - mountPath: /stackable/opensearch-dashboards/config/tls name: tls - # The Helm chart sets the volume "config" and adds a volume mount at - # /usr/share/opensearch-dashboards/config. But in the Stackable image, the configuration directory - # is located in /stackable/opensearch-dashboards/config. +{% endif %} - mountPath: /stackable/opensearch-dashboards/config/opensearch_dashboards.yml name: config subPath: opensearch_dashboards.yml diff --git a/tests/templates/kuttl/smoke/10-assert.yaml.j2 b/tests/templates/kuttl/smoke/10-assert.yaml.j2 index 6979ac6..08a5a68 100644 --- a/tests/templates/kuttl/smoke/10-assert.yaml.j2 +++ b/tests/templates/kuttl/smoke/10-assert.yaml.j2 @@ -4,7 +4,7 @@ --- apiVersion: kuttl.dev/v1beta1 kind: TestAssert -timeout: 600 +timeout: 120 --- apiVersion: apps/v1 kind: StatefulSet @@ -169,12 +169,15 @@ spec: name: listener - mountPath: /stackable/log name: log + - mountPath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/internal + name: tls-internal +{% if test_scenario['values']['server-use-tls'] == 'true' %} + - mountPath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/server + name: tls-server +{% endif %} - mountPath: {{ test_scenario['values']['opensearch_home'] }}/config/opensearch-security name: security-config readOnly: true - - mountPath: {{ test_scenario['values']['opensearch_home'] }}/config/tls - name: tls - readOnly: true {% if lookup('env', 'VECTOR_AGGREGATOR') %} - args: - |- @@ -255,16 +258,12 @@ spec: - emptyDir: sizeLimit: 30Mi name: log - - name: security-config - secret: - defaultMode: 0o660 - secretName: opensearch-security-config - ephemeral: volumeClaimTemplate: metadata: annotations: secrets.stackable.tech/class: tls - secrets.stackable.tech/scope: node,pod,service=opensearch,service=opensearch-nodes-cluster-manager-headless + secrets.stackable.tech/scope: listener-volume=listener,pod spec: accessModes: - ReadWriteOnce @@ -273,7 +272,30 @@ spec: storage: "1" storageClassName: secrets.stackable.tech volumeMode: Filesystem - name: tls + name: tls-internal +{% if test_scenario['values']['server-use-tls'] == 'true' %} + - ephemeral: + volumeClaimTemplate: + metadata: + annotations: + secrets.stackable.tech/backend.autotls.cert.lifetime: 1d + secrets.stackable.tech/class: tls + secrets.stackable.tech/format: tls-pem + secrets.stackable.tech/scope: service=opensearch,listener-volume=listener,pod + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: "1" + storageClassName: secrets.stackable.tech + volumeMode: Filesystem + name: tls-server +{% endif %} + - name: security-config + secret: + defaultMode: 0o660 + secretName: opensearch-security-config volumeClaimTemplates: - apiVersion: v1 kind: PersistentVolumeClaim @@ -480,12 +502,15 @@ spec: name: listener - mountPath: /stackable/log name: log + - mountPath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/internal + name: tls-internal +{% if test_scenario['values']['server-use-tls'] == 'true' %} + - mountPath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/server + name: tls-server +{% endif %} - mountPath: {{ test_scenario['values']['opensearch_home'] }}/config/opensearch-security name: security-config readOnly: true - - mountPath: {{ test_scenario['values']['opensearch_home'] }}/config/tls - name: tls - readOnly: true {% if lookup('env', 'VECTOR_AGGREGATOR') %} - args: - |- @@ -566,16 +591,12 @@ spec: - emptyDir: sizeLimit: 30Mi name: log - - name: security-config - secret: - defaultMode: 0o660 - secretName: opensearch-security-config - ephemeral: volumeClaimTemplate: metadata: annotations: secrets.stackable.tech/class: tls - secrets.stackable.tech/scope: node,pod,service=opensearch-nodes-data-headless + secrets.stackable.tech/scope: listener-volume=listener,pod spec: accessModes: - ReadWriteOnce @@ -584,7 +605,30 @@ spec: storage: "1" storageClassName: secrets.stackable.tech volumeMode: Filesystem - name: tls + name: tls-internal +{% if test_scenario['values']['server-use-tls'] == 'true' %} + - ephemeral: + volumeClaimTemplate: + metadata: + annotations: + secrets.stackable.tech/backend.autotls.cert.lifetime: 1d + secrets.stackable.tech/class: tls + secrets.stackable.tech/format: tls-pem + secrets.stackable.tech/scope: service=opensearch,listener-volume=listener,pod + spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: "1" + storageClassName: secrets.stackable.tech + volumeMode: Filesystem + name: tls-server +{% endif %} + - name: security-config + secret: + defaultMode: 0o660 + secretName: opensearch-security-config volumeClaimTemplates: - apiVersion: v1 kind: PersistentVolumeClaim @@ -654,14 +698,18 @@ data: node.store.allow_mmap: "false" plugins.security.allow_default_init_securityindex: "true" plugins.security.nodes_dn: ["CN=generated certificate for pod"] +{% if test_scenario['values']['server-use-tls'] == 'true' %} plugins.security.ssl.http.enabled: "true" - plugins.security.ssl.http.pemcert_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.crt" - plugins.security.ssl.http.pemkey_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.key" - plugins.security.ssl.http.pemtrustedcas_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/ca.crt" + plugins.security.ssl.http.pemcert_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/server/tls.crt" + plugins.security.ssl.http.pemkey_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/server/tls.key" + plugins.security.ssl.http.pemtrustedcas_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/server/ca.crt" +{% else %} + plugins.security.ssl.http.enabled: "false" +{% endif %} plugins.security.ssl.transport.enabled: "true" - plugins.security.ssl.transport.pemcert_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.crt" - plugins.security.ssl.transport.pemkey_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.key" - plugins.security.ssl.transport.pemtrustedcas_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/ca.crt" + plugins.security.ssl.transport.pemcert_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/internal/tls.crt" + plugins.security.ssl.transport.pemkey_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/internal/tls.key" + plugins.security.ssl.transport.pemtrustedcas_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/internal/ca.crt" --- apiVersion: v1 kind: ConfigMap @@ -690,14 +738,18 @@ data: node.store.allow_mmap: "false" plugins.security.allow_default_init_securityindex: "true" plugins.security.nodes_dn: ["CN=generated certificate for pod"] +{% if test_scenario['values']['server-use-tls'] == 'true' %} plugins.security.ssl.http.enabled: "true" - plugins.security.ssl.http.pemcert_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.crt" - plugins.security.ssl.http.pemkey_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.key" - plugins.security.ssl.http.pemtrustedcas_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/ca.crt" + plugins.security.ssl.http.pemcert_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/server/tls.crt" + plugins.security.ssl.http.pemkey_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/server/tls.key" + plugins.security.ssl.http.pemtrustedcas_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/server/ca.crt" +{% else %} + plugins.security.ssl.http.enabled: "false" +{% endif %} plugins.security.ssl.transport.enabled: "true" - plugins.security.ssl.transport.pemcert_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.crt" - plugins.security.ssl.transport.pemkey_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.key" - plugins.security.ssl.transport.pemtrustedcas_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/ca.crt" + plugins.security.ssl.transport.pemcert_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/internal/tls.crt" + plugins.security.ssl.transport.pemkey_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/internal/tls.key" + plugins.security.ssl.transport.pemtrustedcas_filepath: "{{ test_scenario['values']['opensearch_home'] }}/config/tls/internal/ca.crt" --- apiVersion: v1 kind: Service diff --git a/tests/templates/kuttl/smoke/10-install-opensearch.yaml.j2 b/tests/templates/kuttl/smoke/10-install-opensearch.yaml.j2 index 47c203c..734bc07 100644 --- a/tests/templates/kuttl/smoke/10-install-opensearch.yaml.j2 +++ b/tests/templates/kuttl/smoke/10-install-opensearch.yaml.j2 @@ -10,8 +10,12 @@ spec: {% endif %} productVersion: "{{ test_scenario['values']['opensearch'].split(',')[0] }}" pullPolicy: IfNotPresent -{% if lookup('env', 'VECTOR_AGGREGATOR') %} clusterConfig: +{% if test_scenario['values']['server-use-tls'] == 'false' %} + tls: + serverSecretClass: null +{% endif %} +{% if lookup('env', 'VECTOR_AGGREGATOR') %} vectorAggregatorConfigMapName: vector-aggregator-discovery {% endif %} nodes: @@ -29,15 +33,6 @@ spec: capacity: 100Mi listenerClass: external-unstable replicas: 3 - podOverrides: - spec: - volumes: - - name: tls - ephemeral: - volumeClaimTemplate: - metadata: - annotations: - secrets.stackable.tech/scope: node,pod,service=opensearch,service=opensearch-nodes-cluster-manager-headless data: config: nodeRoles: @@ -50,15 +45,6 @@ spec: capacity: 2Gi listenerClass: cluster-internal replicas: 2 - podOverrides: - spec: - volumes: - - name: tls - ephemeral: - volumeClaimTemplate: - metadata: - annotations: - secrets.stackable.tech/scope: node,pod,service=opensearch-nodes-data-headless envOverrides: # Only required for the official image # The official image (built with https://github.com/opensearch-project/opensearch-build) @@ -76,14 +62,6 @@ spec: # not be created even if enough disk space would be available. cluster.routing.allocation.disk.threshold_enabled: "false" plugins.security.allow_default_init_securityindex: "true" - plugins.security.ssl.transport.enabled: "true" - plugins.security.ssl.transport.pemcert_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.crt - plugins.security.ssl.transport.pemkey_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.key - plugins.security.ssl.transport.pemtrustedcas_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/ca.crt - plugins.security.ssl.http.enabled: "true" - plugins.security.ssl.http.pemcert_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.crt - plugins.security.ssl.http.pemkey_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/tls.key - plugins.security.ssl.http.pemtrustedcas_filepath: {{ test_scenario['values']['opensearch_home'] }}/config/tls/ca.crt podOverrides: spec: containers: @@ -92,27 +70,11 @@ spec: - name: security-config mountPath: {{ test_scenario['values']['opensearch_home'] }}/config/opensearch-security readOnly: true - - name: tls - mountPath: {{ test_scenario['values']['opensearch_home'] }}/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 - spec: - storageClassName: secrets.stackable.tech - accessModes: - - ReadWriteOnce - resources: - requests: - storage: "1" --- apiVersion: v1 kind: Secret diff --git a/tests/templates/kuttl/smoke/20-test-opensearch.yaml b/tests/templates/kuttl/smoke/20-test-opensearch.yaml.j2 similarity index 95% rename from tests/templates/kuttl/smoke/20-test-opensearch.yaml rename to tests/templates/kuttl/smoke/20-test-opensearch.yaml.j2 index fcc3fcc..af78429 100644 --- a/tests/templates/kuttl/smoke/20-test-opensearch.yaml +++ b/tests/templates/kuttl/smoke/20-test-opensearch.yaml.j2 @@ -22,6 +22,8 @@ spec: # required for pip install - name: HOME value: /stackable + - name: HTTP_USE_TLS + value: "{{ test_scenario['values']['server-use-tls'] }}" - name: NAMESPACE valueFrom: fieldRef: @@ -78,6 +80,7 @@ data: from opensearchpy import OpenSearch namespace = os.environ['NAMESPACE'] + http_use_tls = os.environ['HTTP_USE_TLS'] == 'true' host = f'opensearch.{namespace}.svc.cluster.local' port = 9200 @@ -89,8 +92,8 @@ data: hosts = [{'host': host, 'port': port}], http_compress = True, # enables gzip compression for request bodies http_auth = auth, - use_ssl = True, - verify_certs = True, + use_ssl = http_use_tls, + verify_certs = http_use_tls, ca_certs = ca_certs_path ) diff --git a/tests/templates/kuttl/snapshot-s3/20-install-opensearch.yaml.j2 b/tests/templates/kuttl/snapshot-s3/20-install-opensearch.yaml.j2 index 2839ecb..b19bbf7 100644 --- a/tests/templates/kuttl/snapshot-s3/20-install-opensearch.yaml.j2 +++ b/tests/templates/kuttl/snapshot-s3/20-install-opensearch.yaml.j2 @@ -33,14 +33,6 @@ spec: # not be created even if enough disk space would be available. cluster.routing.allocation.disk.threshold_enabled: "false" plugins.security.allow_default_init_securityindex: "true" - 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 s3.client.default.endpoint: https://minio:9000/ s3.client.default.protocol: https s3.client.default.region: unused # but required @@ -106,9 +98,6 @@ spec: mountPath: /etc/pki/java/cacerts subPath: java/cacerts readOnly: true - - name: tls - mountPath: /stackable/opensearch/config/tls - readOnly: true - name: keystore mountPath: /stackable/opensearch/config/opensearch.keystore subPath: opensearch.keystore @@ -132,20 +121,6 @@ spec: - name: system-trust-store emptyDir: sizeLimit: 10Mi - - name: tls - ephemeral: - volumeClaimTemplate: - metadata: - annotations: - secrets.stackable.tech/scope: node,pod,service=opensearch,service=opensearch-nodes-default-headless - secrets.stackable.tech/class: tls - spec: - storageClassName: secrets.stackable.tech - accessModes: - - ReadWriteOnce - resources: - requests: - storage: "1" --- apiVersion: v1 kind: Secret diff --git a/tests/test-definition.yaml b/tests/test-definition.yaml index f224072..72f63e3 100644 --- a/tests/test-definition.yaml +++ b/tests/test-definition.yaml @@ -9,6 +9,10 @@ dimensions: - name: opensearch_home values: - /stackable/opensearch + - name: server-use-tls + values: + - "true" + - "false" # The release must sometimes be known in podOverrides or Helm values - name: release values: @@ -18,6 +22,7 @@ tests: dimensions: - opensearch - opensearch_home + - server-use-tls - name: external-access dimensions: - opensearch @@ -38,6 +43,7 @@ tests: dimensions: - opensearch - opensearch_home + - server-use-tls - release # requires the repository-s3 plugin - name: snapshot-s3