Skip to content
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
a5b7d91
wip - compiling
maltesander Mar 29, 2025
aa254e4
wip
maltesander Mar 31, 2025
6f38bb9
wip
maltesander Apr 4, 2025
fc7b35a
cleanup & test
maltesander Apr 13, 2025
261df99
remove comments
maltesander Apr 15, 2025
41d7eec
adapt entra name
maltesander Apr 15, 2025
d52c9aa
set correct default
maltesander Apr 15, 2025
108abe1
Merge remote-tracking branch 'origin/main' into feat/experimental-ent…
maltesander Apr 15, 2025
6f75fc7
merge main
maltesander Apr 15, 2025
04c3117
fmt
maltesander Apr 15, 2025
dc5130f
test fix entra endpoint
maltesander Apr 15, 2025
29202b9
fmt
maltesander Apr 15, 2025
5a4860e
split token and host endpoint
maltesander Apr 15, 2025
6b85d1b
fix group response
maltesander Apr 15, 2025
f438b63
clippy
maltesander Apr 15, 2025
4ed2a92
use url in entra endpoint
maltesander Apr 15, 2025
c26952f
regenerate charts
maltesander Apr 15, 2025
888076d
extend test, improve erros
maltesander Apr 15, 2025
b974eb6
use with_context
maltesander Apr 16, 2025
61baffb
use with context 2
maltesander Apr 16, 2025
c85e2b3
clippy
maltesander Apr 16, 2025
60d903b
Merge remote-tracking branch 'origin/main' into feat/experimental-ent…
maltesander Apr 16, 2025
b1913ca
change endpoint to hostname in CRD
maltesander Apr 17, 2025
cad745a
consolidate naming
maltesander Apr 17, 2025
8c07822
change entrabackend to use url consistently
maltesander Apr 17, 2025
2dc58ce
Merge remote-tracking branch 'origin/main' into feat/experimental-ent…
maltesander Apr 17, 2025
e6a531a
remove obsolete tests
maltesander Apr 17, 2025
45cf3cc
reduce tests further
maltesander Apr 17, 2025
d0c127a
add documentation
maltesander Apr 17, 2025
c93f239
adapted changelog
maltesander Apr 17, 2025
616b514
fix typo
maltesander Apr 17, 2025
4d10eaa
make port optional
maltesander Apr 22, 2025
cd15999
clippy
maltesander Apr 22, 2025
d7b088c
Merge remote-tracking branch 'origin/main' into feat/experimental-ent…
maltesander Apr 22, 2025
bf0b62e
Merge remote-tracking branch 'origin/main' into feat/experimental-ent…
maltesander May 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions deploy/helm/opa-operator/crds/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ spec:
- experimentalXfscAas
- required:
- experimentalActiveDirectory
- required:
- experimentalEntra
properties:
experimentalActiveDirectory:
description: Backend that fetches user information from Active Directory
Expand Down Expand Up @@ -137,6 +139,81 @@ spec:
- kerberosSecretClassName
- ldapServer
type: object
experimentalEntra:
description: Backend that fetches user information from Microsoft Entra
properties:
clientCredentialsSecret:
description: |-
Name of a Secret that contains client credentials of a Entra account with permission to read user metadata.

Must contain the fields `clientId` and `clientSecret`.
type: string
hostnameGraph:
default: graph.microsoft.com
description: Hostname of the user info provider, defaults to `graph.microsoft.com`.
type: string
hostnameToken:
default: login.microsoft.com
description: Hostname of the token provider, defaults to `login.microsoft.com`.
type: string
port:
default: 443
description: Port of the identity provider. Defaults to 443.
format: uint16
minimum: 0.0
type: integer
tenantId:
description: The Microsoft Entra tenant ID.
type: string
tls:
default:
verification:
server:
caCert:
webPki: {}
description: Use a TLS connection. Should usually be set to WebPki.
nullable: true
properties:
verification:
description: The verification method used to verify the certificates of the server and/or the client.
oneOf:
- required:
- none
- required:
- server
properties:
none:
description: Use TLS but don't verify certificates.
type: object
server:
description: Use TLS and a CA certificate to verify the server.
properties:
caCert:
description: CA cert to verify the server.
oneOf:
- required:
- webPki
- required:
- secretClass
properties:
secretClass:
description: Name of the [SecretClass](https://docs.stackable.tech/home/nightly/secret-operator/secretclass) which will provide the CA certificate. Note that a SecretClass does not need to have a key but can also work with just a CA certificate, so if you got provided with a CA cert but don't have access to the key you can still use this method.
type: string
webPki:
description: Use TLS and the CA certificates trusted by the common web browsers to verify the server. This can be useful when you e.g. use public AWS S3 or other public available services.
type: object
type: object
required:
- caCert
type: object
type: object
required:
- verification
type: object
required:
- clientCredentialsSecret
- tenantId
type: object
experimentalXfscAas:
description: Backend that fetches user information from the Gaia-X Cross Federation Services Components (XFSC) Authentication & Authorization Service.
properties:
Expand Down
25 changes: 24 additions & 1 deletion rust/operator-binary/src/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ use stackable_operator::{
product_image_selection::ResolvedProductImage,
rbac::build_rbac_resources,
secret_class::{SecretClassVolume, SecretClassVolumeScope},
tls_verification::TlsClientDetailsError,
tls_verification::{TlsClientDetails, TlsClientDetailsError},
},
k8s_openapi::{
DeepMerge,
Expand Down Expand Up @@ -1014,6 +1014,29 @@ fn build_server_rolegroup_daemonset(
.add_volumes_and_mounts(&mut pb, vec![&mut cb_user_info_fetcher])
.context(UserInfoFetcherTlsVolumeAndMountsSnafu)?;
}
user_info_fetcher::v1alpha1::Backend::Entra(entra) => {
pb.add_volume(
VolumeBuilder::new(USER_INFO_FETCHER_CREDENTIALS_VOLUME_NAME)
.secret(SecretVolumeSource {
secret_name: Some(entra.client_credentials_secret.clone()),
..Default::default()
})
.build(),
)
.context(AddVolumeSnafu)?;
cb_user_info_fetcher
.add_volume_mount(
USER_INFO_FETCHER_CREDENTIALS_VOLUME_NAME,
USER_INFO_FETCHER_CREDENTIALS_DIR,
)
.context(AddVolumeMountSnafu)?;

TlsClientDetails {
tls: entra.tls.clone(),
}
.add_volumes_and_mounts(&mut pb, vec![&mut cb_user_info_fetcher])
.context(UserInfoFetcherTlsVolumeAndMountsSnafu)?;
}
}

pb.add_container(cb_user_info_fetcher.build());
Expand Down
59 changes: 57 additions & 2 deletions rust/operator-binary/src/crd/user_info_fetcher.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use std::collections::BTreeMap;
use std::{collections::BTreeMap, str::FromStr};

use serde::{Deserialize, Serialize};
use stackable_operator::{
commons::{networking::HostName, tls_verification::TlsClientDetails},
commons::{
networking::HostName,
tls_verification::{CaCert, Tls, TlsClientDetails, TlsServerVerification, TlsVerification},
},
schemars::{self, JsonSchema},
time::Duration,
versioned::versioned,
Expand Down Expand Up @@ -38,6 +41,10 @@ pub mod versioned {
/// Backend that fetches user information from Active Directory
#[serde(rename = "experimentalActiveDirectory")]
ActiveDirectory(v1alpha1::ActiveDirectoryBackend),

/// Backend that fetches user information from Microsoft Entra
#[serde(rename = "experimentalEntra")]
Entra(v1alpha1::EntraBackend),
}

#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
Expand Down Expand Up @@ -110,6 +117,34 @@ pub mod versioned {
pub additional_group_attribute_filters: BTreeMap<String, String>,
}

#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct EntraBackend {
/// Hostname of the token provider, defaults to `login.microsoft.com`.
#[serde(default = "entra_default_host_token")]
pub hostname_token: HostName,

/// Hostname of the user info provider, defaults to `graph.microsoft.com`.
#[serde(default = "entra_default_host_graph")]
pub hostname_graph: HostName,

/// Port of the identity provider. Defaults to 443.
#[serde(default = "entra_default_port")]
pub port: u16,

/// The Microsoft Entra tenant ID.
pub tenant_id: String,

/// Use a TLS connection. Should usually be set to WebPki.
#[serde(default = "default_tls_web_pki")]
pub tls: Option<Tls>,

/// Name of a Secret that contains client credentials of a Entra account with permission to read user metadata.
///
/// Must contain the fields `clientId` and `clientSecret`.
pub client_credentials_secret: String,
}

#[derive(Clone, Debug, Deserialize, Eq, JsonSchema, PartialEq, Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Cache {
Expand All @@ -129,6 +164,26 @@ fn default_root_path() -> String {
"/".to_string()
}

fn entra_default_host_token() -> HostName {
HostName::from_str("login.microsoft.com").unwrap()
}

fn entra_default_host_graph() -> HostName {
HostName::from_str("graph.microsoft.com").unwrap()
}

fn entra_default_port() -> u16 {
443
}

fn default_tls_web_pki() -> Option<Tls> {
Some(Tls {
verification: TlsVerification::Server(TlsServerVerification {
ca_cert: CaCert::WebPki {},
}),
})
}

fn aas_default_port() -> u16 {
5000
}
Expand Down
Loading