Skip to content

Commit d502af3

Browse files
committed
WIP implementation opa-role-mapping
1 parent ba1c7ab commit d502af3

File tree

4 files changed

+69
-5
lines changed

4 files changed

+69
-5
lines changed

rust/crd/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,9 @@ pub enum SupersetConfigOptions {
8686
AuthLdapTlsCertfile,
8787
AuthLdapTlsKeyfile,
8888
AuthLdapTlsCacertfile,
89+
CustomSecurityManager,
90+
StackableOpaEndpoint,
91+
OpaPackageName,
8992
}
9093

9194
impl SupersetConfigOptions {
@@ -133,6 +136,10 @@ impl FlaskAppConfigOptions for SupersetConfigOptions {
133136
SupersetConfigOptions::AuthLdapTlsCertfile => PythonType::StringLiteral,
134137
SupersetConfigOptions::AuthLdapTlsKeyfile => PythonType::StringLiteral,
135138
SupersetConfigOptions::AuthLdapTlsCacertfile => PythonType::StringLiteral,
139+
SupersetConfigOptions::CustomSecurityManager => PythonType::StringLiteral,
140+
SupersetConfigOptions::StackableOpaEndpoint => PythonType::StringLiteral,
141+
SupersetConfigOptions::OpaPackageName => PythonType::StringLiteral,
142+
// TODO: Set new options for OpaSecurityManager like:
136143
}
137144
}
138145
}
Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1+
use std::collections::BTreeMap;
2+
13
use stackable_operator::{
24
client::Client,
35
commons::opa::{OpaApiVersion, OpaConfig},
46
};
57
use stackable_superset_crd::SupersetCluster;
68

79
pub struct SupersetOpaConfig {
8-
opa_role_mapping: bool,
10+
opa_endpoint: String,
11+
opa_package: Option<String>,
912
}
1013

1114
impl SupersetOpaConfig {
@@ -14,8 +17,44 @@ impl SupersetOpaConfig {
1417
superset: &SupersetCluster,
1518
opa_config: &OpaConfig,
1619
) -> Result<Self, stackable_operator::commons::opa::Error> {
20+
// Get opa_base_url for later use in CustomOpaSecurityManager
21+
let opa_endpoint = opa_config
22+
.full_document_url_from_config_map(client, superset, None, OpaApiVersion::V1)
23+
.await?;
24+
25+
let opa_package = opa_config.package.clone();
1726
Ok(SupersetOpaConfig {
18-
opa_role_mapping: true,
27+
opa_endpoint,
28+
opa_package,
1929
})
2030
}
31+
32+
// Adding necessary configurations. Imports are solved in config.rs
33+
pub fn as_config(&self) -> BTreeMap<String, Option<String>> {
34+
let config = BTreeMap::from([
35+
(
36+
"CUSTOM_SECURITY_MANAGER".to_string(),
37+
Some("OpaSupersetSecurityManager".to_string()),
38+
),
39+
(
40+
"AUTH_USER_REGISTRATION_ROLE".to_string(),
41+
Some("os.getenv('AUTH_USER_REGISTRATION_ROLE', 'Public')".to_string()),
42+
),
43+
// TODO: Figure out how to tell a what are the
44+
// rule names used.
45+
(
46+
"STACKABLE_OPA_RULE".to_string(),
47+
Some("os.getenv('STACKABLE_OPA_RULE', 'user_roles')".to_string()),
48+
),
49+
(
50+
"STACKABLE_OPA_ENDPOINT".to_string(),
51+
Some(self.opa_endpoint.clone()),
52+
),
53+
(
54+
"STACKABLE_OPA_PACKAGE".to_string(),
55+
self.opa_package.clone(),
56+
),
57+
]);
58+
config
59+
}
2160
}

rust/operator-binary/src/config.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ pub const PYTHON_IMPORTS: &[&str] = &[
3535
"from log_config import StackableLoggingConfigurator",
3636
];
3737

38+
// TODO: Eihter use or remove this
39+
pub const OPA_IMPORTS: &[&str] =
40+
&["from superset.security.manager import OpaSupersetSecurityManager"];
41+
3842
pub fn add_superset_config(
3943
config: &mut BTreeMap<String, String>,
4044
authentication_config: &SupersetClientAuthenticationDetailsResolved,

rust/operator-binary/src/superset_controller.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ use strum::{EnumDiscriminants, IntoStaticStr};
7777
use crate::{
7878
authorization::opa::SupersetOpaConfig,
7979
commands::add_cert_to_python_certifi_command,
80-
config::{self, PYTHON_IMPORTS},
80+
config::{self, OPA_IMPORTS, PYTHON_IMPORTS},
8181
controller_commons::{self, CONFIG_VOLUME_NAME, LOG_CONFIG_VOLUME_NAME, LOG_VOLUME_NAME},
8282
operations::{graceful_shutdown::add_graceful_shutdown_config, pdb::add_pdbs},
8383
product_logging::{
@@ -426,6 +426,7 @@ pub async fn reconcile_superset(
426426
&rolegroup,
427427
rolegroup_config,
428428
&auth_config,
429+
&superset_opa_config,
429430
&config.logging,
430431
vector_aggregator_address.as_deref(),
431432
)?;
@@ -553,11 +554,12 @@ fn build_rolegroup_config_map(
553554
rolegroup: &RoleGroupRef<SupersetCluster>,
554555
rolegroup_config: &HashMap<PropertyNameKind, BTreeMap<String, String>>,
555556
authentication_config: &SupersetClientAuthenticationDetailsResolved,
557+
superset_opa_config: &Option<SupersetOpaConfig>,
556558
logging: &Logging<Container>,
557559
vector_aggregator_address: Option<&str>,
558560
) -> Result<ConfigMap, Error> {
559561
let mut config_properties = BTreeMap::new();
560-
562+
let imports = PYTHON_IMPORTS;
561563
// TODO: this is true per default for versions 3.0.0 and up.
562564
// We deactivate it here to keep existing functionality.
563565
// However this is a security issue and should be configured properly
@@ -567,6 +569,18 @@ fn build_rolegroup_config_map(
567569
config::add_superset_config(&mut config_properties, authentication_config)
568570
.context(AddSupersetConfigSnafu)?;
569571

572+
// Adding opa configuration properties to config_properties.
573+
// This will be injected as key/value pair in superset_config.py
574+
if let Some(opa_config) = superset_opa_config {
575+
for (k, v) in opa_config.as_config() {
576+
config_properties.insert(k, v.unwrap_or_default());
577+
}
578+
// If opa role mapping is configured, insert CustomOpaSecurityManager import
579+
for opa_import in OPA_IMPORTS {
580+
imports.to_vec().push(&opa_import);
581+
}
582+
}
583+
570584
// The order here should be kept in order to preserve overrides.
571585
// No properties should be added after this extend.
572586
config_properties.extend(
@@ -590,7 +604,7 @@ fn build_rolegroup_config_map(
590604
flask_app_config_writer::write::<SupersetConfigOptions, _, _>(
591605
&mut config_file,
592606
config_properties.iter(),
593-
PYTHON_IMPORTS,
607+
imports,
594608
)
595609
.with_context(|_| BuildRoleGroupConfigFileSnafu {
596610
rolegroup: rolegroup.clone(),

0 commit comments

Comments
 (0)