Skip to content

Commit 8055760

Browse files
authored
feat: OPA TLS support (#812)
* feat: OPA TLS support * chore: changelog * recfactor: OPA tls mount helper method
1 parent e4320f1 commit 8055760

File tree

4 files changed

+88
-3
lines changed

4 files changed

+88
-3
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ All notable changes to this project will be documented in this file.
1616
- Add support for Trino 477 ([#801]).
1717
- Add support for Hive 4.1.0 ([#805]).
1818
- Add `prometheus.io/path|port|scheme` annotations to metrics service ([#807]).
19+
- Add support for OPA with TLS enabled ([#812]).
1920

2021
### Changed
2122

@@ -45,6 +46,7 @@ All notable changes to this project will be documented in this file.
4546
[#805]: https://github.com/stackabletech/trino-operator/pull/805
4647
[#807]: https://github.com/stackabletech/trino-operator/pull/807
4748
[#810]: https://github.com/stackabletech/trino-operator/pull/810
49+
[#812]: https://github.com/stackabletech/trino-operator/pull/812
4850

4951
## [25.7.0] - 2025-07-23
5052

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

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,14 @@ 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;
911

12+
pub const OPA_TLS_VOLUME_NAME: &str = "opa-tls";
13+
1014
pub struct TrinoOpaConfig {
1115
/// URI for OPA policies, e.g.
1216
/// `http://localhost:8081/v1/data/trino/allow`
@@ -28,6 +32,10 @@ pub struct TrinoOpaConfig {
2832
/// such operations, they will be bulk allowed or denied depending
2933
/// on this setting
3034
pub(crate) allow_permission_management_operations: bool,
35+
/// Optional TLS secret class for OPA communication.
36+
/// If set, the CA certificate from this secret class will be added
37+
/// to Trino's truststore to make it trust OPA's TLS certificate.
38+
pub(crate) tls_secret_class: Option<String>,
3139
}
3240

3341
impl TrinoOpaConfig {
@@ -66,12 +74,24 @@ impl TrinoOpaConfig {
6674
OpaApiVersion::V1,
6775
)
6876
.await?;
77+
78+
let tls_secret_class = client
79+
.get::<ConfigMap>(
80+
&opa_config.config_map_name,
81+
trino.namespace().as_deref().unwrap_or("default"),
82+
)
83+
.await
84+
.ok()
85+
.and_then(|cm| cm.data)
86+
.and_then(|mut data| data.remove("OPA_SECRET_CLASS"));
87+
6988
Ok(TrinoOpaConfig {
7089
non_batched_connection_string,
7190
batched_connection_string,
7291
row_filters_connection_string: Some(row_filters_connection_string),
7392
column_masking_connection_string: Some(column_masking_connection_string),
7493
allow_permission_management_operations: true,
94+
tls_secret_class,
7595
})
7696
}
7797

@@ -107,4 +127,10 @@ impl TrinoOpaConfig {
107127
}
108128
config
109129
}
130+
131+
pub fn tls_mount_path(&self) -> Option<String> {
132+
self.tls_secret_class
133+
.as_ref()
134+
.map(|_| format!("/stackable/secrets/{OPA_TLS_VOLUME_NAME}"))
135+
}
110136
}

rust/operator-binary/src/controller.rs

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,10 +76,10 @@ use strum::{EnumDiscriminants, IntoStaticStr};
7676

7777
use crate::{
7878
authentication::{TrinoAuthenticationConfig, TrinoAuthenticationTypes},
79-
authorization::opa::TrinoOpaConfig,
79+
authorization::opa::{OPA_TLS_VOLUME_NAME, TrinoOpaConfig},
8080
catalog::{FromTrinoCatalogError, config::CatalogConfig},
81-
command, config,
82-
config::{client_protocol, fault_tolerant_execution},
81+
command,
82+
config::{self, client_protocol, fault_tolerant_execution},
8383
crd::{
8484
ACCESS_CONTROL_PROPERTIES, APP_NAME, CONFIG_DIR_NAME, CONFIG_PROPERTIES, Container,
8585
DISCOVERY_URI, ENV_INTERNAL_SECRET, ENV_SPOOLING_SECRET, EXCHANGE_MANAGER_PROPERTIES,
@@ -630,6 +630,7 @@ pub async fn reconcile_trino(
630630
&rbac_sa.name_any(),
631631
&resolved_fte_config,
632632
&resolved_client_protocol_config,
633+
&trino_opa_config,
633634
)?;
634635

635636
cluster_resources
@@ -1037,6 +1038,7 @@ fn build_rolegroup_statefulset(
10371038
sa_name: &str,
10381039
resolved_fte_config: &Option<fault_tolerant_execution::ResolvedFaultTolerantExecutionConfig>,
10391040
resolved_spooling_config: &Option<client_protocol::ResolvedClientProtocolConfig>,
1041+
trino_opa_config: &Option<TrinoOpaConfig>,
10401042
) -> Result<StatefulSet> {
10411043
let role = trino
10421044
.role(trino_role)
@@ -1140,6 +1142,7 @@ fn build_rolegroup_statefulset(
11401142
&requested_secret_lifetime,
11411143
resolved_fte_config,
11421144
resolved_spooling_config,
1145+
trino_opa_config,
11431146
)?;
11441147

11451148
let mut prepare_args = vec![];
@@ -1165,6 +1168,17 @@ fn build_rolegroup_statefulset(
11651168
prepare_args
11661169
.extend(trino_authentication_config.commands(&TrinoRole::Coordinator, &Container::Prepare));
11671170

1171+
// Add OPA TLS certificate to truststore if configured
1172+
if let Some(tls_mount_path) = trino_opa_config
1173+
.as_ref()
1174+
.and_then(|opa_config| opa_config.tls_mount_path())
1175+
{
1176+
prepare_args.extend(command::add_cert_to_truststore(
1177+
format!("{}/ca.crt", tls_mount_path).as_str(),
1178+
STACKABLE_CLIENT_TLS_DIR,
1179+
));
1180+
}
1181+
11681182
let container_prepare = cb_prepare
11691183
.image_from_product_image(resolved_product_image)
11701184
.command(vec![
@@ -1710,6 +1724,7 @@ fn tls_volume_mounts(
17101724
requested_secret_lifetime: &Duration,
17111725
resolved_fte_config: &Option<fault_tolerant_execution::ResolvedFaultTolerantExecutionConfig>,
17121726
resolved_spooling_config: &Option<client_protocol::ResolvedClientProtocolConfig>,
1727+
trino_opa_config: &Option<TrinoOpaConfig>,
17131728
) -> Result<()> {
17141729
if let Some(server_tls) = trino.get_server_tls() {
17151730
cb_prepare
@@ -1789,6 +1804,32 @@ fn tls_volume_mounts(
17891804
.context(AddVolumeSnafu)?;
17901805
}
17911806

1807+
// Add OPA TLS certs if configured
1808+
if let Some((tls_secret_class, tls_mount_path)) =
1809+
trino_opa_config.as_ref().and_then(|opa_config| {
1810+
opa_config
1811+
.tls_secret_class
1812+
.as_ref()
1813+
.zip(opa_config.tls_mount_path())
1814+
})
1815+
{
1816+
cb_prepare
1817+
.add_volume_mount(OPA_TLS_VOLUME_NAME, &tls_mount_path)
1818+
.context(AddVolumeMountSnafu)?;
1819+
1820+
let opa_tls_volume = VolumeBuilder::new(OPA_TLS_VOLUME_NAME)
1821+
.ephemeral(
1822+
SecretOperatorVolumeSourceBuilder::new(tls_secret_class)
1823+
.build()
1824+
.context(TlsCertSecretClassVolumeBuildSnafu)?,
1825+
)
1826+
.build();
1827+
1828+
pod_builder
1829+
.add_volume(opa_tls_volume)
1830+
.context(AddVolumeSnafu)?;
1831+
}
1832+
17921833
// fault tolerant execution S3 credentials and other resources
17931834
if let Some(resolved_fte) = resolved_fte_config {
17941835
cb_prepare
@@ -2028,6 +2069,7 @@ mod tests {
20282069
.to_string(),
20292070
),
20302071
allow_permission_management_operations: true,
2072+
tls_secret_class: None,
20312073
});
20322074
let resolved_fte_config = match &trino.spec.cluster_config.fault_tolerant_execution {
20332075
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)