Skip to content

Commit 2767a27

Browse files
committed
feat: OPA TLS support
1 parent a633d6f commit 2767a27

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

rust/operator-binary/src/authorization/opa.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use std::collections::BTreeMap;
33
use stackable_operator::{
44
client::Client,
55
commons::opa::{OpaApiVersion, OpaConfig},
6+
k8s_openapi::api::core::v1::ConfigMap,
7+
kube::ResourceExt,
68
};
79

810
use crate::crd::v1alpha1::TrinoCluster;
@@ -28,6 +30,10 @@ pub struct TrinoOpaConfig {
2830
/// such operations, they will be bulk allowed or denied depending
2931
/// on this setting
3032
pub(crate) allow_permission_management_operations: bool,
33+
/// Optional TLS secret class for OPA communication.
34+
/// If set, the CA certificate from this secret class will be added
35+
/// to Trino's truststore to make it trust OPA's TLS certificate.
36+
pub(crate) tls_secret_class: Option<String>,
3137
}
3238

3339
impl TrinoOpaConfig {
@@ -66,12 +72,24 @@ impl TrinoOpaConfig {
6672
OpaApiVersion::V1,
6773
)
6874
.await?;
75+
76+
let tls_secret_class = client
77+
.get::<ConfigMap>(
78+
&opa_config.config_map_name,
79+
trino.namespace().as_deref().unwrap_or("default"),
80+
)
81+
.await
82+
.ok()
83+
.and_then(|cm| cm.data)
84+
.and_then(|mut data| data.remove("OPA_SECRET_CLASS"));
85+
6986
Ok(TrinoOpaConfig {
7087
non_batched_connection_string,
7188
batched_connection_string,
7289
row_filters_connection_string: Some(row_filters_connection_string),
7390
column_masking_connection_string: Some(column_masking_connection_string),
7491
allow_permission_management_operations: true,
92+
tls_secret_class,
7593
})
7694
}
7795

rust/operator-binary/src/controller.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ pub const MAX_PREPARE_LOG_FILE_SIZE: MemoryQuantity = MemoryQuantity {
123123
};
124124

125125
const DOCKER_IMAGE_BASE_NAME: &str = "trino";
126+
const OPA_TLS_VOLUME_NAME: &str = "opa-tls";
126127

127128
#[derive(Snafu, Debug, EnumDiscriminants)]
128129
#[strum_discriminants(derive(IntoStaticStr))]
@@ -630,6 +631,7 @@ pub async fn reconcile_trino(
630631
&rbac_sa.name_any(),
631632
&resolved_fte_config,
632633
&resolved_client_protocol_config,
634+
&trino_opa_config,
633635
)?;
634636

635637
cluster_resources
@@ -1037,6 +1039,7 @@ fn build_rolegroup_statefulset(
10371039
sa_name: &str,
10381040
resolved_fte_config: &Option<fault_tolerant_execution::ResolvedFaultTolerantExecutionConfig>,
10391041
resolved_spooling_config: &Option<client_protocol::ResolvedClientProtocolConfig>,
1042+
trino_opa_config: &Option<TrinoOpaConfig>,
10401043
) -> Result<StatefulSet> {
10411044
let role = trino
10421045
.role(trino_role)
@@ -1140,6 +1143,7 @@ fn build_rolegroup_statefulset(
11401143
&requested_secret_lifetime,
11411144
resolved_fte_config,
11421145
resolved_spooling_config,
1146+
trino_opa_config,
11431147
)?;
11441148

11451149
let mut prepare_args = vec![];
@@ -1165,6 +1169,18 @@ fn build_rolegroup_statefulset(
11651169
prepare_args
11661170
.extend(trino_authentication_config.commands(&TrinoRole::Coordinator, &Container::Prepare));
11671171

1172+
// Add OPA TLS certificate to truststore if configured
1173+
if trino_opa_config
1174+
.as_ref()
1175+
.and_then(|c| c.tls_secret_class.as_ref())
1176+
.is_some()
1177+
{
1178+
prepare_args.extend(command::add_cert_to_truststore(
1179+
&format!("/stackable/secrets/{OPA_TLS_VOLUME_NAME}/ca.crt"),
1180+
STACKABLE_CLIENT_TLS_DIR,
1181+
));
1182+
}
1183+
11681184
let container_prepare = cb_prepare
11691185
.image_from_product_image(resolved_product_image)
11701186
.command(vec![
@@ -1710,6 +1726,7 @@ fn tls_volume_mounts(
17101726
requested_secret_lifetime: &Duration,
17111727
resolved_fte_config: &Option<fault_tolerant_execution::ResolvedFaultTolerantExecutionConfig>,
17121728
resolved_spooling_config: &Option<client_protocol::ResolvedClientProtocolConfig>,
1729+
trino_opa_config: &Option<TrinoOpaConfig>,
17131730
) -> Result<()> {
17141731
if let Some(server_tls) = trino.get_server_tls() {
17151732
cb_prepare
@@ -1789,6 +1806,28 @@ fn tls_volume_mounts(
17891806
.context(AddVolumeSnafu)?;
17901807
}
17911808

1809+
if let Some(opa_config) = trino_opa_config {
1810+
if let Some(opa_tls_secret_class) = &opa_config.tls_secret_class {
1811+
let opa_tls_mount_path = format!("/stackable/secrets/{OPA_TLS_VOLUME_NAME}");
1812+
1813+
cb_prepare
1814+
.add_volume_mount(OPA_TLS_VOLUME_NAME, &opa_tls_mount_path)
1815+
.context(AddVolumeMountSnafu)?;
1816+
1817+
let opa_tls_volume = VolumeBuilder::new(OPA_TLS_VOLUME_NAME)
1818+
.ephemeral(
1819+
SecretOperatorVolumeSourceBuilder::new(opa_tls_secret_class)
1820+
.build()
1821+
.context(TlsCertSecretClassVolumeBuildSnafu)?,
1822+
)
1823+
.build();
1824+
1825+
pod_builder
1826+
.add_volume(opa_tls_volume)
1827+
.context(AddVolumeSnafu)?;
1828+
}
1829+
}
1830+
17921831
// fault tolerant execution S3 credentials and other resources
17931832
if let Some(resolved_fte) = resolved_fte_config {
17941833
cb_prepare
@@ -2028,6 +2067,7 @@ mod tests {
20282067
.to_string(),
20292068
),
20302069
allow_permission_management_operations: true,
2070+
tls_secret_class: None,
20312071
});
20322072
let resolved_fte_config = match &trino.spec.cluster_config.fault_tolerant_execution {
20332073
Some(fault_tolerant_execution) => Some(

tests/templates/kuttl/opa-authorization/10-install-opa.yaml.j2

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,19 @@ commands:
55
- script: |
66
kubectl apply -n $NAMESPACE -f - <<EOF
77
---
8+
apiVersion: secrets.stackable.tech/v1alpha1
9+
kind: SecretClass
10+
metadata:
11+
name: opa-tls-$NAMESPACE
12+
spec:
13+
backend:
14+
autoTls:
15+
ca:
16+
autoGenerate: true
17+
secret:
18+
name: opa-tls-ca-$NAMESPACE
19+
namespace: $NAMESPACE
20+
---
821
apiVersion: opa.stackable.tech/v1alpha1
922
kind: OpaCluster
1023
metadata:
@@ -19,6 +32,8 @@ commands:
1932
{% endif %}
2033
pullPolicy: IfNotPresent
2134
clusterConfig:
35+
tls:
36+
serverSecretClass: opa-tls-$NAMESPACE
2237
userInfo:
2338
backend:
2439
keycloak:

0 commit comments

Comments
 (0)