Skip to content

Commit 25745d1

Browse files
committed
wip: adress feedback on pr
1 parent 383e358 commit 25745d1

8 files changed

Lines changed: 121 additions & 78 deletions

File tree

deploy/helm/opensearch-operator/crds/crds.yaml

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,37 @@ spec:
3131
clusterConfig:
3232
default:
3333
tls:
34-
secretClass: null
34+
restSecretClass: tls
35+
transportSecretClass: tls
3536
description: Configuration that applies to all roles and role groups
3637
properties:
3738
tls:
39+
default:
40+
restSecretClass: tls
41+
transportSecretClass: tls
42+
description: TLS configuration options for the REST API and internal communication (transport).
3843
properties:
39-
secretClass:
44+
restSecretClass:
45+
default: tls
4046
description: |-
41-
Affects client connections and internal transport connections.
47+
Only affects client connections to the REST API.
4248
This setting controls:
4349
- If TLS encryption is used at all
4450
- Which cert the servers should use to authenticate themselves against the client
45-
maxLength: 223
51+
maxLength: 253
4652
minLength: 1
4753
nullable: true
4854
type: string
55+
transportSecretClass:
56+
default: tls
57+
description: |-
58+
Only affects internal communication (transport). Used for mutual verification between OpenSearch nodes.
59+
This setting controls:
60+
- Which cert the servers should use to authenticate themselves against other servers
61+
- Which ca.crt to use when validating the other server
62+
maxLength: 253
63+
minLength: 1
64+
type: string
4965
type: object
5066
vectorAggregatorConfigMapName:
5167
description: |-
@@ -57,8 +73,6 @@ spec:
5773
minLength: 1
5874
nullable: true
5975
type: string
60-
required:
61-
- tls
6276
type: object
6377
clusterOperation:
6478
default:

rust/operator-binary/src/controller/build/node_config.rs

Lines changed: 31 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ pub const CONFIG_OPTION_PLUGINS_SECURITY_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH: &
9797
pub struct NodeConfig {
9898
cluster: ValidatedCluster,
9999
role_group_config: OpenSearchRoleGroupConfig,
100-
discovery_service_name: ServiceName,
100+
pub discovery_service_name: ServiceName,
101101
}
102102

103103
// Most functions are public because their configuration values could also be used in environment
@@ -123,9 +123,7 @@ impl NodeConfig {
123123
pub fn opensearch_config(&self) -> serde_json::Map<String, Value> {
124124
let mut config = self.static_opensearch_config();
125125

126-
if self.cluster.cluster_config.tls.secret_class.is_some() {
127-
config.append(&mut self.tls_config());
128-
}
126+
config.append(&mut self.tls_config());
129127

130128
for (setting, value) in self
131129
.role_group_config
@@ -176,41 +174,49 @@ impl NodeConfig {
176174
pub fn tls_config(&self) -> serde_json::Map<String, Value> {
177175
let mut config = serde_json::Map::new();
178176

179-
// TLS config for HTTP port
180-
config.insert(
181-
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_ENABLED.to_owned(),
182-
json!("true".to_string()),
183-
);
184-
config.insert(
185-
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_PEMCERT_FILEPATH.to_owned(),
186-
json!("${OPENSEARCH_PATH_CONF}/tls/tls.crt".to_string()),
187-
);
188-
config.insert(
189-
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_PEMKEY_FILEPATH.to_owned(),
190-
json!("${OPENSEARCH_PATH_CONF}/tls/tls.key".to_string()),
191-
);
192-
config.insert(
193-
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH.to_owned(),
194-
json!("${OPENSEARCH_PATH_CONF}/tls/ca.crt".to_string()),
195-
);
196-
// TLS config for TRANSPORT port
177+
// TLS config for TRANSPORT port which is always enabled.
197178
config.insert(
198179
CONFIG_OPTION_PLUGINS_SECURITY_SSL_TRANSPORT_ENABLED.to_owned(),
199180
json!("true".to_string()),
200181
);
201182
config.insert(
202183
CONFIG_OPTION_PLUGINS_SECURITY_SSL_TRANSPORT_PEMCERT_FILEPATH.to_owned(),
203-
json!("${OPENSEARCH_PATH_CONF}/tls/tls.crt".to_string()),
184+
json!("${OPENSEARCH_PATH_CONF}/tls/transport/tls.crt".to_string()),
204185
);
205186
config.insert(
206187
CONFIG_OPTION_PLUGINS_SECURITY_SSL_TRANSPORT_PEMKEY_FILEPATH.to_owned(),
207-
json!("${OPENSEARCH_PATH_CONF}/tls/tls.key".to_string()),
188+
json!("${OPENSEARCH_PATH_CONF}/tls/transport/tls.key".to_string()),
208189
);
209190
config.insert(
210191
CONFIG_OPTION_PLUGINS_SECURITY_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH.to_owned(),
211-
json!("${OPENSEARCH_PATH_CONF}/tls/ca.crt".to_string()),
192+
json!("${OPENSEARCH_PATH_CONF}/tls/transport/ca.crt".to_string()),
212193
);
213194

195+
// TLS config for HTTP port which is optional.
196+
if self.cluster.cluster_config.tls.rest_secret_class.is_some() {
197+
config.insert(
198+
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_ENABLED.to_owned(),
199+
json!("true".to_string()),
200+
);
201+
config.insert(
202+
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_PEMCERT_FILEPATH.to_owned(),
203+
json!("${OPENSEARCH_PATH_CONF}/tls/rest/tls.crt".to_string()),
204+
);
205+
config.insert(
206+
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_PEMKEY_FILEPATH.to_owned(),
207+
json!("${OPENSEARCH_PATH_CONF}/tls/rest/tls.key".to_string()),
208+
);
209+
config.insert(
210+
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH.to_owned(),
211+
json!("${OPENSEARCH_PATH_CONF}/tls/rest/ca.crt".to_string()),
212+
);
213+
} else {
214+
config.insert(
215+
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_ENABLED.to_owned(),
216+
json!("false".to_string()),
217+
);
218+
}
219+
214220
config
215221
}
216222

rust/operator-binary/src/controller/build/role_group_builder.rs

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ constant!(DATA_VOLUME_NAME: VolumeName = "data");
7272
constant!(LISTENER_VOLUME_NAME: PersistentVolumeClaimName = "listener");
7373
const LISTENER_VOLUME_DIR: &str = "/stackable/listener";
7474

75-
constant!(TLS_VOLUME_NAME: VolumeName = "tls");
75+
constant!(TLS_REST_VOLUME_NAME: VolumeName = "tls-rest");
76+
constant!(TLS_TRANSPORT_VOLUME_NAME: VolumeName = "tls-transport");
7677

7778
constant!(LOG_VOLUME_NAME: VolumeName = "log");
7879
const LOG_VOLUME_DIR: &str = "/stackable/log";
@@ -215,10 +216,7 @@ impl<'a> RoleGroupBuilder<'a> {
215216
/// Builds the [`PodTemplateSpec`] for the role-group [`StatefulSet`]
216217
fn build_pod_template(&self) -> PodTemplateSpec {
217218
let mut node_role_labels = Labels::new();
218-
let service_scopes = vec![
219-
self.resource_names.cluster_name.to_string(),
220-
self.resource_names.headless_service_name().to_string(),
221-
];
219+
let service_scopes = vec![self.node_config.discovery_service_name.clone()];
222220

223221
for node_role in self.role_group_config.config.node_roles.iter() {
224222
node_role_labels.insert(Self::build_node_role_label(node_role));
@@ -293,12 +291,21 @@ impl<'a> RoleGroupBuilder<'a> {
293291
}),
294292
..Volume::default()
295293
},
294+
build_tls_volume(
295+
&TLS_TRANSPORT_VOLUME_NAME.to_string(),
296+
&self.cluster.cluster_config.tls.transport_secret_class,
297+
service_scopes.clone(),
298+
SecretFormat::TlsPem,
299+
&self.role_group_config.config.requested_secret_lifetime,
300+
Some(&LISTENER_VOLUME_NAME.to_string()),
301+
),
296302
];
297303

298-
if let Some(tls_secret_class_name) = &self.cluster.cluster_config.tls.secret_class {
304+
if let Some(tls_rest_secret_class_name) = &self.cluster.cluster_config.tls.rest_secret_class
305+
{
299306
volumes.push(build_tls_volume(
300-
&TLS_VOLUME_NAME.to_string(),
301-
tls_secret_class_name,
307+
&TLS_REST_VOLUME_NAME.to_string(),
308+
tls_rest_secret_class_name,
302309
service_scopes,
303310
SecretFormat::TlsPem,
304311
&self.role_group_config.config.requested_secret_lifetime,
@@ -457,12 +464,17 @@ impl<'a> RoleGroupBuilder<'a> {
457464
name: LOG_VOLUME_NAME.to_string(),
458465
..VolumeMount::default()
459466
},
467+
VolumeMount {
468+
mount_path: format!("{opensearch_path_conf}/tls/transport"),
469+
name: TLS_TRANSPORT_VOLUME_NAME.to_string(),
470+
..VolumeMount::default()
471+
},
460472
];
461473

462-
if self.cluster.cluster_config.tls.secret_class.is_some() {
474+
if self.cluster.cluster_config.tls.rest_secret_class.is_some() {
463475
volume_mounts.push(VolumeMount {
464-
mount_path: format!("{opensearch_path_conf}/tls"),
465-
name: TLS_VOLUME_NAME.to_string(),
476+
mount_path: format!("{opensearch_path_conf}/tls/rest"),
477+
name: TLS_REST_VOLUME_NAME.to_string(),
466478
..VolumeMount::default()
467479
})
468480
}

rust/operator-binary/src/controller/validate.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,6 @@ pub enum Error {
7474
source: crate::framework::product_logging::framework::Error,
7575
},
7676

77-
#[snafu(display("failed to set tls secret class"))]
78-
ParseTlsSecretClassName { source: crate::framework::Error },
79-
8077
#[snafu(display("fragment validation failure"))]
8178
ValidateOpenSearchConfig {
8279
source: stackable_operator::config::fragment::ValidationError,
@@ -282,7 +279,7 @@ mod tests {
282279
},
283280
framework::{
284281
ClusterName, ConfigMapName, ControllerName, ListenerClassName, NamespaceName,
285-
OperatorName, ProductName, ProductVersion, RoleGroupName, TlsSecretClassName,
282+
OperatorName, ProductName, ProductVersion, RoleGroupName, SecretClassName,
286283
builder::pod::container::{EnvVarName, EnvVarSet},
287284
product_logging::framework::{
288285
ValidatedContainerLogConfigChoice, VectorContainerLogConfig,
@@ -311,7 +308,8 @@ mod tests {
311308
uuid!("e6ac237d-a6d4-43a1-8135-f36506110912"),
312309
OpenSearchClusterConfig {
313310
tls: OpenSearchTls {
314-
secret_class: Some(TlsSecretClassName::from_str_unsafe("tls"))
311+
rest_secret_class: Some(SecretClassName::from_str_unsafe("tls")),
312+
transport_secret_class: SecretClassName::from_str_unsafe("tls")
315313
},
316314
vector_aggregator_config_map_name: Some(ConfigMapName::from_str_unsafe(
317315
"vector-aggregator"
@@ -678,7 +676,8 @@ mod tests {
678676
.expect("should be a valid ProductImage structure"),
679677
cluster_config: v1alpha1::OpenSearchClusterConfig {
680678
tls: OpenSearchTls {
681-
secret_class: Some(TlsSecretClassName::from_str_unsafe("tls")),
679+
rest_secret_class: Some(SecretClassName::from_str_unsafe("tls")),
680+
transport_secret_class: SecretClassName::from_str_unsafe("tls"),
682681
},
683682
vector_aggregator_config_map_name: Some(ConfigMapName::from_str_unsafe(
684683
"vector-aggregator",

rust/operator-binary/src/crd/mod.rs

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ use crate::{
3030
constant,
3131
framework::{
3232
ClusterName, ConfigMapName, ContainerName, ListenerClassName, NameIsValidLabelValue,
33-
ProductName, RoleName, TlsSecretClassName, role_utils::GenericProductSpecificCommonConfig,
33+
ProductName, RoleName, SecretClassName, role_utils::GenericProductSpecificCommonConfig,
3434
},
3535
};
3636

3737
constant!(DEFAULT_LISTENER_CLASS: ListenerClassName = "cluster-internal");
38+
constant!(TLS_DEFAULT_SECRET_CLASS: SecretClassName = "tls");
3839

3940
#[versioned(
4041
version(name = "v1alpha1"),
@@ -80,6 +81,8 @@ pub mod versioned {
8081
#[derive(Clone, Debug, Default, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
8182
#[serde(rename_all = "camelCase")]
8283
pub struct OpenSearchClusterConfig {
84+
/// TLS configuration options for the REST API and internal communication (transport).
85+
#[serde(default)]
8386
pub tls: OpenSearchTls,
8487
/// Name of the Vector aggregator [discovery ConfigMap](DOCS_BASE_URL_PLACEHOLDER/concepts/service_discovery).
8588
/// It must contain the key `ADDRESS` with the address of the Vector aggregator.
@@ -89,14 +92,24 @@ pub mod versioned {
8992
pub vector_aggregator_config_map_name: Option<ConfigMapName>,
9093
}
9194

92-
#[derive(Clone, Debug, Default, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
95+
#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
9396
#[serde(rename_all = "camelCase")]
9497
pub struct OpenSearchTls {
95-
/// Affects client connections and internal transport connections.
98+
/// Only affects client connections to the REST API.
9699
/// This setting controls:
97100
/// - If TLS encryption is used at all
98101
/// - Which cert the servers should use to authenticate themselves against the client
99-
pub secret_class: Option<TlsSecretClassName>,
102+
#[serde(
103+
default = "rest_secret_class_default",
104+
skip_serializing_if = "Option::is_none"
105+
)]
106+
pub rest_secret_class: Option<SecretClassName>,
107+
/// Only affects internal communication (transport). Used for mutual verification between OpenSearch nodes.
108+
/// This setting controls:
109+
/// - Which cert the servers should use to authenticate themselves against other servers
110+
/// - Which ca.crt to use when validating the other server
111+
#[serde(default = "transport_secret_class_default")]
112+
pub transport_secret_class: SecretClassName,
100113
}
101114

102115
// The possible node roles are by default the built-in roles and the search role, see
@@ -320,6 +333,23 @@ impl v1alpha1::OpenSearchConfig {
320333
}
321334
}
322335

336+
impl Default for v1alpha1::OpenSearchTls {
337+
fn default() -> Self {
338+
v1alpha1::OpenSearchTls {
339+
rest_secret_class: rest_secret_class_default(),
340+
transport_secret_class: transport_secret_class_default(),
341+
}
342+
}
343+
}
344+
345+
fn rest_secret_class_default() -> Option<SecretClassName> {
346+
Some(TLS_DEFAULT_SECRET_CLASS.to_owned())
347+
}
348+
349+
fn transport_secret_class_default() -> SecretClassName {
350+
TLS_DEFAULT_SECRET_CLASS.to_owned()
351+
}
352+
323353
#[derive(Clone, Debug, Default, Deserialize, JsonSchema, PartialEq, Serialize)]
324354
pub struct NodeRoles(pub Vec<v1alpha1::NodeRole>);
325355

rust/operator-binary/src/framework.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,6 @@ pub enum Error {
7979
/// Duplicates the private constant [`stackable-operator::kvp::label::value::LABEL_VALUE_MAX_LEN`]
8080
pub const MAX_LABEL_VALUE_LENGTH: usize = 63;
8181

82-
/// Maximum length of annotation values
83-
pub const MAX_ANNOTATION_LENGTH: usize = 253;
84-
8582
/// Has a non-empty name
8683
///
8784
/// Useful as an object reference; Should not be used to create an object because the name could
@@ -516,11 +513,12 @@ attributed_string_type! {
516513
is_valid_label_value
517514
}
518515
attributed_string_type! {
519-
TlsSecretClassName,
516+
SecretClassName,
520517
"The TLS SecretClass name",
521518
"tls",
522-
// The secret class name is used in an annotation on the tls volume. To make sure the
523-
(max_length = MAX_ANNOTATION_LENGTH - 30)
519+
// The secret class name is used in an annotation on the tls volume.
520+
(max_length = RFC_1123_SUBDOMAIN_MAX_LENGTH),
521+
is_rfc_1123_dns_subdomain_name
524522
}
525523
#[cfg(test)]
526524
mod tests {

rust/operator-binary/src/framework/builder/volume.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@ use stackable_operator::{
44
shared::time::Duration,
55
};
66

7-
use crate::framework::TlsSecretClassName;
7+
use crate::framework::{SecretClassName, ServiceName};
88

99
pub fn build_tls_volume(
1010
volume_name: &String,
11-
tls_secret_class_name: &TlsSecretClassName,
12-
service_scopes: impl IntoIterator<Item = impl AsRef<str>>,
11+
tls_secret_class_name: &SecretClassName,
12+
service_scopes: Vec<ServiceName>,
1313
secret_format: SecretFormat,
1414
requested_secret_lifetime: &Duration,
1515
listener_scope: Option<&str>,
@@ -18,7 +18,7 @@ pub fn build_tls_volume(
1818
SecretOperatorVolumeSourceBuilder::new(tls_secret_class_name);
1919

2020
for scope in service_scopes {
21-
secret_volume_source_builder.with_service_scope(scope.as_ref());
21+
secret_volume_source_builder.with_service_scope(scope);
2222
}
2323
if let Some(listener_scope) = listener_scope {
2424
secret_volume_source_builder.with_listener_volume_scope(listener_scope);

0 commit comments

Comments
 (0)