use crate::{common, error::Error, hsm};
use super::types::Group;
pub static PA_ADMIN: &str = "pa_admin";
pub static SYSTEM_WIDE_HSM_GROUPS: [&str; 4] =
["alps", "prealps", "alpse", "alpsb"];
pub static KEYCLOAK_ROLES_TO_IGNORE: [&str; 3] = [
"offline_access",
"uma_authorization",
"default-roles-shasta",
];
pub static ROLES: [&str; 6] = [
"Compute",
"Service",
"System",
"Application",
"Storage",
"Management",
];
pub static SUBROLES: [&str; 8] = [
"Worker",
"Master",
"Storage",
"UAN",
"Gateway",
"LNETRouter",
"Visualization",
"UserDefined",
];
pub fn filter_system_hsm_groups(
hsm_group_vec_rslt: Result<Vec<Group>, Error>,
) -> Result<Vec<Group>, Error> {
let hsm_group_vec_filtered_rslt: Result<Vec<Group>, Error> =
hsm_group_vec_rslt.and_then(|hsm_group_vec| {
Ok(
hsm_group_vec
.iter()
.filter(|hsm_group| {
let label = hsm_group.label.as_str();
!SYSTEM_WIDE_HSM_GROUPS.contains(&label)
})
.cloned()
.collect::<Vec<Group>>(),
)
});
if let Ok([]) = hsm_group_vec_filtered_rslt.as_deref() {
Err(Error::Message(format!(
"HSM groups '{}' not allowed.",
SYSTEM_WIDE_HSM_GROUPS.join(", ")
)))
} else {
hsm_group_vec_filtered_rslt
}
}
pub fn filter_keycloak_roles(keycloak_roles: &[&str]) -> Vec<String> {
keycloak_roles
.iter()
.filter(|role| !KEYCLOAK_ROLES_TO_IGNORE.contains(&role))
.map(|role| role.to_string())
.collect()
}
pub fn filter_system_hsm_group_names(
hsm_group_name_vec: Vec<String>,
) -> Vec<String> {
hsm_group_name_vec
.into_iter()
.filter(|hsm_group_name| {
!SYSTEM_WIDE_HSM_GROUPS.contains(&hsm_group_name.as_str())
})
.collect()
}
pub fn filter_roles_and_subroles(hsm_group_name_vec: &[&str]) -> Vec<String> {
hsm_group_name_vec
.iter()
.filter(|hsm_group_name| {
!ROLES.contains(&hsm_group_name) && !SUBROLES.contains(&hsm_group_name)
})
.map(|hsm_group_name| hsm_group_name.to_string())
.collect()
}
pub fn validate_groups_auth_token(
cfs_group_names: &[&str],
shasta_token: &str,
) -> Result<Vec<String>, Error> {
let keycloak_roles = common::jwt_ops::get_roles(shasta_token)?;
Ok(validate_groups(
cfs_group_names,
&keycloak_roles
.iter()
.map(String::as_str)
.collect::<Vec<&str>>(),
))
}
pub fn validate_groups(
cfs_group_names: &[&str],
keycloak_roles: &[&str],
) -> Vec<String> {
if keycloak_roles.contains(&PA_ADMIN) {
vec![]
} else {
let groups_and_roles_in_auth_token =
hsm::group::hacks::filter_keycloak_roles(keycloak_roles);
let site_wide_and_cluster_groups_in_auth_token =
hsm::group::hacks::filter_roles_and_subroles(
&groups_and_roles_in_auth_token
.iter()
.map(String::as_str)
.collect::<Vec<&str>>(),
);
let groups_in_user_auth_token =
filter_system_hsm_group_names(site_wide_and_cluster_groups_in_auth_token);
let groups_without_roles_subroles =
hsm::group::hacks::filter_roles_and_subroles(cfs_group_names);
let groups_without_system_wide =
hsm::group::hacks::filter_system_hsm_group_names(
groups_without_roles_subroles.to_vec(),
);
groups_without_system_wide
.into_iter()
.filter(|group| !groups_in_user_auth_token.contains(group))
.collect()
}
}