Skip to content

Commit ee78b3f

Browse files
Rework RoleGroupSecurityMode
1 parent 6e0c459 commit ee78b3f

6 files changed

Lines changed: 334 additions & 198 deletions

File tree

rust/operator-binary/src/controller.rs

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use crate::{
3939
role_utils::{GenericProductSpecificCommonConfig, RoleGroupConfig},
4040
types::{
4141
common::Port,
42-
kubernetes::{Hostname, ListenerClassName, NamespaceName, Uid},
42+
kubernetes::{Hostname, ListenerClassName, NamespaceName, SecretClassName, Uid},
4343
operator::{
4444
ClusterName, ControllerName, OperatorName, ProductName, ProductVersion,
4545
RoleGroupName, RoleName,
@@ -181,11 +181,23 @@ impl ValidatedLogging {
181181
}
182182
}
183183

184+
/// Validated security configuration
184185
#[derive(Clone, Debug, PartialEq)]
185-
pub struct ValidatedSecurity {
186-
pub managing_role_group: Option<RoleGroupName>,
187-
pub settings: v1alpha1::SecurityConfig,
188-
pub tls: v1alpha1::OpenSearchTls,
186+
pub enum ValidatedSecurity {
187+
/// At least one security setting is managed by the operator
188+
ManagedByOperator {
189+
managing_role_group: RoleGroupName,
190+
settings: v1alpha1::SecurityConfig,
191+
tls_server_secret_class: SecretClassName,
192+
tls_internal_secret_class: SecretClassName,
193+
},
194+
195+
/// All security settings are managed by the API
196+
ManagedByApi {
197+
settings: v1alpha1::SecurityConfig,
198+
tls_server_secret_class: Option<SecretClassName>,
199+
tls_internal_secret_class: SecretClassName,
200+
},
189201
}
190202

191203
#[derive(Clone, Debug, PartialEq)]
@@ -284,10 +296,16 @@ impl ValidatedCluster {
284296

285297
/// Whether security is enabled and a server TLS class is defined or not.
286298
pub fn is_server_tls_enabled(&self) -> bool {
287-
self.security
288-
.as_ref()
289-
.and_then(|security| security.tls.server_secret_class.as_ref())
290-
.is_some()
299+
matches!(
300+
self.security,
301+
Some(ValidatedSecurity::ManagedByApi {
302+
tls_server_secret_class: Some(_),
303+
..
304+
}) | Some(ValidatedSecurity::ManagedByOperator {
305+
tls_server_secret_class: _,
306+
..
307+
})
308+
)
291309
}
292310
}
293311

@@ -459,7 +477,7 @@ mod tests {
459477
product_logging::framework::ValidatedContainerLogConfigChoice,
460478
role_utils::GenericProductSpecificCommonConfig,
461479
types::{
462-
kubernetes::{ListenerClassName, NamespaceName},
480+
kubernetes::{ListenerClassName, NamespaceName, SecretClassName},
463481
operator::{ClusterName, OperatorName, ProductVersion, RoleGroupName},
464482
},
465483
},
@@ -575,10 +593,10 @@ mod tests {
575593
),
576594
]
577595
.into(),
578-
Some(ValidatedSecurity {
579-
managing_role_group: None,
596+
Some(ValidatedSecurity::ManagedByApi {
580597
settings: v1alpha1::SecurityConfig::default(),
581-
tls: v1alpha1::OpenSearchTls::default(),
598+
tls_server_secret_class: None,
599+
tls_internal_secret_class: SecretClassName::from_str_unsafe("tls"),
582600
}),
583601
vec![],
584602
None,

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

Lines changed: 88 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use tracing::warn;
88

99
use super::ValidatedCluster;
1010
use crate::{
11-
controller::OpenSearchRoleGroupConfig,
11+
controller::{OpenSearchRoleGroupConfig, build::role_group_builder::RoleGroupSecurityMode},
1212
crd::v1alpha1,
1313
framework::{
1414
builder::pod::container::{EnvVarName, EnvVarSet},
@@ -140,6 +140,7 @@ pub struct NodeConfig {
140140
cluster: ValidatedCluster,
141141
role_group_name: RoleGroupName,
142142
role_group_config: OpenSearchRoleGroupConfig,
143+
role_group_security_mode: RoleGroupSecurityMode,
143144
pub seed_nodes_service_name: ServiceName,
144145
cluster_domain_name: DomainName,
145146
headless_service_name: ServiceName,
@@ -152,6 +153,7 @@ impl NodeConfig {
152153
cluster: ValidatedCluster,
153154
role_group_name: RoleGroupName,
154155
role_group_config: OpenSearchRoleGroupConfig,
156+
role_group_security_mode: RoleGroupSecurityMode,
155157
seed_nodes_service_name: ServiceName,
156158
cluster_domain_name: DomainName,
157159
headless_service_name: ServiceName,
@@ -160,6 +162,7 @@ impl NodeConfig {
160162
cluster,
161163
role_group_name,
162164
role_group_config,
165+
role_group_security_mode,
163166
seed_nodes_service_name,
164167
cluster_domain_name,
165168
headless_service_name,
@@ -217,10 +220,6 @@ impl NodeConfig {
217220
CONFIG_OPTION_DISCOVERY_TYPE.to_owned(),
218221
json!(self.discovery_type()),
219222
);
220-
config.insert(
221-
CONFIG_OPTION_PLUGINS_SECURITY_DISABLED.to_owned(),
222-
json!(self.cluster.security.is_none()),
223-
);
224223
config.insert
225224
// Accept certificates generated by the secret-operator
226225
(
@@ -239,18 +238,27 @@ impl NodeConfig {
239238
)),
240239
);
241240

242-
if let Some(security) = &self.cluster.security {
243-
config.insert(
244-
CONFIG_OPTION_PLUGINS_SECURITY_ALLOW_DEFAULT_INIT_SECURITYINDEX.to_owned(),
245-
json!(security.settings.is_only_managed_by_api()),
246-
);
247-
if !security.settings.is_only_managed_by_api() {
241+
match self.role_group_security_mode {
242+
RoleGroupSecurityMode::Initializing { .. } => {
243+
config.insert(
244+
CONFIG_OPTION_PLUGINS_SECURITY_ALLOW_DEFAULT_INIT_SECURITYINDEX.to_owned(),
245+
json!(true),
246+
);
247+
}
248+
RoleGroupSecurityMode::Managing { .. }
249+
| RoleGroupSecurityMode::Participating { .. } => {
248250
config.insert(
249251
CONFIG_OPTION_PLUGINS_SECURITY_AUTHCZ_ADMIN_DN.to_owned(),
250252
json!(self.super_admin_dn()),
251253
);
252254
}
253-
}
255+
RoleGroupSecurityMode::Disabled => {
256+
config.insert(
257+
CONFIG_OPTION_PLUGINS_SECURITY_DISABLED.to_owned(),
258+
json!(true),
259+
);
260+
}
261+
};
254262

255263
config
256264
}
@@ -264,9 +272,13 @@ impl NodeConfig {
264272
pub fn tls_config(&self) -> serde_json::Map<String, Value> {
265273
let mut config = serde_json::Map::new();
266274

267-
if let Some(security) = &self.cluster.security {
268-
let opensearch_path_conf = self.opensearch_path_conf();
275+
let opensearch_path_conf = self.opensearch_path_conf();
269276

277+
if self
278+
.role_group_security_mode
279+
.tls_internal_secret_class()
280+
.is_some()
281+
{
270282
// TLS config for TRANSPORT port which is always enabled.
271283
config.insert(
272284
CONFIG_OPTION_PLUGINS_SECURITY_SSL_TRANSPORT_ENABLED.to_owned(),
@@ -284,31 +296,34 @@ impl NodeConfig {
284296
CONFIG_OPTION_PLUGINS_SECURITY_SSL_TRANSPORT_PEMTRUSTEDCAS_FILEPATH.to_owned(),
285297
json!(format!("{opensearch_path_conf}/tls/internal/ca.crt")),
286298
);
299+
}
287300

288-
// TLS config for HTTP port (REST API) (optional).
289-
if security.tls.server_secret_class.is_some() {
290-
config.insert(
291-
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_ENABLED.to_owned(),
292-
json!(true),
293-
);
294-
config.insert(
295-
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_PEMCERT_FILEPATH.to_owned(),
296-
json!(format!("{opensearch_path_conf}/tls/server/tls.crt")),
297-
);
298-
config.insert(
299-
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_PEMKEY_FILEPATH.to_owned(),
300-
json!(format!("{opensearch_path_conf}/tls/server/tls.key")),
301-
);
302-
config.insert(
303-
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH.to_owned(),
304-
json!(format!("{opensearch_path_conf}/tls/server/ca.crt")),
305-
);
306-
} else {
307-
config.insert(
308-
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_ENABLED.to_owned(),
309-
json!(false),
310-
);
311-
}
301+
if self
302+
.role_group_security_mode
303+
.tls_server_secret_class()
304+
.is_some()
305+
{
306+
config.insert(
307+
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_ENABLED.to_owned(),
308+
json!(true),
309+
);
310+
config.insert(
311+
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_PEMCERT_FILEPATH.to_owned(),
312+
json!(format!("{opensearch_path_conf}/tls/server/tls.crt")),
313+
);
314+
config.insert(
315+
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_PEMKEY_FILEPATH.to_owned(),
316+
json!(format!("{opensearch_path_conf}/tls/server/tls.key")),
317+
);
318+
config.insert(
319+
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_PEMTRUSTEDCAS_FILEPATH.to_owned(),
320+
json!(format!("{opensearch_path_conf}/tls/server/ca.crt")),
321+
);
322+
} else {
323+
config.insert(
324+
CONFIG_OPTION_PLUGINS_SECURITY_SSL_HTTP_ENABLED.to_owned(),
325+
json!(false),
326+
);
312327
}
313328

314329
config
@@ -536,7 +551,9 @@ mod tests {
536551
product_logging::framework::ValidatedContainerLogConfigChoice,
537552
role_utils::GenericProductSpecificCommonConfig,
538553
types::{
539-
kubernetes::{ConfigMapKey, ConfigMapName, ListenerClassName, NamespaceName},
554+
kubernetes::{
555+
ConfigMapKey, ConfigMapName, ListenerClassName, NamespaceName, SecretClassName,
556+
},
540557
operator::{ClusterName, ProductVersion, RoleGroupName},
541558
},
542559
},
@@ -607,6 +624,30 @@ mod tests {
607624
product_specific_common_config: GenericProductSpecificCommonConfig::default(),
608625
};
609626

627+
let security_settings = v1alpha1::SecurityConfig {
628+
config: v1alpha1::SecurityConfigFileType {
629+
managed_by: v1alpha1::SecurityConfigFileTypeManagedBy::Operator,
630+
content: v1alpha1::SecurityConfigFileTypeContent::ValueFrom(
631+
v1alpha1::SecurityConfigFileTypeContentValueFrom::ConfigMapKeyRef(
632+
v1alpha1::ConfigMapKeyRef {
633+
name: ConfigMapName::from_str_unsafe("security-config"),
634+
key: ConfigMapKey::from_str_unsafe("config.yml"),
635+
},
636+
),
637+
),
638+
},
639+
..v1alpha1::SecurityConfig::default()
640+
};
641+
let tls_server_secret_class = SecretClassName::from_str_unsafe("tls");
642+
let tls_internal_secret_class = SecretClassName::from_str_unsafe("tls");
643+
644+
let validated_security = ValidatedSecurity::ManagedByOperator {
645+
managing_role_group: role_group_name.clone(),
646+
settings: security_settings.clone(),
647+
tls_server_secret_class: tls_server_secret_class.clone(),
648+
tls_internal_secret_class: tls_internal_secret_class.clone(),
649+
};
650+
610651
let cluster = ValidatedCluster::new(
611652
ResolvedProductImage {
612653
product_version: "3.4.0".to_owned(),
@@ -626,32 +667,22 @@ mod tests {
626667
role_group_config.clone(),
627668
)]
628669
.into(),
629-
Some(ValidatedSecurity {
630-
managing_role_group: Some(RoleGroupName::from_str_unsafe("default")),
631-
settings: v1alpha1::SecurityConfig {
632-
config: v1alpha1::SecurityConfigFileType {
633-
managed_by: v1alpha1::SecurityConfigFileTypeManagedBy::Operator,
634-
content: v1alpha1::SecurityConfigFileTypeContent::ValueFrom(
635-
v1alpha1::SecurityConfigFileTypeContentValueFrom::ConfigMapKeyRef(
636-
v1alpha1::ConfigMapKeyRef {
637-
name: ConfigMapName::from_str_unsafe("security-config"),
638-
key: ConfigMapKey::from_str_unsafe("config.yml"),
639-
},
640-
),
641-
),
642-
},
643-
..v1alpha1::SecurityConfig::default()
644-
},
645-
tls: v1alpha1::OpenSearchTls::default(),
646-
}),
670+
Some(validated_security),
647671
vec![],
648672
None,
649673
);
650674

675+
let role_group_security_config = RoleGroupSecurityMode::Managing {
676+
settings: security_settings.clone(),
677+
tls_server_secret_class: tls_server_secret_class.clone(),
678+
tls_internal_secret_class: tls_internal_secret_class.clone(),
679+
};
680+
651681
NodeConfig::new(
652682
cluster,
653683
role_group_name,
654684
role_group_config,
685+
role_group_security_config,
655686
ServiceName::from_str_unsafe("my-opensearch-seed-nodes"),
656687
DomainName::from_str("cluster.local").expect("should be a valid domain name"),
657688
ServiceName::from_str_unsafe("my-opensearch-cluster-default-headless"),
@@ -672,9 +703,7 @@ mod tests {
672703
"network.host: \"0.0.0.0\"\n",
673704
"node.attr.role-group: \"data\"\n",
674705
"path.logs: \"/stackable/log/opensearch\"\n",
675-
"plugins.security.allow_default_init_securityindex: false\n",
676706
"plugins.security.authcz.admin_dn: \"CN=update-security-config.0b1e30e6-326e-4c1a-868d-ad6598b49e8b\"\n",
677-
"plugins.security.disabled: false\n",
678707
"plugins.security.nodes_dn: [\"CN=generated certificate for pod\"]\n",
679708
"plugins.security.ssl.http.enabled: true\n",
680709
"plugins.security.ssl.http.pemcert_filepath: \"/stackable/opensearch/config/tls/server/tls.crt\"\n",

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@ mod tests {
349349
common::Port,
350350
kubernetes::{
351351
ConfigMapName, Hostname, ListenerClassName, ListenerName, NamespaceName,
352-
ServiceName,
352+
SecretClassName, ServiceName,
353353
},
354354
operator::{
355355
ClusterName, ControllerName, OperatorName, ProductName, ProductVersion,
@@ -427,10 +427,10 @@ mod tests {
427427
role_group_config.clone(),
428428
)]
429429
.into(),
430-
Some(ValidatedSecurity {
431-
managing_role_group: None,
430+
Some(ValidatedSecurity::ManagedByApi {
432431
settings: v1alpha1::SecurityConfig::default(),
433-
tls: v1alpha1::OpenSearchTls::default(),
432+
tls_server_secret_class: Some(SecretClassName::from_str_unsafe("tls")),
433+
tls_internal_secret_class: SecretClassName::from_str_unsafe("tls"),
434434
}),
435435
vec![],
436436
Some(ValidatedDiscoveryEndpoint {

0 commit comments

Comments
 (0)