Multi-tenancy: registry reach, links, membership and count limits over JMAP (MT-2, MT-3, MT-6, MT-7, MT-8, MT-11, MT-12, MT-17, MT-18)
Inside a tenant, server-level object types are forbidden and x:Tenant reads return only the caller's own tenant, which it can't change. Registry writes refuse links across tenant boundaries in both directions, give a new principal its domain's tenant, move a domain's principals and DKIM keys with it into a tenant, refuse moves out of a tenant while its people remain, and refuse creates past a tenant's count limits with overQuota and limit.tenant-quota.
This commit is contained in:
@@ -89,6 +89,11 @@ impl JmapAuthorization for AccessToken {
|
||||
let MethodObject::Registry(object_type) = object else {
|
||||
unreachable!()
|
||||
};
|
||||
// inbuxa: MT-2: server-level objects are out of a tenant's reach
|
||||
assert_tenant_reach(
|
||||
self,
|
||||
inbuxa_features::tenancy::reach::can_read(object_type),
|
||||
)?;
|
||||
object_type.get_permission()
|
||||
}
|
||||
},
|
||||
@@ -203,6 +208,11 @@ impl JmapAuthorization for AccessToken {
|
||||
let MethodObject::Registry(object_type) = object else {
|
||||
unreachable!()
|
||||
};
|
||||
// inbuxa: MT-2, MT-12: server-level objects are out of a tenant's reach
|
||||
assert_tenant_reach(
|
||||
self,
|
||||
inbuxa_features::tenancy::reach::can_write(object_type),
|
||||
)?;
|
||||
let set_permissions = object_type.set_permission();
|
||||
validate_set(
|
||||
s,
|
||||
@@ -295,6 +305,11 @@ impl JmapAuthorization for AccessToken {
|
||||
let MethodObject::Registry(object_type) = object else {
|
||||
unreachable!()
|
||||
};
|
||||
// inbuxa: MT-2: server-level objects are out of a tenant's reach
|
||||
assert_tenant_reach(
|
||||
self,
|
||||
inbuxa_features::tenancy::reach::can_read(object_type),
|
||||
)?;
|
||||
object_type.query_permission()
|
||||
}
|
||||
},
|
||||
@@ -316,6 +331,17 @@ impl JmapAuthorization for AccessToken {
|
||||
}
|
||||
}
|
||||
|
||||
// inbuxa: MT-2
|
||||
fn assert_tenant_reach(access_token: &AccessToken, reachable: bool) -> trc::Result<()> {
|
||||
if reachable || access_token.tenant_id().is_none() {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(trc::JmapEvent::Forbidden
|
||||
.into_err()
|
||||
.details("You are not authorized to perform this action"))
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_set<T: JmapObject>(
|
||||
set: &SetRequest<'_, T>,
|
||||
access_token: &AccessToken,
|
||||
|
||||
Reference in New Issue
Block a user