migration: Implement import from LDAP
This commit is contained in:
committed by
nitnelave
parent
aa83f6cab6
commit
31cf9b8e2c
205
migration-tool/src/main.rs
Normal file
205
migration-tool/src/main.rs
Normal file
@@ -0,0 +1,205 @@
|
||||
use std::collections::HashSet;
|
||||
|
||||
use anyhow::{anyhow, Result};
|
||||
use requestty::{prompt_one, Question};
|
||||
|
||||
mod ldap;
|
||||
mod lldap;
|
||||
|
||||
use ldap::LdapGroup;
|
||||
use lldap::{LldapGroup, User};
|
||||
|
||||
fn ask_generic_confirmation(name: &str, message: &str) -> Result<bool> {
|
||||
let confirm = Question::confirm(name)
|
||||
.message(message)
|
||||
.default(true)
|
||||
.build();
|
||||
let answer = prompt_one(confirm)?;
|
||||
Ok(answer.as_bool().unwrap())
|
||||
}
|
||||
|
||||
fn get_users_to_add(users: &[User], existing_users: &[String]) -> Result<Option<Vec<User>>> {
|
||||
let existing_users = HashSet::<&String>::from_iter(existing_users);
|
||||
let num_found_users = users.len();
|
||||
let input_users: Vec<_> = users
|
||||
.iter()
|
||||
.filter(|u| !existing_users.contains(&u.user_input.id))
|
||||
.map(User::clone)
|
||||
.collect();
|
||||
println!(
|
||||
"Found {} users, of which {} new users: [\n {}\n]",
|
||||
num_found_users,
|
||||
input_users.len(),
|
||||
input_users
|
||||
.iter()
|
||||
.map(|u| format!(
|
||||
"\"{}\" ({})",
|
||||
&u.user_input.id,
|
||||
if u.password.is_some() {
|
||||
"with password"
|
||||
} else {
|
||||
"no password"
|
||||
}
|
||||
))
|
||||
.collect::<Vec<_>>()
|
||||
.join(",\n ")
|
||||
);
|
||||
if !input_users.is_empty()
|
||||
&& ask_generic_confirmation(
|
||||
"proceed_users",
|
||||
"Do you want to proceed to add those users to LLDAP?",
|
||||
)?
|
||||
{
|
||||
Ok(Some(input_users))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
fn should_insert_groups(
|
||||
input_groups: &[LdapGroup],
|
||||
existing_groups: &[LldapGroup],
|
||||
) -> Result<bool> {
|
||||
let existing_group_names =
|
||||
HashSet::<&str>::from_iter(existing_groups.iter().map(|g| g.display_name.as_str()));
|
||||
let new_groups = input_groups
|
||||
.iter()
|
||||
.filter(|g| !existing_group_names.contains(g.name.as_str()));
|
||||
let num_new_groups = new_groups.clone().count();
|
||||
println!(
|
||||
"Found {} groups, of which {} new groups: [\n {}\n]",
|
||||
input_groups.len(),
|
||||
num_new_groups,
|
||||
new_groups
|
||||
.map(|g| g.name.as_str())
|
||||
.collect::<Vec<_>>()
|
||||
.join(",\n ")
|
||||
);
|
||||
Ok(num_new_groups != 0
|
||||
&& ask_generic_confirmation(
|
||||
"proceed_groups",
|
||||
"Do you want to proceed to add those groups to LLDAP?",
|
||||
)?)
|
||||
}
|
||||
|
||||
struct GroupList {
|
||||
ldap_groups: Vec<LdapGroup>,
|
||||
lldap_groups: Vec<LldapGroup>,
|
||||
}
|
||||
|
||||
fn migrate_groups(
|
||||
graphql_client: &lldap::GraphQLClient,
|
||||
ldap_connection: &mut ldap::LdapClient,
|
||||
) -> Result<Option<GroupList>> {
|
||||
Ok(
|
||||
if ask_generic_confirmation("should_import_groups", "Do you want to import groups?")? {
|
||||
let mut existing_groups = lldap::get_lldap_groups(graphql_client)?;
|
||||
let ldap_groups = ldap::get_groups(ldap_connection)?;
|
||||
if should_insert_groups(&ldap_groups, &existing_groups)? {
|
||||
lldap::insert_groups_into_lldap(
|
||||
&ldap_groups,
|
||||
&mut existing_groups,
|
||||
graphql_client,
|
||||
)?;
|
||||
}
|
||||
Some(GroupList {
|
||||
ldap_groups,
|
||||
lldap_groups: existing_groups,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
struct UserList {
|
||||
lldap_users: Vec<String>,
|
||||
ldap_users: Vec<User>,
|
||||
}
|
||||
|
||||
fn migrate_users(
|
||||
graphql_client: &lldap::GraphQLClient,
|
||||
ldap_connection: &mut ldap::LdapClient,
|
||||
) -> Result<Option<UserList>> {
|
||||
Ok(
|
||||
if ask_generic_confirmation("should_import_users", "Do you want to import users?")? {
|
||||
let mut existing_users = lldap::get_lldap_users(graphql_client)?;
|
||||
let users = ldap::get_users(ldap_connection)?;
|
||||
if let Some(users_to_add) = get_users_to_add(&users, &existing_users)? {
|
||||
lldap::insert_users_into_lldap(users_to_add, &mut existing_users, graphql_client)?;
|
||||
}
|
||||
Some(UserList {
|
||||
lldap_users: existing_users,
|
||||
ldap_users: users,
|
||||
})
|
||||
} else {
|
||||
None
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn migrate_memberships(
|
||||
user_list: Option<UserList>,
|
||||
group_list: Option<GroupList>,
|
||||
graphql_client: lldap::GraphQLClient,
|
||||
ldap_connection: &mut ldap::LdapClient,
|
||||
) -> Result<()> {
|
||||
let (ldap_users, existing_users) = user_list
|
||||
.map(
|
||||
|UserList {
|
||||
ldap_users,
|
||||
lldap_users,
|
||||
}| (Some(ldap_users), Some(lldap_users)),
|
||||
)
|
||||
.unwrap_or_default();
|
||||
let (ldap_groups, existing_groups) = group_list
|
||||
.map(
|
||||
|GroupList {
|
||||
ldap_groups,
|
||||
lldap_groups,
|
||||
}| (Some(ldap_groups), Some(lldap_groups)),
|
||||
)
|
||||
.unwrap_or_default();
|
||||
let ldap_users = ldap_users
|
||||
.ok_or_else(|| anyhow!("Missing LDAP users"))
|
||||
.or_else(|_| ldap::get_users(ldap_connection))?;
|
||||
let ldap_groups = ldap_groups
|
||||
.ok_or_else(|| anyhow!("Missing LDAP groups"))
|
||||
.or_else(|_| ldap::get_groups(ldap_connection))?;
|
||||
let existing_groups = existing_groups
|
||||
.ok_or_else(|| anyhow!("Missing LLDAP groups"))
|
||||
.or_else(|_| lldap::get_lldap_groups(&graphql_client))?;
|
||||
let existing_users = existing_users
|
||||
.ok_or_else(|| anyhow!("Missing LLDAP users"))
|
||||
.or_else(|_| lldap::get_lldap_users(&graphql_client))?;
|
||||
lldap::insert_group_memberships_into_lldap(
|
||||
&ldap_users,
|
||||
&ldap_groups,
|
||||
&existing_users,
|
||||
&existing_groups,
|
||||
&graphql_client,
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
println!(
|
||||
"The migration tool requires access to both the original LDAP \
|
||||
server and the HTTP API of the target LLDAP server."
|
||||
);
|
||||
if !ask_generic_confirmation("setup_ready", "Are you ready to start?")? {
|
||||
return Ok(());
|
||||
}
|
||||
let mut ldap_connection = ldap::get_ldap_connection()?;
|
||||
let graphql_client = lldap::get_lldap_client()?;
|
||||
let user_list = migrate_users(&graphql_client, &mut ldap_connection)?;
|
||||
let group_list = migrate_groups(&graphql_client, &mut ldap_connection)?;
|
||||
if ask_generic_confirmation(
|
||||
"should_import_memberships",
|
||||
"Do you want to import group memberships?",
|
||||
)? {
|
||||
migrate_memberships(user_list, group_list, graphql_client, &mut ldap_connection)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user