mirror of
https://github.com/kanidm/kanidm.git
synced 2025-02-23 20:47:01 +01:00
Add support for storing security token key in domain config (#581)
This commit is contained in:
parent
dbb57e9a7b
commit
573e346476
16
Cargo.lock
generated
16
Cargo.lock
generated
|
@ -499,9 +499,9 @@ checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9"
|
|||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "0.2.16"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90682c8d613ad3373e66de8c6411e0ae2ab2571e879d2efbf73558cc66f21279"
|
||||
checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"memchr",
|
||||
|
@ -511,9 +511,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.7.0"
|
||||
version = "3.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631"
|
||||
checksum = "d9df67f7bf9ef8498769f994239c45613ef0c5899415fb58e9add412d2c1a538"
|
||||
|
||||
[[package]]
|
||||
name = "bundy"
|
||||
|
@ -3640,9 +3640,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6"
|
|||
|
||||
[[package]]
|
||||
name = "tracing"
|
||||
version = "0.1.27"
|
||||
version = "0.1.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2ba9ab62b7d6497a8638dfda5e5c4fb3b2d5a7fca4118f2b96151c8ef1a437e"
|
||||
checksum = "84f96e095c0c82419687c20ddf5cb3eadb61f4e1405923c9dc8e53a1adacbda8"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"pin-project-lite 0.2.7",
|
||||
|
@ -3693,9 +3693,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tracing-subscriber"
|
||||
version = "0.2.23"
|
||||
version = "0.2.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56c42e73a9d277d4d2b6a88389a137ccf3c58599660b17e8f5fc39305e490669"
|
||||
checksum = "fdd0568dbfe3baf7048b7908d2b32bca0d81cd56bec6d2a8f894b01d74f86be3"
|
||||
dependencies = [
|
||||
"ansi_term",
|
||||
"chrono",
|
||||
|
|
10
Makefile
10
Makefile
|
@ -20,6 +20,16 @@ buildx/kanidmd/simd:
|
|||
$(ARGS) .
|
||||
@docker buildx imagetools $(EXT_OPTS) inspect $(IMAGE_BASE)/server:$(IMAGE_VERSION)
|
||||
|
||||
buildx/kanidmd/x86_64_v3: ## build multiarch server images
|
||||
buildx/kanidmd/x86_64_v3:
|
||||
@docker buildx build $(EXT_OPTS) --pull --push --platform "linux/amd64" \
|
||||
--allow security.insecure \
|
||||
-f kanidmd/Dockerfile -t $(IMAGE_BASE)/server:x86_64_$(IMAGE_VERSION) \
|
||||
--build-arg "KANIDM_BUILD_PROFILE=container_x86_64_v3" \
|
||||
--build-arg "KANIDM_FEATURES=" \
|
||||
$(ARGS) .
|
||||
@docker buildx imagetools $(EXT_OPTS) inspect $(IMAGE_BASE)/server:$(IMAGE_VERSION)
|
||||
|
||||
buildx/kanidmd: ## build multiarch server images
|
||||
buildx/kanidmd:
|
||||
@docker buildx build $(EXT_OPTS) --pull --push --platform $(IMAGE_ARCH) \
|
||||
|
|
|
@ -1318,18 +1318,13 @@ impl KanidmAsyncClient {
|
|||
}
|
||||
|
||||
// ==== domain_info (aka domain)
|
||||
pub async fn idm_domain_list(&self) -> Result<Vec<Entry>, ClientError> {
|
||||
self.perform_get_request("/v1/domain").await
|
||||
pub async fn idm_domain_get(&self) -> Result<Entry, ClientError> {
|
||||
let r: Result<Vec<Entry>, ClientError> = self.perform_get_request("/v1/domain").await;
|
||||
r.and_then(|mut v| v.pop().ok_or(ClientError::EmptyResponse))
|
||||
}
|
||||
|
||||
pub async fn idm_domain_get(&self, id: &str) -> Result<Entry, ClientError> {
|
||||
self.perform_get_request(format!("/v1/domain/{}", id).as_str())
|
||||
.await
|
||||
}
|
||||
|
||||
// pub fn idm_domain_get_attr
|
||||
pub async fn idm_domain_get_ssid(&self, id: &str) -> Result<String, ClientError> {
|
||||
self.perform_get_request(format!("/v1/domain/{}/_attr/domain_ssid", id).as_str())
|
||||
pub async fn idm_domain_get_ssid(&self) -> Result<String, ClientError> {
|
||||
self.perform_get_request("/v1/domain/_attr/domain_ssid")
|
||||
.await
|
||||
.and_then(|mut r: Vec<String>|
|
||||
// Get the first result
|
||||
|
@ -1339,13 +1334,14 @@ impl KanidmAsyncClient {
|
|||
))
|
||||
}
|
||||
|
||||
// pub fn idm_domain_put_attr
|
||||
pub async fn idm_domain_set_ssid(&self, id: &str, ssid: &str) -> Result<(), ClientError> {
|
||||
self.perform_put_request(
|
||||
format!("/v1/domain/{}/_attr/domain_ssid", id).as_str(),
|
||||
vec![ssid.to_string()],
|
||||
)
|
||||
.await
|
||||
pub async fn idm_domain_set_ssid(&self, ssid: &str) -> Result<(), ClientError> {
|
||||
self.perform_put_request("/v1/domain/_attr/domain_ssid", vec![ssid.to_string()])
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn idm_domain_reset_token_key(&self) -> Result<(), ClientError> {
|
||||
self.perform_delete_request("/v1/domain/_attr/domain_token_key")
|
||||
.await
|
||||
}
|
||||
|
||||
// ==== schema
|
||||
|
|
|
@ -846,22 +846,22 @@ impl KanidmClient {
|
|||
}
|
||||
|
||||
// ==== domain_info (aka domain)
|
||||
pub fn idm_domain_list(&self) -> Result<Vec<Entry>, ClientError> {
|
||||
tokio_block_on(self.asclient.idm_domain_list())
|
||||
}
|
||||
|
||||
pub fn idm_domain_get(&self, id: &str) -> Result<Entry, ClientError> {
|
||||
tokio_block_on(self.asclient.idm_domain_get(id))
|
||||
pub fn idm_domain_get(&self) -> Result<Entry, ClientError> {
|
||||
tokio_block_on(self.asclient.idm_domain_get())
|
||||
}
|
||||
|
||||
// pub fn idm_domain_get_attr
|
||||
pub fn idm_domain_get_ssid(&self, id: &str) -> Result<String, ClientError> {
|
||||
tokio_block_on(self.asclient.idm_domain_get_ssid(id))
|
||||
pub fn idm_domain_get_ssid(&self) -> Result<String, ClientError> {
|
||||
tokio_block_on(self.asclient.idm_domain_get_ssid())
|
||||
}
|
||||
|
||||
// pub fn idm_domain_put_attr
|
||||
pub fn idm_domain_set_ssid(&self, id: &str, ssid: &str) -> Result<(), ClientError> {
|
||||
tokio_block_on(self.asclient.idm_domain_set_ssid(id, ssid))
|
||||
pub fn idm_domain_set_ssid(&self, ssid: &str) -> Result<(), ClientError> {
|
||||
tokio_block_on(self.asclient.idm_domain_set_ssid(ssid))
|
||||
}
|
||||
|
||||
pub fn idm_domain_reset_token_key(&self) -> Result<(), ClientError> {
|
||||
tokio_block_on(self.asclient.idm_domain_reset_token_key())
|
||||
}
|
||||
|
||||
// ==== schema
|
||||
|
|
|
@ -505,19 +505,12 @@ fn test_server_rest_domain_lifecycle() {
|
|||
let res = rsclient.auth_simple_password("admin", ADMIN_TEST_PASSWORD);
|
||||
assert!(res.is_ok());
|
||||
|
||||
let mut dlist = rsclient.idm_domain_list().unwrap();
|
||||
assert!(dlist.len() == 1);
|
||||
|
||||
let dlocal = rsclient.idm_domain_get("domain_local").unwrap();
|
||||
// There should be one, and it's the domain_local
|
||||
assert!(dlist.pop().unwrap().attrs == dlocal.attrs);
|
||||
let _dlocal = rsclient.idm_domain_get().unwrap();
|
||||
|
||||
// Change the ssid
|
||||
rsclient
|
||||
.idm_domain_set_ssid("domain_local", "new_ssid")
|
||||
.unwrap();
|
||||
rsclient.idm_domain_set_ssid("new_ssid").unwrap();
|
||||
// check get and get the ssid and domain info
|
||||
let nssid = rsclient.idm_domain_get_ssid("domain_local").unwrap();
|
||||
let nssid = rsclient.idm_domain_get_ssid().unwrap();
|
||||
assert!(nssid == "new_ssid");
|
||||
});
|
||||
}
|
||||
|
|
28
kanidm_tools/src/cli/domain.rs
Normal file
28
kanidm_tools/src/cli/domain.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
use crate::DomainOpt;
|
||||
|
||||
impl DomainOpt {
|
||||
pub fn debug(&self) -> bool {
|
||||
match self {
|
||||
DomainOpt::Show(copt) | DomainOpt::ResetTokenKey(copt) => copt.debug,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exec(&self) {
|
||||
match self {
|
||||
DomainOpt::Show(copt) => {
|
||||
let client = copt.to_client();
|
||||
match client.idm_domain_get() {
|
||||
Ok(e) => println!("{}", e),
|
||||
Err(e) => eprintln!("Error -> {:?}", e),
|
||||
}
|
||||
}
|
||||
DomainOpt::ResetTokenKey(copt) => {
|
||||
let client = copt.to_client();
|
||||
match client.idm_domain_reset_token_key() {
|
||||
Ok(_) => println!("Success"),
|
||||
Err(e) => eprintln!("Error -> {:?}", e),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -17,6 +17,7 @@ include!("../opt/kanidm.rs");
|
|||
|
||||
pub mod account;
|
||||
pub mod common;
|
||||
pub mod domain;
|
||||
pub mod group;
|
||||
pub mod oauth2;
|
||||
pub mod raw;
|
||||
|
@ -76,12 +77,14 @@ impl SystemOpt {
|
|||
pub fn debug(&self) -> bool {
|
||||
match self {
|
||||
SystemOpt::Oauth2(oopt) => oopt.debug(),
|
||||
SystemOpt::Domain(dopt) => dopt.debug(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn exec(&self) {
|
||||
match self {
|
||||
SystemOpt::Oauth2(oopt) => oopt.exec(),
|
||||
SystemOpt::Domain(dopt) => dopt.exec(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -379,11 +379,25 @@ pub enum Oauth2Opt {
|
|||
Delete(Named),
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
pub enum DomainOpt {
|
||||
#[structopt(name = "show")]
|
||||
/// Show information about this systems domain
|
||||
Show(CommonOpt),
|
||||
#[structopt(name = "reset_token_key")]
|
||||
/// Reset this domain token signing key. This will cause all user sessions to be
|
||||
/// invalidated (logged out).
|
||||
ResetTokenKey(CommonOpt),
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
pub enum SystemOpt {
|
||||
#[structopt(name = "oauth2")]
|
||||
/// Configure and display oauth2/oidc resource server configuration
|
||||
Oauth2(Oauth2Opt),
|
||||
#[structopt(name = "domain")]
|
||||
/// Configure and display domain configuration
|
||||
Domain(DomainOpt),
|
||||
}
|
||||
|
||||
#[derive(Debug, StructOpt)]
|
||||
|
|
|
@ -2,7 +2,8 @@ ARG BASE_IMAGE=opensuse/tumbleweed:latest
|
|||
FROM ${BASE_IMAGE} AS builder
|
||||
LABEL mantainer william@blackhats.net.au
|
||||
|
||||
RUN zypper -vv ref && \
|
||||
RUN zypper ar obs://devel:languages:rust devel:languages:rust && \
|
||||
zypper --gpg-auto-import-keys ref --force && \
|
||||
zypper dup -y && \
|
||||
zypper install -y \
|
||||
cargo \
|
||||
|
|
|
@ -826,10 +826,12 @@ pub const JSON_IDM_ACP_DOMAIN_ADMIN_PRIV_V1: &str = r#"{
|
|||
"uuid",
|
||||
"domain_name",
|
||||
"domain_ssid",
|
||||
"domain_uuid"
|
||||
"domain_uuid",
|
||||
"domain_token_key"
|
||||
],
|
||||
"acp_modify_removedattr": [
|
||||
"domain_ssid"
|
||||
"domain_ssid",
|
||||
"domain_token_key"
|
||||
],
|
||||
"acp_modify_presentattr": [
|
||||
"domain_ssid"
|
||||
|
|
|
@ -346,7 +346,7 @@ pub const JSON_SYSTEM_INFO_V1: &str = r#"{
|
|||
"class": ["object", "system_info", "system"],
|
||||
"uuid": ["00000000-0000-0000-0000-ffffff000001"],
|
||||
"description": ["System (local) info and metadata object."],
|
||||
"version": ["3"]
|
||||
"version": ["4"]
|
||||
}
|
||||
}"#;
|
||||
|
||||
|
|
|
@ -274,6 +274,34 @@ pub const JSON_SCHEMA_ATTR_DOMAIN_SSID: &str = r#"{
|
|||
]
|
||||
}
|
||||
}"#;
|
||||
pub const JSON_SCHEMA_ATTR_DOMAIN_TOKEN_KEY: &str = r#"{
|
||||
"attrs": {
|
||||
"class": [
|
||||
"object",
|
||||
"system",
|
||||
"attributetype"
|
||||
],
|
||||
"description": [
|
||||
"The domains token signing key, which is shared between IDM servers."
|
||||
],
|
||||
"index": [],
|
||||
"unique": [
|
||||
"false"
|
||||
],
|
||||
"multivalue": [
|
||||
"false"
|
||||
],
|
||||
"attributename": [
|
||||
"domain_token_key"
|
||||
],
|
||||
"syntax": [
|
||||
"SECRET_UTF8STRING"
|
||||
],
|
||||
"uuid": [
|
||||
"00000000-0000-0000-0000-ffff00000088"
|
||||
]
|
||||
}
|
||||
}"#;
|
||||
|
||||
pub const JSON_SCHEMA_ATTR_GIDNUMBER: &str = r#"{
|
||||
"attrs": {
|
||||
|
@ -748,7 +776,8 @@ pub const JSON_SCHEMA_CLASS_DOMAIN_INFO: &str = r#"
|
|||
"systemmust": [
|
||||
"name",
|
||||
"domain_uuid",
|
||||
"domain_name"
|
||||
"domain_name",
|
||||
"domain_token_key"
|
||||
],
|
||||
"uuid": [
|
||||
"00000000-0000-0000-0000-ffff00000052"
|
||||
|
|
|
@ -142,8 +142,8 @@ pub const _STR_UUID_SCHEMA_ATTR_OAUTH2_RS_BASIC_TOKEN_KEY: &str =
|
|||
"00000000-0000-0000-0000-ffff00000084";
|
||||
pub const STR_UUID_SCHEMA_CLASS_OAUTH2_RS: &str = "00000000-0000-0000-0000-ffff00000085";
|
||||
pub const STR_UUID_SCHEMA_CLASS_OAUTH2_RS_BASIC: &str = "00000000-0000-0000-0000-ffff00000086";
|
||||
|
||||
pub const STR_UUID_SCHEMA_ATTR_CN: &str = "00000000-0000-0000-0000-ffff00000087";
|
||||
pub const STR_UUID_SCHEMA_ATTR_DOMAIN_TOKEN_KEY: &str = "00000000-0000-0000-0000-ffff00000088";
|
||||
|
||||
// System and domain infos
|
||||
// I'd like to strongly criticise william of the past for making poor choices about these allocations.
|
||||
|
@ -321,4 +321,6 @@ lazy_static! {
|
|||
Uuid::parse_str(STR_UUID_SCHEMA_CLASS_OAUTH2_RS).unwrap();
|
||||
pub static ref UUID_SCHEMA_CLASS_OAUTH2_RS_BASIC: Uuid =
|
||||
Uuid::parse_str(STR_UUID_SCHEMA_CLASS_OAUTH2_RS_BASIC).unwrap();
|
||||
pub static ref UUID_SCHEMA_ATTR_DOMAIN_TOKEN_KEY: Uuid =
|
||||
Uuid::parse_str(STR_UUID_SCHEMA_ATTR_DOMAIN_TOKEN_KEY).unwrap();
|
||||
}
|
||||
|
|
|
@ -553,11 +553,11 @@ pub fn create_https_server(
|
|||
|
||||
let mut domain_route = appserver.at("/v1/domain");
|
||||
domain_route.at("/").get(domain_get);
|
||||
domain_route.at("/:id").get(domain_id_get);
|
||||
domain_route
|
||||
.at("/:id/_attr/:attr")
|
||||
.get(domain_id_get_attr)
|
||||
.put(domain_id_put_attr);
|
||||
.at("/_attr/:attr")
|
||||
.get(domain_get_attr)
|
||||
.put(domain_put_attr)
|
||||
.delete(domain_delete_attr);
|
||||
|
||||
let mut recycle_route = appserver.at("/v1/recycle_bin");
|
||||
recycle_route.at("/").get(recycle_bin_get);
|
||||
|
|
|
@ -115,15 +115,15 @@ pub async fn json_rest_event_delete_id(
|
|||
to_tide_response(res, hvalue)
|
||||
}
|
||||
|
||||
pub async fn json_rest_event_get_id_attr(
|
||||
pub async fn json_rest_event_get_attr(
|
||||
req: tide::Request<AppState>,
|
||||
id: &str,
|
||||
filter: Filter<FilterInvalid>,
|
||||
) -> tide::Result {
|
||||
let id = req.get_url_param("id")?;
|
||||
let attr = req.get_url_param("attr")?;
|
||||
let uat = req.get_current_uat();
|
||||
let filter = Filter::join_parts_and(filter, filter_all!(f_id(id)));
|
||||
|
||||
let filter = Filter::join_parts_and(filter, filter_all!(f_id(id.as_str())));
|
||||
let (eventid, hvalue) = req.new_eventid();
|
||||
|
||||
let attrs = Some(vec![attr.clone()]);
|
||||
|
@ -137,6 +137,14 @@ pub async fn json_rest_event_get_id_attr(
|
|||
to_tide_response(res, hvalue)
|
||||
}
|
||||
|
||||
pub async fn json_rest_event_get_id_attr(
|
||||
req: tide::Request<AppState>,
|
||||
filter: Filter<FilterInvalid>,
|
||||
) -> tide::Result {
|
||||
let id = req.get_url_param("id")?;
|
||||
json_rest_event_get_attr(req, id.as_str(), filter).await
|
||||
}
|
||||
|
||||
pub async fn json_rest_event_post(
|
||||
mut req: tide::Request<AppState>,
|
||||
classes: Vec<String>,
|
||||
|
@ -170,12 +178,12 @@ pub async fn json_rest_event_post_id_attr(
|
|||
to_tide_response(res, hvalue)
|
||||
}
|
||||
|
||||
pub async fn json_rest_event_put_id_attr(
|
||||
pub async fn json_rest_event_put_attr(
|
||||
mut req: tide::Request<AppState>,
|
||||
uuid_or_name: String,
|
||||
filter: Filter<FilterInvalid>,
|
||||
) -> tide::Result {
|
||||
let uat = req.get_current_uat();
|
||||
let uuid_or_name = req.get_url_param("id")?;
|
||||
let attr = req.get_url_param("attr")?;
|
||||
let values: Vec<String> = req.body_json().await?;
|
||||
|
||||
|
@ -188,14 +196,31 @@ pub async fn json_rest_event_put_id_attr(
|
|||
to_tide_response(res, hvalue)
|
||||
}
|
||||
|
||||
pub async fn json_rest_event_put_id_attr(
|
||||
req: tide::Request<AppState>,
|
||||
filter: Filter<FilterInvalid>,
|
||||
) -> tide::Result {
|
||||
let uuid_or_name = req.get_url_param("id")?;
|
||||
json_rest_event_put_attr(req, uuid_or_name, filter).await
|
||||
}
|
||||
|
||||
pub async fn json_rest_event_delete_id_attr(
|
||||
req: tide::Request<AppState>,
|
||||
filter: Filter<FilterInvalid>,
|
||||
attr: String,
|
||||
) -> tide::Result {
|
||||
let uuid_or_name = req.get_url_param("id")?;
|
||||
json_rest_event_delete_attr(req, filter, uuid_or_name, attr).await
|
||||
}
|
||||
|
||||
pub async fn json_rest_event_delete_attr(
|
||||
mut req: tide::Request<AppState>,
|
||||
filter: Filter<FilterInvalid>,
|
||||
uuid_or_name: String,
|
||||
// Seperate for account_delete_id_radius
|
||||
attr: String,
|
||||
) -> tide::Result {
|
||||
let uat = req.get_current_uat();
|
||||
let uuid_or_name = req.get_url_param("id")?;
|
||||
let (eventid, hvalue) = req.new_eventid();
|
||||
|
||||
// TODO #211: Attempt to get an option Vec<String> here?
|
||||
|
@ -672,26 +697,24 @@ pub async fn group_get_id_unix_token(req: tide::Request<AppState>) -> tide::Resu
|
|||
}
|
||||
|
||||
pub async fn domain_get(req: tide::Request<AppState>) -> tide::Result {
|
||||
let filter = filter_all!(f_eq("class", PartialValue::new_class("domain_info")));
|
||||
let filter = filter_all!(f_eq("uuid", PartialValue::new_uuidr(&UUID_DOMAIN_INFO)));
|
||||
json_rest_event_get(req, filter, None).await
|
||||
}
|
||||
|
||||
pub async fn domain_id_get(req: tide::Request<AppState>) -> tide::Result {
|
||||
pub async fn domain_get_attr(req: tide::Request<AppState>) -> tide::Result {
|
||||
let filter = filter_all!(f_eq("class", PartialValue::new_class("domain_info")));
|
||||
json_rest_event_get_id(req, filter, None).await
|
||||
json_rest_event_get_attr(req, STR_UUID_DOMAIN_INFO, filter).await
|
||||
}
|
||||
|
||||
pub async fn domain_id_get_attr(
|
||||
req: tide::Request<AppState>,
|
||||
// (path, session, state): (Path<(String, String)>, Session, Data<AppState>),
|
||||
) -> tide::Result {
|
||||
pub async fn domain_put_attr(req: tide::Request<AppState>) -> tide::Result {
|
||||
let filter = filter_all!(f_eq("class", PartialValue::new_class("domain_info")));
|
||||
json_rest_event_get_id_attr(req, filter).await
|
||||
json_rest_event_put_attr(req, STR_UUID_DOMAIN_INFO.to_string(), filter).await
|
||||
}
|
||||
|
||||
pub async fn domain_id_put_attr(req: tide::Request<AppState>) -> tide::Result {
|
||||
pub async fn domain_delete_attr(req: tide::Request<AppState>) -> tide::Result {
|
||||
let filter = filter_all!(f_eq("class", PartialValue::new_class("domain_info")));
|
||||
json_rest_event_put_id_attr(req, filter).await
|
||||
let attr = req.get_url_param("attr")?;
|
||||
json_rest_event_delete_attr(req, filter, STR_UUID_DOMAIN_INFO.to_string(), attr).await
|
||||
}
|
||||
|
||||
pub async fn recycle_bin_get(req: tide::Request<AppState>) -> tide::Result {
|
||||
|
|
|
@ -459,11 +459,9 @@ pub fn recover_account_core(config: &Configuration, name: &str) {
|
|||
|
||||
// Run the password change.
|
||||
let mut idms_prox_write = task::block_on(idms.proxy_write_async(duration_from_epoch_now()));
|
||||
match idms_prox_write.recover_account(name, None) {
|
||||
let new_pw = match idms_prox_write.recover_account(name, None) {
|
||||
Ok(new_pw) => match idms_prox_write.commit() {
|
||||
Ok(()) => {
|
||||
eprintln!("Password reset to -> {}", new_pw);
|
||||
}
|
||||
Ok(_) => new_pw,
|
||||
Err(e) => {
|
||||
error!("A critical error during commit occured {:?}", e);
|
||||
std::process::exit(1);
|
||||
|
@ -476,6 +474,7 @@ pub fn recover_account_core(config: &Configuration, name: &str) {
|
|||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
eprintln!("Success - password reset to -> {}", new_pw);
|
||||
}
|
||||
|
||||
pub async fn create_server_core(config: Configuration) -> Result<(), ()> {
|
||||
|
|
|
@ -428,6 +428,10 @@ impl Entry<EntryInit, EntryNew> {
|
|||
}).collect();
|
||||
vs.unwrap()
|
||||
}
|
||||
"domain_token_key" => {
|
||||
let vs: Option<ValueSet> = vs.into_iter().map(|v| Value::new_secret_str(&v)).collect();
|
||||
vs.unwrap()
|
||||
}
|
||||
ia => {
|
||||
warn!("WARNING: Allowing invalid attribute {} to be interpretted as UTF8 string. YOU MAY ENCOUNTER ODD BEHAVIOUR!!!", ia);
|
||||
let vs: Option<ValueSet> = vs.into_iter().map(|v| Value::new_utf8(v)).collect();
|
||||
|
|
|
@ -158,10 +158,11 @@ impl IdmServer {
|
|||
let (async_tx, async_rx) = unbounded();
|
||||
|
||||
// Get the domain name, as the relying party id.
|
||||
let (rp_id, pw_badlist_set, oauth2rs_set) = {
|
||||
let (rp_id, token_key, pw_badlist_set, oauth2rs_set) = {
|
||||
let qs_read = task::block_on(qs.read_async());
|
||||
(
|
||||
qs_read.get_domain_name()?,
|
||||
qs_read.get_domain_token_key()?,
|
||||
qs_read.get_password_badlist()?,
|
||||
// Add a read/reload of all oauth2 configurations.
|
||||
qs_read.get_oauth2rs_set()?,
|
||||
|
@ -198,12 +199,10 @@ impl IdmServer {
|
|||
});
|
||||
|
||||
// Setup our auth token signing key.
|
||||
let bundy_handle = HS512::generate_key()
|
||||
.and_then(|bundy_key| HS512::from_str(&bundy_key))
|
||||
.map_err(|e| {
|
||||
admin_error!("Failed to generate uat_bundy_hmac - {:?}", e);
|
||||
OperationError::InvalidState
|
||||
})?;
|
||||
let bundy_handle = HS512::from_str(&token_key).map_err(|e| {
|
||||
admin_error!("Failed to generate uat_bundy_hmac - {:?}", e);
|
||||
OperationError::InvalidState
|
||||
})?;
|
||||
let uat_bundy_hmac = Arc::new(CowCell::new(bundy_handle));
|
||||
|
||||
let oauth2rs = Oauth2ResourceServers::try_from(oauth2rs_set).map_err(|e| {
|
||||
|
@ -1943,15 +1942,29 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
|
|||
.get_oauth2rs_set()
|
||||
.and_then(|oauth2rs_set| self.oauth2rs.reload(oauth2rs_set))?;
|
||||
}
|
||||
if self.qs_write.get_changed_domain() {
|
||||
// reload token_key?
|
||||
self.qs_write
|
||||
.get_domain_token_key()
|
||||
.and_then(|token_key| {
|
||||
HS512::from_str(&token_key).map_err(|e| {
|
||||
admin_error!("Failed to generate uat_bundy_hmac - {:?}", e);
|
||||
OperationError::InvalidState
|
||||
})
|
||||
})
|
||||
.map(|new_handle| {
|
||||
*self.uat_bundy_hmac = new_handle;
|
||||
})?;
|
||||
}
|
||||
// Commit everything.
|
||||
self.oauth2rs.commit();
|
||||
self.uat_bundy_hmac.commit();
|
||||
self.pw_badlist_cache.commit();
|
||||
self.mfareg_sessions.commit();
|
||||
self.qs_write.commit()
|
||||
})
|
||||
}
|
||||
|
||||
// TODO: tracing
|
||||
fn reload_password_badlist(&mut self) -> Result<(), OperationError> {
|
||||
match self.qs_write.get_password_badlist() {
|
||||
Ok(badlist_entry) => {
|
||||
|
@ -3804,4 +3817,44 @@ mod tests {
|
|||
assert!(!ident.has_claim("authclass_single"));
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_idm_bundy_uat_token_key_reload() {
|
||||
run_idm_test!(
|
||||
|qs: &QueryServer, idms: &IdmServer, _idms_delayed: &mut IdmServerDelayed| {
|
||||
let ct = Duration::from_secs(TEST_CURRENT_TIME);
|
||||
|
||||
init_admin_w_password(qs, TEST_PASSWORD).expect("Failed to setup admin account");
|
||||
let token = check_admin_password(idms, TEST_PASSWORD);
|
||||
let idms_prox_read = idms.proxy_read();
|
||||
|
||||
// Check it's valid.
|
||||
idms_prox_read
|
||||
.validate_and_parse_uat(Some(token.as_str()), ct)
|
||||
.expect("Failed to validate");
|
||||
|
||||
drop(idms_prox_read);
|
||||
|
||||
// Now reset the token_key - we can cheat and push this
|
||||
// through the migrate 3 to 4 code.
|
||||
let idms_prox_write = idms.proxy_write(ct.clone());
|
||||
idms_prox_write
|
||||
.qs_write
|
||||
.migrate_3_to_4()
|
||||
.expect("Failed to reset domain token key");
|
||||
assert!(idms_prox_write.commit().is_ok());
|
||||
// Check the old token is invalid, due to reload.
|
||||
let new_token = check_admin_password(idms, TEST_PASSWORD);
|
||||
|
||||
let idms_prox_read = idms.proxy_read();
|
||||
assert!(idms_prox_read
|
||||
.validate_and_parse_uat(Some(token.as_str()), ct)
|
||||
.is_err());
|
||||
// A new token will work due to the matching key.
|
||||
idms_prox_read
|
||||
.validate_and_parse_uat(Some(new_token.as_str()), ct)
|
||||
.expect("Failed to validate");
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -248,7 +248,7 @@ macro_rules! run_create_test {
|
|||
{
|
||||
let qs_write = qs.write(duration_from_epoch_now());
|
||||
let r = qs_write.create(&ce);
|
||||
debug!("test result: {:?}", r);
|
||||
trace!("test result: {:?}", r);
|
||||
assert!(r == $expect);
|
||||
$check(&qs_write);
|
||||
match r {
|
||||
|
@ -261,9 +261,9 @@ macro_rules! run_create_test {
|
|||
}
|
||||
}
|
||||
// Make sure there are no errors.
|
||||
debug!("starting verification");
|
||||
trace!("starting verification");
|
||||
let ver = qs.verify();
|
||||
debug!("verification -> {:?}", ver);
|
||||
trace!("verification -> {:?}", ver);
|
||||
assert!(ver.len() == 0);
|
||||
});
|
||||
}};
|
||||
|
@ -303,7 +303,7 @@ macro_rules! run_modify_test {
|
|||
spanned!("plugins::macros::run_modify_test -> post_test check", {
|
||||
$check(&qs_write)
|
||||
});
|
||||
debug!("test result: {:?}", r);
|
||||
trace!("test result: {:?}", r);
|
||||
assert!(r == $expect);
|
||||
match r {
|
||||
Ok(_) => {
|
||||
|
@ -315,9 +315,9 @@ macro_rules! run_modify_test {
|
|||
}
|
||||
}
|
||||
// Make sure there are no errors.
|
||||
debug!("starting verification");
|
||||
trace!("starting verification");
|
||||
let ver = qs.verify();
|
||||
debug!("verification -> {:?}", ver);
|
||||
trace!("verification -> {:?}", ver);
|
||||
assert!(ver.len() == 0);
|
||||
});
|
||||
}};
|
||||
|
@ -352,7 +352,7 @@ macro_rules! run_delete_test {
|
|||
{
|
||||
let qs_write = qs.write(duration_from_epoch_now());
|
||||
let r = qs_write.delete(&de);
|
||||
debug!("test result: {:?}", r);
|
||||
trace!("test result: {:?}", r);
|
||||
$check(&qs_write);
|
||||
assert!(r == $expect);
|
||||
match r {
|
||||
|
@ -365,9 +365,9 @@ macro_rules! run_delete_test {
|
|||
}
|
||||
}
|
||||
// Make sure there are no errors.
|
||||
debug!("starting verification");
|
||||
trace!("starting verification");
|
||||
let ver = qs.verify();
|
||||
debug!("verification -> {:?}", ver);
|
||||
trace!("verification -> {:?}", ver);
|
||||
assert!(ver.len() == 0);
|
||||
});
|
||||
}};
|
||||
|
|
|
@ -6,8 +6,9 @@
|
|||
// relationships.
|
||||
use crate::plugins::Plugin;
|
||||
|
||||
use crate::event::CreateEvent;
|
||||
use crate::event::{CreateEvent, ModifyEvent};
|
||||
use crate::prelude::*;
|
||||
use bundy::hs512::HS512;
|
||||
use kanidm_proto::v1::OperationError;
|
||||
use tracing::trace;
|
||||
|
||||
|
@ -28,8 +29,7 @@ impl Plugin for Domain {
|
|||
cand: &mut Vec<Entry<EntryInvalid, EntryNew>>,
|
||||
_ce: &CreateEvent,
|
||||
) -> Result<(), OperationError> {
|
||||
trace!("Entering plugin_domain pre_create_transform");
|
||||
cand.iter_mut().for_each(|e| {
|
||||
cand.iter_mut().try_for_each(|e| {
|
||||
if e.attribute_equality("class", &PVCLASS_DOMAIN_INFO)
|
||||
&& e.attribute_equality("uuid", &PVUUID_DOMAIN_INFO)
|
||||
{
|
||||
|
@ -43,11 +43,49 @@ impl Plugin for Domain {
|
|||
e.set_ava("domain_name", btreeset![n]);
|
||||
trace!("plugin_domain: Applying domain_name transform");
|
||||
}
|
||||
if !e.attribute_pres("domain_token_key") {
|
||||
let k = HS512::generate_key()
|
||||
.map(|k| Value::new_secret_str(&k))
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Failed to generate domain_token_key");
|
||||
OperationError::InvalidState
|
||||
})?;
|
||||
e.set_ava("domain_token_key", btreeset![k]);
|
||||
trace!("plugin_domain: Applying domain_token_key transform");
|
||||
}
|
||||
trace!(?e);
|
||||
Ok(())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
});
|
||||
trace!("Ending plugin_domain pre_create_transform");
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
fn pre_modify(
|
||||
_qs: &QueryServerWriteTransaction,
|
||||
cand: &mut Vec<Entry<EntryInvalid, EntryCommitted>>,
|
||||
_me: &ModifyEvent,
|
||||
) -> Result<(), OperationError> {
|
||||
cand.iter_mut().try_for_each(|e| {
|
||||
if e.attribute_equality("class", &PVCLASS_DOMAIN_INFO)
|
||||
&& e.attribute_equality("uuid", &PVUUID_DOMAIN_INFO)
|
||||
{
|
||||
if !e.attribute_pres("domain_token_key") {
|
||||
let k = HS512::generate_key()
|
||||
.map(|k| Value::new_secret_str(&k))
|
||||
.map_err(|e| {
|
||||
admin_error!(err = ?e, "Failed to generate domain_token_key");
|
||||
OperationError::InvalidState
|
||||
})?;
|
||||
e.set_ava("domain_token_key", btreeset![k]);
|
||||
trace!("plugin_domain: Applying domain_token_key transform");
|
||||
}
|
||||
trace!(?e);
|
||||
Ok(())
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -166,6 +166,7 @@ impl Plugins {
|
|||
.and_then(|_| password_import::PasswordImport::pre_modify(qs, cand, me))
|
||||
.and_then(|_| oauth2::Oauth2Secrets::pre_modify(qs, cand, me))
|
||||
.and_then(|_| gidnumber::GidNumber::pre_modify(qs, cand, me))
|
||||
.and_then(|_| domain::Domain::pre_modify(qs, cand, me))
|
||||
.and_then(|_| spn::Spn::pre_modify(qs, cand, me))
|
||||
// attr unique should always be last
|
||||
.and_then(|_| attrunique::AttrUnique::pre_modify(qs, cand, me))
|
||||
|
|
|
@ -23,6 +23,7 @@ lazy_static! {
|
|||
m.insert("may");
|
||||
// Allow modification of some domain info types for local configuration.
|
||||
m.insert("domain_ssid");
|
||||
m.insert("domain_token_key");
|
||||
m.insert("badlist_password");
|
||||
m
|
||||
};
|
||||
|
@ -192,10 +193,10 @@ mod tests {
|
|||
],
|
||||
"acp_search_attr": ["name", "class", "uuid", "classname", "attributename"],
|
||||
"acp_modify_class": ["system", "domain_info"],
|
||||
"acp_modify_removedattr": ["class", "displayname", "may", "must", "domain_name", "domain_uuid", "domain_ssid"],
|
||||
"acp_modify_presentattr": ["class", "displayname", "may", "must", "domain_name", "domain_uuid", "domain_ssid"],
|
||||
"acp_modify_removedattr": ["class", "displayname", "may", "must", "domain_name", "domain_uuid", "domain_ssid", "domain_token_key"],
|
||||
"acp_modify_presentattr": ["class", "displayname", "may", "must", "domain_name", "domain_uuid", "domain_ssid", "domain_token_key"],
|
||||
"acp_create_class": ["object", "person", "system", "domain_info"],
|
||||
"acp_create_attr": ["name", "class", "description", "displayname", "domain_name", "domain_uuid", "domain_ssid", "uuid"]
|
||||
"acp_create_attr": ["name", "class", "description", "displayname", "domain_name", "domain_uuid", "domain_ssid", "uuid", "domain_token_key"]
|
||||
}
|
||||
}"#;
|
||||
|
||||
|
@ -326,9 +327,10 @@ mod tests {
|
|||
"name": ["domain_example.net.au"],
|
||||
"uuid": ["96fd1112-28bc-48ae-9dda-5acb4719aaba"],
|
||||
"domain_uuid": ["96fd1112-28bc-48ae-9dda-5acb4719aaba"],
|
||||
"description": ["Demonstration of a remote domain's info being created for uuid generaiton"],
|
||||
"description": ["Demonstration of a remote domain's info being created for uuid generation"],
|
||||
"domain_name": ["example.net.au"],
|
||||
"domain_ssid": ["Example_Wifi"]
|
||||
"domain_ssid": ["Example_Wifi"],
|
||||
"domain_token_key": ["ABCD"]
|
||||
}
|
||||
}"#,
|
||||
);
|
||||
|
@ -363,9 +365,10 @@ mod tests {
|
|||
"name": ["domain_example.net.au"],
|
||||
"uuid": ["96fd1112-28bc-48ae-9dda-5acb4719aaba"],
|
||||
"domain_uuid": ["96fd1112-28bc-48ae-9dda-5acb4719aaba"],
|
||||
"description": ["Demonstration of a remote domain's info being created for uuid generaiton"],
|
||||
"description": ["Demonstration of a remote domain's info being created for uuid generation"],
|
||||
"domain_name": ["example.net.au"],
|
||||
"domain_ssid": ["Example_Wifi"]
|
||||
"domain_ssid": ["Example_Wifi"],
|
||||
"domain_token_key": ["ABCD"]
|
||||
}
|
||||
}"#,
|
||||
);
|
||||
|
@ -391,9 +394,10 @@ mod tests {
|
|||
"name": ["domain_example.net.au"],
|
||||
"uuid": ["96fd1112-28bc-48ae-9dda-5acb4719aaba"],
|
||||
"domain_uuid": ["96fd1112-28bc-48ae-9dda-5acb4719aaba"],
|
||||
"description": ["Demonstration of a remote domain's info being created for uuid generaiton"],
|
||||
"description": ["Demonstration of a remote domain's info being created for uuid generation"],
|
||||
"domain_name": ["example.net.au"],
|
||||
"domain_ssid": ["Example_Wifi"]
|
||||
"domain_ssid": ["Example_Wifi"],
|
||||
"domain_token_key": ["ABCD"]
|
||||
}
|
||||
}"#,
|
||||
);
|
||||
|
|
|
@ -48,6 +48,7 @@ lazy_static! {
|
|||
static ref PVCLASS_ACC: PartialValue = PartialValue::new_class("access_control_create");
|
||||
static ref PVCLASS_ACP: PartialValue = PartialValue::new_class("access_control_profile");
|
||||
static ref PVCLASS_OAUTH2_RS: PartialValue = PartialValue::new_class("oauth2_resource_server");
|
||||
static ref PVUUID_DOMAIN_INFO: PartialValue = PartialValue::new_uuidr(&UUID_DOMAIN_INFO);
|
||||
static ref PVACP_ENABLE_FALSE: PartialValue = PartialValue::new_bool(false);
|
||||
}
|
||||
|
||||
|
@ -88,6 +89,7 @@ pub struct QueryServerWriteTransaction<'a> {
|
|||
changed_schema: Cell<bool>,
|
||||
changed_acp: Cell<bool>,
|
||||
changed_oauth2: Cell<bool>,
|
||||
changed_domain: Cell<bool>,
|
||||
// Store the list of changed uuids for other invalidation needs?
|
||||
changed_uuid: Cell<HashSet<Uuid>>,
|
||||
_db_ticket: SemaphorePermit<'a>,
|
||||
|
@ -686,6 +688,19 @@ pub trait QueryServerTransaction<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
fn get_domain_token_key(&self) -> Result<String, OperationError> {
|
||||
self.internal_search_uuid(&UUID_DOMAIN_INFO)
|
||||
.and_then(|e| {
|
||||
e.get_ava_single_secret("domain_token_key")
|
||||
.map(str::to_string)
|
||||
.ok_or(OperationError::InvalidEntryState)
|
||||
})
|
||||
.map_err(|e| {
|
||||
admin_error!(?e, "Error getting domain token key");
|
||||
e
|
||||
})
|
||||
}
|
||||
|
||||
// ! TRACING INTEGRATED
|
||||
// This is a helper to get password badlist.
|
||||
fn get_password_badlist(&self) -> Result<HashSet<String>, OperationError> {
|
||||
|
@ -928,6 +943,7 @@ impl QueryServer {
|
|||
changed_schema: Cell::new(false),
|
||||
changed_acp: Cell::new(false),
|
||||
changed_oauth2: Cell::new(false),
|
||||
changed_domain: Cell::new(false),
|
||||
changed_uuid: Cell::new(HashSet::new()),
|
||||
_db_ticket: db_ticket,
|
||||
_write_ticket: write_ticket,
|
||||
|
@ -1007,6 +1023,10 @@ impl QueryServer {
|
|||
migrate_txn.migrate_2_to_3()?;
|
||||
}
|
||||
|
||||
if system_info_version < 4 {
|
||||
migrate_txn.migrate_3_to_4()?;
|
||||
}
|
||||
|
||||
migrate_txn.commit()?;
|
||||
// Migrations complete. Init idm will now set the version as needed.
|
||||
|
||||
|
@ -1136,6 +1156,13 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
.any(|e| e.attribute_equality("class", &PVCLASS_OAUTH2_RS)),
|
||||
)
|
||||
}
|
||||
if !self.changed_domain.get() {
|
||||
self.changed_domain.set(
|
||||
commit_cand
|
||||
.iter()
|
||||
.any(|e| e.attribute_equality("uuid", &PVUUID_DOMAIN_INFO)),
|
||||
)
|
||||
}
|
||||
|
||||
let cu = self.changed_uuid.as_ptr();
|
||||
unsafe {
|
||||
|
@ -1145,6 +1172,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
schema_reload = ?self.changed_schema,
|
||||
acp_reload = ?self.changed_acp,
|
||||
oauth2_reload = ?self.changed_oauth2,
|
||||
domain_reload = ?self.changed_domain,
|
||||
);
|
||||
|
||||
// We are complete, finalise logging and return
|
||||
|
@ -1266,6 +1294,13 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
.any(|e| e.attribute_equality("class", &PVCLASS_OAUTH2_RS)),
|
||||
)
|
||||
}
|
||||
if !self.changed_domain.get() {
|
||||
self.changed_domain.set(
|
||||
del_cand
|
||||
.iter()
|
||||
.any(|e| e.attribute_equality("uuid", &PVUUID_DOMAIN_INFO)),
|
||||
)
|
||||
}
|
||||
|
||||
let cu = self.changed_uuid.as_ptr();
|
||||
unsafe {
|
||||
|
@ -1276,6 +1311,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
schema_reload = ?self.changed_schema,
|
||||
acp_reload = ?self.changed_acp,
|
||||
oauth2_reload = ?self.changed_oauth2,
|
||||
domain_reload = ?self.changed_domain,
|
||||
);
|
||||
|
||||
// Send result
|
||||
|
@ -1611,6 +1647,14 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
.any(|e| e.attribute_equality("class", &PVCLASS_OAUTH2_RS)),
|
||||
)
|
||||
}
|
||||
if !self.changed_domain.get() {
|
||||
self.changed_domain.set(
|
||||
norm_cand
|
||||
.iter()
|
||||
.chain(pre_candidates.iter().map(|e| e.as_ref()))
|
||||
.any(|e| e.attribute_equality("uuid", &PVUUID_DOMAIN_INFO)),
|
||||
)
|
||||
}
|
||||
|
||||
let cu = self.changed_uuid.as_ptr();
|
||||
unsafe {
|
||||
|
@ -1626,6 +1670,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
schema_reload = ?self.changed_schema,
|
||||
acp_reload = ?self.changed_acp,
|
||||
oauth2_reload = ?self.changed_oauth2,
|
||||
domain_reload = ?self.changed_domain,
|
||||
);
|
||||
|
||||
// return
|
||||
|
@ -1758,6 +1803,13 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
.any(|e| e.attribute_equality("class", &PVCLASS_OAUTH2_RS)),
|
||||
)
|
||||
}
|
||||
if !self.changed_domain.get() {
|
||||
self.changed_domain.set(
|
||||
norm_cand
|
||||
.iter()
|
||||
.any(|e| e.attribute_equality("uuid", &PVUUID_DOMAIN_INFO)),
|
||||
)
|
||||
}
|
||||
let cu = self.changed_uuid.as_ptr();
|
||||
unsafe {
|
||||
(*cu).extend(
|
||||
|
@ -1771,6 +1823,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
schema_reload = ?self.changed_schema,
|
||||
acp_reload = ?self.changed_acp,
|
||||
oauth2_reload = ?self.changed_oauth2,
|
||||
domain_reload = ?self.changed_domain,
|
||||
);
|
||||
|
||||
trace!("Modify operation success");
|
||||
|
@ -1839,6 +1892,18 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
})
|
||||
}
|
||||
|
||||
/// Migrate 3 to 4 - this triggers a regen of the domains security token
|
||||
/// as we previously did not have it in the entry.
|
||||
pub fn migrate_3_to_4(&self) -> Result<(), OperationError> {
|
||||
spanned!("server::migrate_3_to_4", {
|
||||
admin_warn!("starting 3 to 4 migration.");
|
||||
let filter = filter!(f_eq("uuid", (*PVUUID_DOMAIN_INFO).clone()));
|
||||
let modlist = ModifyList::new_purge("domain_token_key");
|
||||
self.internal_modify(&filter, &modlist)
|
||||
// Complete
|
||||
})
|
||||
}
|
||||
|
||||
// These are where searches and other actions are actually implemented. This
|
||||
// is the "internal" version, where we define the event as being internal
|
||||
// only, allowing certain plugin by passes etc.
|
||||
|
@ -2115,6 +2180,7 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
JSON_SCHEMA_ATTR_DOMAIN_NAME,
|
||||
JSON_SCHEMA_ATTR_DOMAIN_UUID,
|
||||
JSON_SCHEMA_ATTR_DOMAIN_SSID,
|
||||
JSON_SCHEMA_ATTR_DOMAIN_TOKEN_KEY,
|
||||
JSON_SCHEMA_ATTR_GIDNUMBER,
|
||||
JSON_SCHEMA_ATTR_BADLIST_PASSWORD,
|
||||
JSON_SCHEMA_ATTR_LOGINSHELL,
|
||||
|
@ -2502,6 +2568,10 @@ impl<'a> QueryServerWriteTransaction<'a> {
|
|||
self.changed_oauth2.get()
|
||||
}
|
||||
|
||||
pub fn get_changed_domain(&self) -> bool {
|
||||
self.changed_domain.get()
|
||||
}
|
||||
|
||||
pub fn commit(mut self) -> Result<(), OperationError> {
|
||||
// This could be faster if we cache the set of classes changed
|
||||
// in an operation so we can check if we need to do the reload or not
|
||||
|
|
Loading…
Reference in a new issue