mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 12:37:00 +01:00
Allow opt-in of easter eggs (#3308)
So that we can start to add some more easter eggs to the server, we also need to respect user preferences that may not want them. This adds a configuration setting to the domain allowing a release build to opt-in to easter eggs, and development builds to opt-out of them.
This commit is contained in:
parent
1fbbf323fa
commit
50a7d9d700
|
@ -1,4 +1,5 @@
|
||||||
use crate::{ClientError, KanidmClient};
|
use crate::{ClientError, KanidmClient};
|
||||||
|
use kanidm_proto::constants::ATTR_DOMAIN_ALLOW_EASTER_EGGS;
|
||||||
use kanidm_proto::internal::ImageValue;
|
use kanidm_proto::internal::ImageValue;
|
||||||
use reqwest::multipart;
|
use reqwest::multipart;
|
||||||
|
|
||||||
|
@ -8,6 +9,14 @@ impl KanidmClient {
|
||||||
self.perform_delete_request("/v1/domain/_image").await
|
self.perform_delete_request("/v1/domain/_image").await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn idm_set_domain_allow_easter_eggs(&self, enable: bool) -> Result<(), ClientError> {
|
||||||
|
self.perform_put_request(
|
||||||
|
&format!("{}{}", "/v1/domain/_attr/", ATTR_DOMAIN_ALLOW_EASTER_EGGS),
|
||||||
|
vec![enable.to_string()],
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
/// Add or update the domain logo/image
|
/// Add or update the domain logo/image
|
||||||
pub async fn idm_domain_update_image(&self, image: ImageValue) -> Result<(), ClientError> {
|
pub async fn idm_domain_update_image(&self, image: ImageValue) -> Result<(), ClientError> {
|
||||||
let file_content_type = image.filetype.as_content_type_str();
|
let file_content_type = image.filetype.as_content_type_str();
|
||||||
|
|
|
@ -53,6 +53,7 @@ pub enum Attribute {
|
||||||
DisplayName,
|
DisplayName,
|
||||||
Dn,
|
Dn,
|
||||||
Domain,
|
Domain,
|
||||||
|
DomainAllowEasterEggs,
|
||||||
DomainDevelopmentTaint,
|
DomainDevelopmentTaint,
|
||||||
DomainDisplayName,
|
DomainDisplayName,
|
||||||
DomainLdapBasedn,
|
DomainLdapBasedn,
|
||||||
|
@ -282,6 +283,7 @@ impl Attribute {
|
||||||
Attribute::DisplayName => ATTR_DISPLAYNAME,
|
Attribute::DisplayName => ATTR_DISPLAYNAME,
|
||||||
Attribute::Dn => ATTR_DN,
|
Attribute::Dn => ATTR_DN,
|
||||||
Attribute::Domain => ATTR_DOMAIN,
|
Attribute::Domain => ATTR_DOMAIN,
|
||||||
|
Attribute::DomainAllowEasterEggs => ATTR_DOMAIN_ALLOW_EASTER_EGGS,
|
||||||
Attribute::DomainDevelopmentTaint => ATTR_DOMAIN_DEVELOPMENT_TAINT,
|
Attribute::DomainDevelopmentTaint => ATTR_DOMAIN_DEVELOPMENT_TAINT,
|
||||||
Attribute::DomainDisplayName => ATTR_DOMAIN_DISPLAY_NAME,
|
Attribute::DomainDisplayName => ATTR_DOMAIN_DISPLAY_NAME,
|
||||||
Attribute::DomainLdapBasedn => ATTR_DOMAIN_LDAP_BASEDN,
|
Attribute::DomainLdapBasedn => ATTR_DOMAIN_LDAP_BASEDN,
|
||||||
|
@ -464,6 +466,7 @@ impl Attribute {
|
||||||
ATTR_DISPLAYNAME => Attribute::DisplayName,
|
ATTR_DISPLAYNAME => Attribute::DisplayName,
|
||||||
ATTR_DN => Attribute::Dn,
|
ATTR_DN => Attribute::Dn,
|
||||||
ATTR_DOMAIN => Attribute::Domain,
|
ATTR_DOMAIN => Attribute::Domain,
|
||||||
|
ATTR_DOMAIN_ALLOW_EASTER_EGGS => Attribute::DomainAllowEasterEggs,
|
||||||
ATTR_DOMAIN_DISPLAY_NAME => Attribute::DomainDisplayName,
|
ATTR_DOMAIN_DISPLAY_NAME => Attribute::DomainDisplayName,
|
||||||
ATTR_DOMAIN_DEVELOPMENT_TAINT => Attribute::DomainDevelopmentTaint,
|
ATTR_DOMAIN_DEVELOPMENT_TAINT => Attribute::DomainDevelopmentTaint,
|
||||||
ATTR_DOMAIN_LDAP_BASEDN => Attribute::DomainLdapBasedn,
|
ATTR_DOMAIN_LDAP_BASEDN => Attribute::DomainLdapBasedn,
|
||||||
|
|
|
@ -89,6 +89,7 @@ pub const ATTR_DESCRIPTION: &str = "description";
|
||||||
pub const ATTR_DIRECTMEMBEROF: &str = "directmemberof";
|
pub const ATTR_DIRECTMEMBEROF: &str = "directmemberof";
|
||||||
pub const ATTR_DISPLAYNAME: &str = "displayname";
|
pub const ATTR_DISPLAYNAME: &str = "displayname";
|
||||||
pub const ATTR_DN: &str = "dn";
|
pub const ATTR_DN: &str = "dn";
|
||||||
|
pub const ATTR_DOMAIN_ALLOW_EASTER_EGGS: &str = "domain_allow_easter_eggs";
|
||||||
pub const ATTR_DOMAIN_DEVELOPMENT_TAINT: &str = "domain_development_taint";
|
pub const ATTR_DOMAIN_DEVELOPMENT_TAINT: &str = "domain_development_taint";
|
||||||
pub const ATTR_DOMAIN_DISPLAY_NAME: &str = "domain_display_name";
|
pub const ATTR_DOMAIN_DISPLAY_NAME: &str = "domain_display_name";
|
||||||
pub const ATTR_DOMAIN_LDAP_BASEDN: &str = "domain_ldap_basedn";
|
pub const ATTR_DOMAIN_LDAP_BASEDN: &str = "domain_ldap_basedn";
|
||||||
|
|
|
@ -1129,6 +1129,64 @@ lazy_static! {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
pub static ref IDM_ACP_DOMAIN_ADMIN_DL9: BuiltinAcp = BuiltinAcp {
|
||||||
|
classes: vec![
|
||||||
|
EntryClass::Object,
|
||||||
|
EntryClass::AccessControlProfile,
|
||||||
|
EntryClass::AccessControlModify,
|
||||||
|
EntryClass::AccessControlSearch
|
||||||
|
],
|
||||||
|
name: "idm_acp_domain_admin",
|
||||||
|
uuid: UUID_IDM_ACP_DOMAIN_ADMIN_V1,
|
||||||
|
description: "Builtin IDM Control for granting domain info administration locally",
|
||||||
|
receiver: BuiltinAcpReceiver::Group(vec![UUID_DOMAIN_ADMINS]),
|
||||||
|
target: BuiltinAcpTarget::Filter(ProtoFilter::And(vec![
|
||||||
|
ProtoFilter::Eq(
|
||||||
|
Attribute::Uuid.to_string(),
|
||||||
|
STR_UUID_DOMAIN_INFO.to_string()
|
||||||
|
),
|
||||||
|
FILTER_ANDNOT_TOMBSTONE_OR_RECYCLED.clone()
|
||||||
|
])),
|
||||||
|
search_attrs: vec![
|
||||||
|
Attribute::Class,
|
||||||
|
Attribute::Name,
|
||||||
|
Attribute::Uuid,
|
||||||
|
Attribute::DomainAllowEasterEggs,
|
||||||
|
Attribute::DomainDisplayName,
|
||||||
|
Attribute::DomainName,
|
||||||
|
Attribute::DomainLdapBasedn,
|
||||||
|
Attribute::DomainSsid,
|
||||||
|
Attribute::DomainUuid,
|
||||||
|
Attribute::KeyInternalData,
|
||||||
|
Attribute::LdapAllowUnixPwBind,
|
||||||
|
Attribute::Version,
|
||||||
|
Attribute::Image,
|
||||||
|
],
|
||||||
|
modify_removed_attrs: vec![
|
||||||
|
Attribute::DomainDisplayName,
|
||||||
|
Attribute::DomainSsid,
|
||||||
|
Attribute::DomainLdapBasedn,
|
||||||
|
Attribute::DomainAllowEasterEggs,
|
||||||
|
Attribute::LdapAllowUnixPwBind,
|
||||||
|
Attribute::KeyActionRevoke,
|
||||||
|
Attribute::KeyActionRotate,
|
||||||
|
Attribute::Image,
|
||||||
|
],
|
||||||
|
modify_present_attrs: vec![
|
||||||
|
Attribute::DomainDisplayName,
|
||||||
|
Attribute::DomainLdapBasedn,
|
||||||
|
Attribute::DomainSsid,
|
||||||
|
Attribute::DomainAllowEasterEggs,
|
||||||
|
Attribute::LdapAllowUnixPwBind,
|
||||||
|
Attribute::KeyActionRevoke,
|
||||||
|
Attribute::KeyActionRotate,
|
||||||
|
Attribute::Image,
|
||||||
|
],
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
pub static ref IDM_ACP_SYNC_ACCOUNT_MANAGE_V1: BuiltinAcp = BuiltinAcp {
|
pub static ref IDM_ACP_SYNC_ACCOUNT_MANAGE_V1: BuiltinAcp = BuiltinAcp {
|
||||||
classes: vec![
|
classes: vec![
|
||||||
|
|
|
@ -770,6 +770,14 @@ pub static ref SCHEMA_ATTR_DOMAIN_DEVELOPMENT_TAINT_DL7: SchemaAttribute = Schem
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub static ref SCHEMA_ATTR_DOMAIN_ALLOW_EASTER_EGGS_DL9: SchemaAttribute = SchemaAttribute {
|
||||||
|
uuid: UUID_SCHEMA_ATTR_DOMAIN_ALLOW_EASTER_EGGS,
|
||||||
|
name: Attribute::DomainAllowEasterEggs,
|
||||||
|
description: "A flag to enable easter eggs in the server that may not always be wanted by all users/deployments.".to_string(),
|
||||||
|
syntax: SyntaxType::Boolean,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
pub static ref SCHEMA_ATTR_REFERS_DL7: SchemaAttribute = SchemaAttribute {
|
pub static ref SCHEMA_ATTR_REFERS_DL7: SchemaAttribute = SchemaAttribute {
|
||||||
uuid: UUID_SCHEMA_ATTR_REFERS,
|
uuid: UUID_SCHEMA_ATTR_REFERS,
|
||||||
name: Attribute::Refers,
|
name: Attribute::Refers,
|
||||||
|
@ -1177,6 +1185,30 @@ pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL8: SchemaClass = SchemaClass {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub static ref SCHEMA_CLASS_DOMAIN_INFO_DL9: SchemaClass = SchemaClass {
|
||||||
|
uuid: UUID_SCHEMA_CLASS_DOMAIN_INFO,
|
||||||
|
name: EntryClass::DomainInfo.into(),
|
||||||
|
description: "Local domain information and configuration".to_string(),
|
||||||
|
|
||||||
|
systemmay: vec![
|
||||||
|
Attribute::DomainSsid,
|
||||||
|
Attribute::DomainLdapBasedn,
|
||||||
|
Attribute::LdapAllowUnixPwBind,
|
||||||
|
Attribute::Image,
|
||||||
|
Attribute::PatchLevel,
|
||||||
|
Attribute::DomainDevelopmentTaint,
|
||||||
|
Attribute::DomainAllowEasterEggs,
|
||||||
|
],
|
||||||
|
systemmust: vec![
|
||||||
|
Attribute::Name,
|
||||||
|
Attribute::DomainUuid,
|
||||||
|
Attribute::DomainName,
|
||||||
|
Attribute::DomainDisplayName,
|
||||||
|
Attribute::Version,
|
||||||
|
],
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
pub static ref SCHEMA_CLASS_POSIXGROUP: SchemaClass = SchemaClass {
|
pub static ref SCHEMA_CLASS_POSIXGROUP: SchemaClass = SchemaClass {
|
||||||
uuid: UUID_SCHEMA_CLASS_POSIXGROUP,
|
uuid: UUID_SCHEMA_CLASS_POSIXGROUP,
|
||||||
name: EntryClass::PosixGroup.into(),
|
name: EntryClass::PosixGroup.into(),
|
||||||
|
|
|
@ -321,6 +321,8 @@ pub const UUID_SCHEMA_ATTR_APPLICATION_PASSWORD: Uuid =
|
||||||
pub const UUID_SCHEMA_ATTR_CREATED_AT_CID: Uuid = uuid!("00000000-0000-0000-0000-ffff00000184");
|
pub const UUID_SCHEMA_ATTR_CREATED_AT_CID: Uuid = uuid!("00000000-0000-0000-0000-ffff00000184");
|
||||||
pub const UUID_SCHEMA_ATTR_ALLOW_PRIMARY_CRED_FALLBACK: Uuid =
|
pub const UUID_SCHEMA_ATTR_ALLOW_PRIMARY_CRED_FALLBACK: Uuid =
|
||||||
uuid!("00000000-0000-0000-0000-ffff00000185");
|
uuid!("00000000-0000-0000-0000-ffff00000185");
|
||||||
|
pub const UUID_SCHEMA_ATTR_DOMAIN_ALLOW_EASTER_EGGS: Uuid =
|
||||||
|
uuid!("00000000-0000-0000-0000-ffff00000186");
|
||||||
|
|
||||||
// System and domain infos
|
// System and domain infos
|
||||||
// I'd like to strongly criticise william of the past for making poor choices about these allocations.
|
// I'd like to strongly criticise william of the past for making poor choices about these allocations.
|
||||||
|
|
|
@ -647,7 +647,9 @@ impl QueryServerWriteTransaction<'_> {
|
||||||
// Now update schema
|
// Now update schema
|
||||||
let idm_schema_changes = [
|
let idm_schema_changes = [
|
||||||
SCHEMA_ATTR_OAUTH2_DEVICE_FLOW_ENABLE_DL9.clone().into(),
|
SCHEMA_ATTR_OAUTH2_DEVICE_FLOW_ENABLE_DL9.clone().into(),
|
||||||
|
SCHEMA_ATTR_DOMAIN_ALLOW_EASTER_EGGS_DL9.clone().into(),
|
||||||
SCHEMA_CLASS_OAUTH2_RS_DL9.clone().into(),
|
SCHEMA_CLASS_OAUTH2_RS_DL9.clone().into(),
|
||||||
|
SCHEMA_CLASS_DOMAIN_INFO_DL9.clone().into(),
|
||||||
];
|
];
|
||||||
|
|
||||||
idm_schema_changes
|
idm_schema_changes
|
||||||
|
@ -663,6 +665,7 @@ impl QueryServerWriteTransaction<'_> {
|
||||||
let idm_data = [
|
let idm_data = [
|
||||||
IDM_ACP_OAUTH2_MANAGE_DL9.clone().into(),
|
IDM_ACP_OAUTH2_MANAGE_DL9.clone().into(),
|
||||||
IDM_ACP_GROUP_MANAGE_DL9.clone().into(),
|
IDM_ACP_GROUP_MANAGE_DL9.clone().into(),
|
||||||
|
IDM_ACP_DOMAIN_ADMIN_DL9.clone().into(),
|
||||||
];
|
];
|
||||||
|
|
||||||
idm_data
|
idm_data
|
||||||
|
|
|
@ -79,6 +79,7 @@ pub struct DomainInfo {
|
||||||
pub(crate) d_patch_level: u32,
|
pub(crate) d_patch_level: u32,
|
||||||
pub(crate) d_devel_taint: bool,
|
pub(crate) d_devel_taint: bool,
|
||||||
pub(crate) d_ldap_allow_unix_pw_bind: bool,
|
pub(crate) d_ldap_allow_unix_pw_bind: bool,
|
||||||
|
pub(crate) d_allow_easter_eggs: bool,
|
||||||
// In future this should be image reference instead of the image itself.
|
// In future this should be image reference instead of the image itself.
|
||||||
d_image: Option<ImageValue>,
|
d_image: Option<ImageValue>,
|
||||||
}
|
}
|
||||||
|
@ -103,6 +104,10 @@ impl DomainInfo {
|
||||||
pub fn has_custom_image(&self) -> bool {
|
pub fn has_custom_image(&self) -> bool {
|
||||||
self.d_image.is_some()
|
self.d_image.is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn allow_easter_eggs(&self) -> bool {
|
||||||
|
self.d_allow_easter_eggs
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, Default)]
|
||||||
|
@ -1657,6 +1662,7 @@ impl QueryServer {
|
||||||
// Automatically derive our current taint mode based on the PRERELEASE setting.
|
// Automatically derive our current taint mode based on the PRERELEASE setting.
|
||||||
d_devel_taint: option_env!("KANIDM_PRE_RELEASE").is_some(),
|
d_devel_taint: option_env!("KANIDM_PRE_RELEASE").is_some(),
|
||||||
d_ldap_allow_unix_pw_bind: false,
|
d_ldap_allow_unix_pw_bind: false,
|
||||||
|
d_allow_easter_eggs: false,
|
||||||
d_image: None,
|
d_image: None,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -2284,6 +2290,11 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
||||||
.get_ava_single_bool(Attribute::DomainDevelopmentTaint)
|
.get_ava_single_bool(Attribute::DomainDevelopmentTaint)
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let domain_allow_easter_eggs = domain_info
|
||||||
|
.get_ava_single_bool(Attribute::DomainAllowEasterEggs)
|
||||||
|
// This defaults to false for release versions, and true in development
|
||||||
|
.unwrap_or(option_env!("KANIDM_PRE_RELEASE").is_some());
|
||||||
|
|
||||||
// We have to set the domain version here so that features which check for it
|
// We have to set the domain version here so that features which check for it
|
||||||
// will now see it's been increased. This also prevents recursion during reloads
|
// will now see it's been increased. This also prevents recursion during reloads
|
||||||
// inside of a domain migration.
|
// inside of a domain migration.
|
||||||
|
@ -2293,6 +2304,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
||||||
mut_d_info.d_vers = domain_info_version;
|
mut_d_info.d_vers = domain_info_version;
|
||||||
mut_d_info.d_patch_level = domain_info_patch_level;
|
mut_d_info.d_patch_level = domain_info_patch_level;
|
||||||
mut_d_info.d_devel_taint = domain_info_devel_taint;
|
mut_d_info.d_devel_taint = domain_info_devel_taint;
|
||||||
|
mut_d_info.d_allow_easter_eggs = domain_allow_easter_eggs;
|
||||||
|
|
||||||
// We must both be at the correct domain version *and* the correct patch level. If we are
|
// We must both be at the correct domain version *and* the correct patch level. If we are
|
||||||
// not, then we only proceed to migrate *if* our server boot phase is correct.
|
// not, then we only proceed to migrate *if* our server boot phase is correct.
|
||||||
|
|
|
@ -12,6 +12,7 @@ impl DomainOpt {
|
||||||
| DomainOpt::SetImage { copt, .. }
|
| DomainOpt::SetImage { copt, .. }
|
||||||
| DomainOpt::RemoveImage { copt }
|
| DomainOpt::RemoveImage { copt }
|
||||||
| DomainOpt::SetLdapAllowUnixPasswordBind { copt, .. }
|
| DomainOpt::SetLdapAllowUnixPasswordBind { copt, .. }
|
||||||
|
| DomainOpt::SetAllowEasterEggs { copt, .. }
|
||||||
| DomainOpt::RevokeKey { copt, .. }
|
| DomainOpt::RevokeKey { copt, .. }
|
||||||
| DomainOpt::Show(copt) => copt.debug,
|
| DomainOpt::Show(copt) => copt.debug,
|
||||||
}
|
}
|
||||||
|
@ -51,6 +52,19 @@ impl DomainOpt {
|
||||||
Err(e) => handle_client_error(e, copt.output_mode),
|
Err(e) => handle_client_error(e, copt.output_mode),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DomainOpt::SetAllowEasterEggs { copt, enable } => {
|
||||||
|
let client = copt.to_client(OpType::Write).await;
|
||||||
|
match client.idm_set_domain_allow_easter_eggs(*enable).await {
|
||||||
|
Ok(_) => {
|
||||||
|
if *enable {
|
||||||
|
println!("Success 🎉 🥚 🎉")
|
||||||
|
} else {
|
||||||
|
println!("Success")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => handle_client_error(e, copt.output_mode),
|
||||||
|
}
|
||||||
|
}
|
||||||
DomainOpt::Show(copt) => {
|
DomainOpt::Show(copt) => {
|
||||||
let client = copt.to_client(OpType::Read).await;
|
let client = copt.to_client(OpType::Read).await;
|
||||||
match client.idm_domain_get().await {
|
match client.idm_domain_get().await {
|
||||||
|
|
|
@ -1332,6 +1332,15 @@ pub enum DomainOpt {
|
||||||
#[clap(name = "allow", action = clap::ArgAction::Set)]
|
#[clap(name = "allow", action = clap::ArgAction::Set)]
|
||||||
enable: bool,
|
enable: bool,
|
||||||
},
|
},
|
||||||
|
/// Enable or disable easter eggs in the server. This includes seasonal icons, kanidm
|
||||||
|
/// birthday surprises and other fun components. Defaults to false for production releases
|
||||||
|
/// and true in development builds.
|
||||||
|
SetAllowEasterEggs {
|
||||||
|
#[clap(flatten)]
|
||||||
|
copt: CommonOpt,
|
||||||
|
#[clap(name = "allow", action = clap::ArgAction::Set)]
|
||||||
|
enable: bool,
|
||||||
|
},
|
||||||
#[clap(name = "show")]
|
#[clap(name = "show")]
|
||||||
/// Show information about this system's domain
|
/// Show information about this system's domain
|
||||||
Show(CommonOpt),
|
Show(CommonOpt),
|
||||||
|
|
Loading…
Reference in a new issue