-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
0492fb8
commit 868d978
Showing
6 changed files
with
93 additions
and
108 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -9,11 +9,9 @@ use famedly_sync::{ | |
ukt_test_helpers::{ | ||
get_mock_server_url, prepare_endpoint_mock, prepare_oauth2_mock, ENDPOINT_PATH, OAUTH2_PATH, | ||
}, | ||
AttributeMapping, Config, FeatureFlag, LdapSourceConfig, | ||
AttributeMapping, Config, FeatureFlag, | ||
}; | ||
use ldap3::{Ldap as LdapClient, LdapConnAsync, LdapConnSettings, Mod}; | ||
use serde::{de::IntoDeserializer, Deserialize}; | ||
use tempfile::TempDir; | ||
use test_log::test; | ||
use tokio::sync::OnceCell; | ||
use url::Url; | ||
|
@@ -24,8 +22,9 @@ use zitadel_rust_client::v1::{ | |
Email, Gender, ImportHumanUserRequest, Phone, Profile, UserType, Zitadel, | ||
}; | ||
|
||
static CONFIG: OnceCell<Config> = OnceCell::const_new(); | ||
static TEMPDIR: OnceCell<TempDir> = OnceCell::const_new(); | ||
static CONFIG_WITH_LDAP: OnceCell<Config> = OnceCell::const_new(); | ||
static CONFIG_WITH_CSV: OnceCell<Config> = OnceCell::const_new(); | ||
static CONFIG_WITH_UKT: OnceCell<Config> = OnceCell::const_new(); | ||
|
||
/// The Famedly UUID namespace to use to generate v5 UUIDs. | ||
const FAMEDLY_NAMESPACE: Uuid = uuid!("d9979cff-abee-4666-bc88-1ec45a843fb8"); | ||
|
@@ -790,7 +789,7 @@ async fn test_e2e_ukt_sync() { | |
prepare_oauth2_mock(&mock_server).await; | ||
prepare_endpoint_mock(&mock_server, "[email protected]").await; | ||
|
||
let mut config = ldap_config().await.clone(); | ||
let mut config = ukt_config().await.clone(); | ||
|
||
config | ||
.sources | ||
|
@@ -847,7 +846,7 @@ async fn test_e2e_ukt_sync() { | |
#[test(tokio::test)] | ||
#[test_log(default_log_filter = "debug")] | ||
async fn test_e2e_csv_sync() { | ||
let mut config = ldap_config().await.clone(); | ||
let mut config = csv_config().await.clone(); | ||
|
||
perform_sync(&config).await.expect("syncing failed"); | ||
|
||
|
@@ -905,7 +904,7 @@ async fn test_e2e_csv_sync() { | |
let grant = grants.result.first().expect("no user grants found"); | ||
assert!(grant.role_keys.clone().into_iter().any(|key| key == FAMEDLY_USER_ROLE)); | ||
|
||
// Not possible to re-import an existing user (as checked by unique email) | ||
// Re-import an existing user to update (as checked by unique email) | ||
let csv_content = indoc::indoc! {r#" | ||
email,first_name,last_name,phone | ||
[email protected],Changed_Name,Changed_Surname,+2222222222 | ||
|
@@ -925,10 +924,10 @@ async fn test_e2e_csv_sync() { | |
let phone = user.phone.expect("user lacks a phone number"); | ||
let email = user.email.expect("user lacks an email address"); | ||
|
||
assert_eq!(profile.first_name, "John"); | ||
assert_eq!(profile.last_name, "Doe"); | ||
assert_eq!(profile.display_name, "Doe, John"); | ||
assert_eq!(phone.phone, "+1111111111"); | ||
assert_eq!(profile.first_name, "Changed_Name"); | ||
assert_eq!(profile.last_name, "Changed_Surname"); | ||
assert_eq!(profile.display_name, "Changed_Surname, Changed_Name"); | ||
assert_eq!(phone.phone, "+2222222222"); | ||
assert!(phone.is_phone_verified); | ||
assert_eq!(email.email, "[email protected]"); | ||
assert!(email.is_email_verified); | ||
|
@@ -939,23 +938,12 @@ async fn test_e2e_csv_sync() { | |
|
||
#[test(tokio::test)] | ||
#[test_log(default_log_filter = "debug")] | ||
async fn test_e2e_full_sync() { | ||
async fn test_e2e_ldap_with_ukt_sync() { | ||
let mock_server = MockServer::start().await; | ||
prepare_oauth2_mock(&mock_server).await; | ||
prepare_endpoint_mock(&mock_server, "[email protected]").await; | ||
|
||
let mut config = ldap_config().await.clone(); | ||
config | ||
.sources | ||
.ukt | ||
.as_mut() | ||
.map(|ukt| { | ||
ukt.oauth2_url = get_mock_server_url(&mock_server, OAUTH2_PATH) | ||
.expect("Failed to get mock server URL"); | ||
ukt.endpoint_url = get_mock_server_url(&mock_server, ENDPOINT_PATH) | ||
.expect("Failed to get mock server URL"); | ||
}) | ||
.expect("UKT configuration is missing"); | ||
// LDAP SYNC | ||
|
||
let mut ldap = Ldap::new().await; | ||
ldap.create_user( | ||
|
@@ -1002,44 +990,34 @@ async fn test_e2e_full_sync() { | |
) | ||
.await; | ||
|
||
let csv_content = indoc::indoc! {r#" | ||
email,first_name,last_name,phone | ||
[email protected],John,Doe,+1111111111 | ||
"#}; | ||
// Have to create a new temp file | ||
// because we can't re-use users between tests | ||
// and the ./tests/environment/files/test-users.csv was already imported | ||
let _file = temp_csv_file(&mut config, csv_content); | ||
let ldap_config = ldap_config().await.clone(); | ||
perform_sync(&ldap_config).await.expect("syncing failed"); | ||
|
||
perform_sync(&config).await.expect("syncing failed"); | ||
// UKT SYNC | ||
|
||
let zitadel = open_zitadel_connection().await; | ||
let mut ukt_config = ukt_config().await.clone(); | ||
ukt_config | ||
.sources | ||
.ukt | ||
.as_mut() | ||
.map(|ukt| { | ||
ukt.oauth2_url = get_mock_server_url(&mock_server, OAUTH2_PATH) | ||
.expect("Failed to get mock server URL"); | ||
ukt.endpoint_url = get_mock_server_url(&mock_server, ENDPOINT_PATH) | ||
.expect("Failed to get mock server URL"); | ||
}) | ||
.expect("UKT configuration is missing"); | ||
|
||
let user = zitadel | ||
.get_user_by_login_name("[email protected]") | ||
.await | ||
.expect("could not query Zitadel users"); | ||
assert!(user.is_some()); | ||
let user = user.expect("could not find user"); | ||
assert_eq!(user.user_name, "[email protected]"); | ||
if let Some(UserType::Human(user)) = user.r#type { | ||
let profile = user.profile.expect("user lacks a profile"); | ||
let phone = user.phone.expect("user lacks a phone number"); | ||
let email = user.email.expect("user lacks an email address"); | ||
perform_sync(&ukt_config).await.expect("syncing failed"); | ||
|
||
assert_eq!(profile.first_name, "John"); | ||
assert_eq!(profile.last_name, "Doe"); | ||
assert_eq!(profile.display_name, "Doe, John"); | ||
assert_eq!(phone.phone, "+1111111111"); | ||
assert!(phone.is_phone_verified); | ||
assert_eq!(email.email, "[email protected]"); | ||
assert!(email.is_email_verified); | ||
} else { | ||
panic!("user lacks details"); | ||
} | ||
// VERIFY RESULTS OF SYNC | ||
|
||
let zitadel = open_zitadel_connection().await; | ||
|
||
let user = zitadel.get_user_by_login_name("[email protected]").await; | ||
assert!(user.is_err_and(|error| matches!(error, ZitadelError::TonicResponseError(status) if status.code() == TonicErrorCode::NotFound))); | ||
assert!(user.is_err_and(|error| matches!(error, | ||
ZitadelError::TonicResponseError(status) if status.code() == | ||
TonicErrorCode::NotFound))); | ||
|
||
let user = zitadel | ||
.get_user_by_login_name("[email protected]") | ||
|
@@ -1066,11 +1044,15 @@ async fn test_e2e_full_sync() { | |
_ => panic!("human user became a machine user?"), | ||
} | ||
|
||
// UPDATES IN LDAP | ||
|
||
ldap.change_user("to_be_changed", vec![("telephoneNumber", HashSet::from(["+12015550123"]))]) | ||
.await; | ||
ldap.delete_user("not_to_be_there_later").await; | ||
|
||
perform_sync(&config).await.expect("syncing failed"); | ||
perform_sync(&ldap_config).await.expect("syncing failed"); | ||
|
||
// VERIFY SECOND LDAP SYNC | ||
|
||
let user = zitadel | ||
.get_user_by_login_name("[email protected]") | ||
|
@@ -1084,7 +1066,6 @@ async fn test_e2e_full_sync() { | |
} | ||
_ => panic!("human user became a machine user?"), | ||
} | ||
|
||
let user = zitadel.get_user_by_login_name("[email protected]").await; | ||
assert!(user.is_err_and(|error| matches!(error, ZitadelError::TonicResponseError(status) if status.code() == TonicErrorCode::NotFound))); | ||
} | ||
|
@@ -1225,12 +1206,12 @@ async fn open_zitadel_connection() -> Zitadel { | |
|
||
/// Get the module's test environment config | ||
async fn ldap_config() -> &'static Config { | ||
CONFIG | ||
CONFIG_WITH_LDAP | ||
.get_or_init(|| async { | ||
let mut config = Config::new(Path::new("tests/environment/config.yaml")) | ||
.expect("failed to parse test env file"); | ||
|
||
config.sources.ldap = serde_json::from_slice( | ||
config.sources.ldap = serde_yaml::from_slice( | ||
&std::fs::read(Path::new("tests/environment/ldap-config.template.yaml")) | ||
.expect("failed to read ldap config file"), | ||
) | ||
|
@@ -1243,12 +1224,12 @@ async fn ldap_config() -> &'static Config { | |
|
||
/// Get the module's test environment config | ||
async fn ukt_config() -> &'static Config { | ||
CONFIG | ||
CONFIG_WITH_UKT | ||
.get_or_init(|| async { | ||
let mut config = Config::new(Path::new("tests/environment/config.yaml")) | ||
.expect("failed to parse test env file"); | ||
|
||
config.sources.ldap = serde_json::from_slice( | ||
config.sources.ukt = serde_yaml::from_slice( | ||
&std::fs::read(Path::new("tests/environment/ukt-config.template.yaml")) | ||
.expect("failed to read ukt config file"), | ||
) | ||
|
@@ -1261,12 +1242,12 @@ async fn ukt_config() -> &'static Config { | |
|
||
/// Get the module's test environment config | ||
async fn csv_config() -> &'static Config { | ||
CONFIG | ||
CONFIG_WITH_CSV | ||
.get_or_init(|| async { | ||
let mut config = Config::new(Path::new("tests/environment/config.yaml")) | ||
.expect("failed to parse test env file"); | ||
|
||
config.sources.ldap = serde_json::from_slice( | ||
config.sources.csv = serde_yaml::from_slice( | ||
&std::fs::read(Path::new("tests/environment/csv-config.template.yaml")) | ||
.expect("failed to read csv config file"), | ||
) | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,3 +7,6 @@ zitadel: | |
|
||
feature_flags: | ||
- sso_login | ||
|
||
sources: | ||
test: 1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,6 @@ | ||
sources: | ||
csv: | ||
file_path: ./tests/environment/files/test-users.csv | ||
# Updates Zitadel to match the CSV file. | ||
#! DANGER: This will delete all users that are not in the CSV file! | ||
|
||
# Expected structure of the CSV file is as follows: | ||
# email,first_name,last_name,phone | ||
file_path: ./tests/environment/files/test-users.csv |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,26 @@ | ||
sources: | ||
ldap: | ||
url: ldap://localhost:1389 | ||
base_dn: ou=testorg,dc=example,dc=org | ||
bind_dn: cn=admin,dc=example,dc=org | ||
bind_password: adminpassword | ||
user_filter: "(objectClass=shadowAccount)" | ||
timeout: 5 | ||
check_for_deleted_entries: true | ||
use_attribute_filter: true | ||
attributes: | ||
first_name: "cn" # objectClass: person | ||
last_name: "sn" # objectClass: person | ||
preferred_username: "displayName" # objectClass: inetOrgPerson | ||
email: "mail" # objectClass: inetOrgPerson | ||
phone: "telephoneNumber" # objectClass: person | ||
user_id: "uid" | ||
status: | ||
name: "shadowFlag" # objectClass: shadowAccount | ||
is_binary: false | ||
disable_bitmasks: [0x2, 0x10] | ||
tls: | ||
client_key: ./tests/environment/certs/client.key | ||
client_certificate: ./tests/environment/certs/client.crt | ||
server_certificate: ./tests/environment/certs/server.crt | ||
danger_disable_tls_verify: false | ||
danger_use_start_tls: false | ||
cache_path: ./test | ||
url: ldap://localhost:1389 | ||
base_dn: ou=testorg,dc=example,dc=org | ||
bind_dn: cn=admin,dc=example,dc=org | ||
bind_password: adminpassword | ||
user_filter: "(objectClass=shadowAccount)" | ||
timeout: 5 | ||
check_for_deleted_entries: true | ||
use_attribute_filter: true | ||
attributes: | ||
first_name: "cn" # objectClass: person | ||
last_name: "sn" # objectClass: person | ||
preferred_username: "displayName" # objectClass: inetOrgPerson | ||
email: "mail" # objectClass: inetOrgPerson | ||
phone: "telephoneNumber" # objectClass: person | ||
user_id: "uid" | ||
status: | ||
name: "shadowFlag" # objectClass: shadowAccount | ||
is_binary: false | ||
disable_bitmasks: [0x2, 0x10] | ||
tls: | ||
client_key: ./tests/environment/certs/client.key | ||
client_certificate: ./tests/environment/certs/client.crt | ||
server_certificate: ./tests/environment/certs/server.crt | ||
danger_disable_tls_verify: false | ||
danger_use_start_tls: false | ||
cache_path: ./test |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,6 @@ | ||
sources: | ||
ukt: | ||
endpoint_url: https://list.example.invalid/usersync4chat/maillist | ||
oauth2_url: https://list.example.invalid/token | ||
client_id: mock_client_id | ||
client_secret: mock_client_secret | ||
scope: "openid read-maillist" | ||
grant_type: client_credentials | ||
endpoint_url: https://list.example.invalid/usersync4chat/maillist | ||
oauth2_url: https://list.example.invalid/token | ||
client_id: mock_client_id | ||
client_secret: mock_client_secret | ||
scope: "openid read-maillist" | ||
grant_type: client_credentials |