20240221 2489 cleanup api v1 (#2573)

This commit is contained in:
Firstyear 2024-02-27 19:25:02 +10:00 committed by GitHub
parent 4096b8f02d
commit fbc021f487
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
109 changed files with 1655 additions and 1643 deletions

40
Cargo.lock generated
View file

@ -221,8 +221,6 @@ dependencies = [
"memchr", "memchr",
"pin-project-lite", "pin-project-lite",
"tokio", "tokio",
"zstd",
"zstd-safe",
] ]
[[package]] [[package]]
@ -667,7 +665,6 @@ version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
dependencies = [ dependencies = [
"jobserver",
"libc", "libc",
] ]
@ -2885,15 +2882,6 @@ version = "1.0.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
[[package]]
name = "jobserver"
version = "0.1.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6"
dependencies = [
"libc",
]
[[package]] [[package]]
name = "jpeg-decoder" name = "jpeg-decoder"
version = "0.3.1" version = "0.3.1"
@ -6892,34 +6880,6 @@ dependencies = [
"flate2", "flate2",
] ]
[[package]]
name = "zstd"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bffb3309596d527cfcba7dfc6ed6052f1d39dfbd7c867aa2e865e4a449c10110"
dependencies = [
"zstd-safe",
]
[[package]]
name = "zstd-safe"
version = "7.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43747c7422e2924c11144d5229878b98180ef8b06cca4ab5af37afc8a8d8ea3e"
dependencies = [
"zstd-sys",
]
[[package]]
name = "zstd-sys"
version = "2.0.9+zstd.1.5.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656"
dependencies = [
"cc",
"pkg-config",
]
[[package]] [[package]]
name = "zxcvbn" name = "zxcvbn"
version = "2.2.2" version = "2.2.2"

View file

@ -29,6 +29,7 @@ use kanidm_proto::constants::{
APPLICATION_JSON, ATTR_ENTRY_MANAGED_BY, ATTR_NAME, CLIENT_TOKEN_CACHE, KOPID, KSESSIONID, APPLICATION_JSON, ATTR_ENTRY_MANAGED_BY, ATTR_NAME, CLIENT_TOKEN_CACHE, KOPID, KSESSIONID,
KVERSION, KVERSION,
}; };
use kanidm_proto::internal::*;
use kanidm_proto::v1::*; use kanidm_proto::v1::*;
use reqwest::header::CONTENT_TYPE; use reqwest::header::CONTENT_TYPE;
use reqwest::Response; use reqwest::Response;

View file

@ -1,10 +1,8 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use kanidm_proto::constants::*; use kanidm_proto::constants::*;
use kanidm_proto::internal::{IdentifyUserRequest, IdentifyUserResponse}; use kanidm_proto::internal::{CredentialStatus, IdentifyUserRequest, IdentifyUserResponse};
use kanidm_proto::v1::{ use kanidm_proto::v1::{AccountUnixExtend, Entry, SingleStringRequest, UatStatus};
AccountUnixExtend, CredentialStatus, Entry, SingleStringRequest, UatStatus,
};
use uuid::Uuid; use uuid::Uuid;
use crate::{ClientError, KanidmClient}; use crate::{ClientError, KanidmClient};

View file

@ -1,7 +1,8 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use kanidm_proto::constants::{ATTR_DISPLAYNAME, ATTR_ENTRY_MANAGED_BY, ATTR_MAIL, ATTR_NAME}; use kanidm_proto::constants::{ATTR_DISPLAYNAME, ATTR_ENTRY_MANAGED_BY, ATTR_MAIL, ATTR_NAME};
use kanidm_proto::v1::{AccountUnixExtend, ApiToken, ApiTokenGenerate, CredentialStatus, Entry}; use kanidm_proto::internal::{ApiToken, CredentialStatus};
use kanidm_proto::v1::{AccountUnixExtend, ApiTokenGenerate, Entry};
use time::OffsetDateTime; use time::OffsetDateTime;
use uuid::Uuid; use uuid::Uuid;

View file

@ -1,8 +1,8 @@
// include!("src/lib/audit_loglevel.rs");
use std::env; use std::env;
fn main() { fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-env-changed=DEP_OPENSSL_VERSION_NUMBER");
if let Ok(v) = env::var("DEP_OPENSSL_VERSION_NUMBER") { if let Ok(v) = env::var("DEP_OPENSSL_VERSION_NUMBER") {
let version = u64::from_str_radix(&v, 16).unwrap(); let version = u64::from_str_radix(&v, 16).unwrap();

View file

@ -22,7 +22,7 @@ use serde::{Deserialize, Serialize};
use std::fmt; use std::fmt;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
use kanidm_proto::v1::OperationError; use kanidm_proto::internal::OperationError;
use openssl::error::ErrorStack as OpenSSLErrorStack; use openssl::error::ErrorStack as OpenSSLErrorStack;
use openssl::hash::{self, MessageDigest}; use openssl::hash::{self, MessageDigest};
use openssl::nid::Nid; use openssl::nid::Nid;

View file

@ -33,6 +33,14 @@ fn determine_git_rev() -> Option<String> {
} }
fn main() { fn main() {
/*
* https://doc.rust-lang.org/cargo/reference/build-scripts.html#change-detection
* If the build script inherently does not need to re-run under any circumstance, then emitting
* cargo:rerun-if-changed=build.rs is a simple way to prevent it from being re-run (otherwise,
* the default if no rerun-if instructions are emitted is to scan the entire package directory
* for changes).
*/
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-env-changed=KANIDM_BUILD_PROFILE"); println!("cargo:rerun-if-env-changed=KANIDM_BUILD_PROFILE");
let profile = env::var("KANIDM_BUILD_PROFILE").unwrap_or_else(|_| "developer".to_string()); let profile = env::var("KANIDM_BUILD_PROFILE").unwrap_or_else(|_| "developer".to_string());

View file

@ -2,6 +2,9 @@ use base64::{engine::general_purpose, Engine as _};
use serde::Deserialize; use serde::Deserialize;
use std::env; use std::env;
// To debug why a rebuild is requested.
// CARGO_LOG=cargo::core::compiler::fingerprint=info cargo ...
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
enum CpuOptLevel { enum CpuOptLevel {
@ -76,6 +79,9 @@ pub fn apply_profile() {
// We have to setup for our pkg version to be passed into things correctly // We have to setup for our pkg version to be passed into things correctly
// now. This relies on the profile build.rs to get the commit rev if present, but // now. This relies on the profile build.rs to get the commit rev if present, but
// we combine it with the local package version // we combine it with the local package version
println!("cargo:rerun-if-env-changed=CARGO_PKG_VERSION");
println!("cargo:rerun-if-env-changed=KANIDM_PKG_COMMIT_REV");
let version = env!("CARGO_PKG_VERSION"); let version = env!("CARGO_PKG_VERSION");
if let Some(commit_rev) = option_env!("KANIDM_PKG_COMMIT_REV") { if let Some(commit_rev) = option_env!("KANIDM_PKG_COMMIT_REV") {
println!( println!(

View file

@ -84,9 +84,9 @@ Stable APIs are:
- LDAP protocol operations - LDAP protocol operations
- JSON HTTP end points which use elements from - JSON HTTP end points which use elements from
[`proto/src/v1.rs`](https://github.com/kanidm/kanidm/blob/master/proto/src/v1.rs) [`proto/src/v1`](https://github.com/kanidm/kanidm/blob/master/proto/src/v1)
- SCIM operations from - SCIM operations from
[`proto/src/scim_v1.rs`](https://github.com/kanidm/kanidm/blob/master/proto/src/scim_v1.rs) [`proto/src/scim_v1`](https://github.com/kanidm/kanidm/blob/master/proto/src/scim_v1)
All other APIs and interactions are not considered stable. Changes will be minimised if possible. All other APIs and interactions are not considered stable. Changes will be minimised if possible.
This includes but is not limited to: This includes but is not limited to:

View file

@ -5,10 +5,15 @@ pub mod uri;
/// The default location for the `kanidm` CLI tool's token cache. /// The default location for the `kanidm` CLI tool's token cache.
pub const CLIENT_TOKEN_CACHE: &str = "~/.cache/kanidm_tokens"; pub const CLIENT_TOKEN_CACHE: &str = "~/.cache/kanidm_tokens";
/// Content type string for jpeg
pub const CONTENT_TYPE_JPG: &str = "image/jpeg"; pub const CONTENT_TYPE_JPG: &str = "image/jpeg";
/// Content type string for png
pub const CONTENT_TYPE_PNG: &str = "image/png"; pub const CONTENT_TYPE_PNG: &str = "image/png";
/// Content type string for gif
pub const CONTENT_TYPE_GIF: &str = "image/gif"; pub const CONTENT_TYPE_GIF: &str = "image/gif";
/// Content type string for svg
pub const CONTENT_TYPE_SVG: &str = "image/svg+xml"; pub const CONTENT_TYPE_SVG: &str = "image/svg+xml";
/// Content type string for webp
pub const CONTENT_TYPE_WEBP: &str = "image/webp"; pub const CONTENT_TYPE_WEBP: &str = "image/webp";
// For when the user uploads things to the various image endpoints, these are the valid content-types. // For when the user uploads things to the various image endpoints, these are the valid content-types.

View file

@ -0,0 +1,437 @@
use serde::{Deserialize, Serialize};
use std::fmt;
use url::Url;
use utoipa::ToSchema;
use uuid::Uuid;
use webauthn_rs_proto::CreationChallengeResponse;
use webauthn_rs_proto::RegisterPublicKeyCredential;
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum TotpAlgo {
Sha1,
Sha256,
Sha512,
}
impl fmt::Display for TotpAlgo {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
TotpAlgo::Sha1 => write!(f, "SHA1"),
TotpAlgo::Sha256 => write!(f, "SHA256"),
TotpAlgo::Sha512 => write!(f, "SHA512"),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct TotpSecret {
pub accountname: String,
/// User-facing name of the system, issuer of the TOTP
pub issuer: String,
pub secret: Vec<u8>,
pub algo: TotpAlgo,
pub step: u64,
pub digits: u8,
}
impl TotpSecret {
/// <https://github.com/google/google-authenticator/wiki/Key-Uri-Format>
pub fn to_uri(&self) -> String {
let accountname = urlencoding::Encoded(&self.accountname);
let issuer = urlencoding::Encoded(&self.issuer);
let label = format!("{}:{}", issuer, accountname);
let algo = self.algo.to_string();
let secret = self.get_secret();
let period = self.step;
let digits = self.digits;
format!(
"otpauth://totp/{}?secret={}&issuer={}&algorithm={}&digits={}&period={}",
label, secret, issuer, algo, digits, period
)
}
pub fn get_secret(&self) -> String {
base32::encode(base32::Alphabet::RFC4648 { padding: false }, &self.secret)
}
}
#[derive(Debug, Serialize, Deserialize, ToSchema)]
pub struct CUIntentToken {
pub token: String,
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, ToSchema)]
pub struct CUSessionToken {
pub token: String,
}
#[derive(Clone, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
pub enum CURequest {
PrimaryRemove,
Password(String),
CancelMFAReg,
TotpGenerate,
TotpVerify(u32, String),
TotpAcceptSha1,
TotpRemove(String),
BackupCodeGenerate,
BackupCodeRemove,
PasskeyInit,
PasskeyFinish(String, RegisterPublicKeyCredential),
PasskeyRemove(Uuid),
AttestedPasskeyInit,
AttestedPasskeyFinish(String, RegisterPublicKeyCredential),
AttestedPasskeyRemove(Uuid),
}
impl fmt::Debug for CURequest {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let t = match self {
CURequest::PrimaryRemove => "CURequest::PrimaryRemove",
CURequest::Password(_) => "CURequest::Password",
CURequest::CancelMFAReg => "CURequest::CancelMFAReg",
CURequest::TotpGenerate => "CURequest::TotpGenerate",
CURequest::TotpVerify(_, _) => "CURequest::TotpVerify",
CURequest::TotpAcceptSha1 => "CURequest::TotpAcceptSha1",
CURequest::TotpRemove(_) => "CURequest::TotpRemove",
CURequest::BackupCodeGenerate => "CURequest::BackupCodeGenerate",
CURequest::BackupCodeRemove => "CURequest::BackupCodeRemove",
CURequest::PasskeyInit => "CURequest::PasskeyInit",
CURequest::PasskeyFinish(_, _) => "CURequest::PasskeyFinish",
CURequest::PasskeyRemove(_) => "CURequest::PasskeyRemove",
CURequest::AttestedPasskeyInit => "CURequest::AttestedPasskeyInit",
CURequest::AttestedPasskeyFinish(_, _) => "CURequest::AttestedPasskeyFinish",
CURequest::AttestedPasskeyRemove(_) => "CURequest::AttestedPasskeyRemove",
};
writeln!(f, "{}", t)
}
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub enum CURegState {
// Nothing in progress.
None,
TotpCheck(TotpSecret),
TotpTryAgain,
TotpInvalidSha1,
BackupCodes(Vec<String>),
Passkey(CreationChallengeResponse),
AttestedPasskey(CreationChallengeResponse),
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub enum CUExtPortal {
None,
Hidden,
Some(Url),
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, ToSchema, PartialEq)]
pub enum CUCredState {
Modifiable,
DeleteOnly,
AccessDeny,
PolicyDeny,
// Disabled,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub enum CURegWarning {
MfaRequired,
PasskeyRequired,
AttestedPasskeyRequired,
AttestedResidentKeyRequired,
Unsatisfiable,
WebauthnAttestationUnsatisfiable,
}
#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
pub struct CUStatus {
// Display values
pub spn: String,
pub displayname: String,
pub ext_cred_portal: CUExtPortal,
// Internal State Tracking
pub mfaregstate: CURegState,
// Display hints + The credential details.
pub can_commit: bool,
pub warnings: Vec<CURegWarning>,
pub primary: Option<CredentialDetail>,
pub primary_state: CUCredState,
pub passkeys: Vec<PasskeyDetail>,
pub passkeys_state: CUCredState,
pub attested_passkeys: Vec<PasskeyDetail>,
pub attested_passkeys_state: CUCredState,
pub attested_passkeys_allowed_devices: Vec<String>,
}
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
pub struct CredentialStatus {
pub creds: Vec<CredentialDetail>,
}
impl fmt::Display for CredentialStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
for cred in &self.creds {
writeln!(f, "---")?;
cred.fmt(f)?;
}
writeln!(f, "---")
}
}
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, ToSchema)]
pub enum CredentialDetailType {
Password,
GeneratedPassword,
Passkey(Vec<String>),
/// totp, webauthn
PasswordMfa(Vec<String>, Vec<String>, usize),
}
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
pub struct CredentialDetail {
pub uuid: Uuid,
pub type_: CredentialDetailType,
}
impl fmt::Display for CredentialDetail {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "uuid: {}", self.uuid)?;
/*
writeln!(f, "claims:")?;
for claim in &self.claims {
writeln!(f, " * {}", claim)?;
}
*/
match &self.type_ {
CredentialDetailType::Password => writeln!(f, "password: set"),
CredentialDetailType::GeneratedPassword => writeln!(f, "generated password: set"),
CredentialDetailType::Passkey(labels) => {
if labels.is_empty() {
writeln!(f, "passkeys: none registered")
} else {
writeln!(f, "passkeys:")?;
for label in labels {
writeln!(f, " * {}", label)?;
}
write!(f, "")
}
}
CredentialDetailType::PasswordMfa(totp_labels, wan_labels, backup_code) => {
writeln!(f, "password: set")?;
if !totp_labels.is_empty() {
writeln!(f, "totp:")?;
for label in totp_labels {
writeln!(f, " * {}", label)?;
}
} else {
writeln!(f, "totp: disabled")?;
}
if *backup_code > 0 {
writeln!(f, "backup_code: enabled")?;
} else {
writeln!(f, "backup_code: disabled")?;
}
if !wan_labels.is_empty() {
// We no longer show the deprecated security key case by default.
writeln!(f, " ⚠️ warning - security keys are deprecated.")?;
writeln!(f, " ⚠️ you should re-enroll these to passkeys.")?;
writeln!(f, "security keys:")?;
for label in wan_labels {
writeln!(f, " * {}", label)?;
}
write!(f, "")
} else {
write!(f, "")
}
}
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
pub struct PasskeyDetail {
pub uuid: Uuid,
pub tag: String,
}
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
pub struct BackupCodesView {
pub backup_codes: Vec<String>,
}
#[derive(Serialize, Deserialize, Debug, ToSchema, PartialEq, Eq, PartialOrd, Ord)]
#[serde(rename_all = "lowercase")]
pub enum PasswordFeedback {
// https://docs.rs/zxcvbn/latest/zxcvbn/feedback/enum.Suggestion.html
UseAFewWordsAvoidCommonPhrases,
NoNeedForSymbolsDigitsOrUppercaseLetters,
AddAnotherWordOrTwo,
CapitalizationDoesntHelpVeryMuch,
AllUppercaseIsAlmostAsEasyToGuessAsAllLowercase,
ReversedWordsArentMuchHarderToGuess,
PredictableSubstitutionsDontHelpVeryMuch,
UseALongerKeyboardPatternWithMoreTurns,
AvoidRepeatedWordsAndCharacters,
AvoidSequences,
AvoidRecentYears,
AvoidYearsThatAreAssociatedWithYou,
AvoidDatesAndYearsThatAreAssociatedWithYou,
// https://docs.rs/zxcvbn/latest/zxcvbn/feedback/enum.Warning.html
StraightRowsOfKeysAreEasyToGuess,
ShortKeyboardPatternsAreEasyToGuess,
RepeatsLikeAaaAreEasyToGuess,
RepeatsLikeAbcAbcAreOnlySlightlyHarderToGuess,
ThisIsATop10Password,
ThisIsATop100Password,
ThisIsACommonPassword,
ThisIsSimilarToACommonlyUsedPassword,
SequencesLikeAbcAreEasyToGuess,
RecentYearsAreEasyToGuess,
AWordByItselfIsEasyToGuess,
DatesAreOftenEasyToGuess,
NamesAndSurnamesByThemselvesAreEasyToGuess,
CommonNamesAndSurnamesAreEasyToGuess,
// Custom
TooShort(u32),
BadListed,
DontReusePasswords,
}
/// Human-readable PasswordFeedback result.
impl fmt::Display for PasswordFeedback {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
PasswordFeedback::AddAnotherWordOrTwo => write!(f, "Add another word or two."),
PasswordFeedback::AllUppercaseIsAlmostAsEasyToGuessAsAllLowercase => write!(
f,
"All uppercase is almost as easy to guess as all lowercase."
),
PasswordFeedback::AvoidDatesAndYearsThatAreAssociatedWithYou => write!(
f,
"Avoid dates and years that are associated with you or your account."
),
PasswordFeedback::AvoidRecentYears => write!(f, "Avoid recent years."),
PasswordFeedback::AvoidRepeatedWordsAndCharacters => {
write!(f, "Avoid repeated words and characters.")
}
PasswordFeedback::AvoidSequences => write!(f, "Avoid sequences of characters."),
PasswordFeedback::AvoidYearsThatAreAssociatedWithYou => {
write!(f, "Avoid years that are associated with you.")
}
PasswordFeedback::AWordByItselfIsEasyToGuess => {
write!(f, "A word by itself is easy to guess.")
}
PasswordFeedback::BadListed => write!(
f,
"This password has been compromised or otherwise blocked and can not be used."
),
PasswordFeedback::CapitalizationDoesntHelpVeryMuch => {
write!(f, "Capitalization doesn't help very much.")
}
PasswordFeedback::CommonNamesAndSurnamesAreEasyToGuess => {
write!(f, "Common names and surnames are easy to guess.")
}
PasswordFeedback::DatesAreOftenEasyToGuess => {
write!(f, "Dates are often easy to guess.")
}
PasswordFeedback::DontReusePasswords => {
write!(
f,
"Don't reuse passwords that already exist on your account"
)
}
PasswordFeedback::NamesAndSurnamesByThemselvesAreEasyToGuess => {
write!(f, "Names and surnames by themselves are easy to guess.")
}
PasswordFeedback::NoNeedForSymbolsDigitsOrUppercaseLetters => {
write!(f, "No need for symbols, digits or upper-case letters.")
}
PasswordFeedback::PredictableSubstitutionsDontHelpVeryMuch => {
write!(f, "Predictable substitutions don't help very much.")
}
PasswordFeedback::RecentYearsAreEasyToGuess => {
write!(f, "Recent years are easy to guess.")
}
PasswordFeedback::RepeatsLikeAaaAreEasyToGuess => {
write!(f, "Repeats like 'aaa' are easy to guess.")
}
PasswordFeedback::RepeatsLikeAbcAbcAreOnlySlightlyHarderToGuess => write!(
f,
"Repeats like abcabcabc are only slightly harder to guess."
),
PasswordFeedback::ReversedWordsArentMuchHarderToGuess => {
write!(f, "Reversed words aren't much harder to guess.")
}
PasswordFeedback::SequencesLikeAbcAreEasyToGuess => {
write!(f, "Sequences like 'abc' are easy to guess.")
}
PasswordFeedback::ShortKeyboardPatternsAreEasyToGuess => {
write!(f, "Short keyboard patterns are easy to guess.")
}
PasswordFeedback::StraightRowsOfKeysAreEasyToGuess => {
write!(f, "Straight rows of keys are easy to guess.")
}
PasswordFeedback::ThisIsACommonPassword => write!(f, "This is a common password."),
PasswordFeedback::ThisIsATop100Password => write!(f, "This is a top 100 password."),
PasswordFeedback::ThisIsATop10Password => write!(f, "This is a top 10 password."),
PasswordFeedback::ThisIsSimilarToACommonlyUsedPassword => {
write!(f, "This is similar to a commonly used password.")
}
PasswordFeedback::TooShort(minlength) => write!(
f,
"Password too was short, needs to be at least {} characters long.",
minlength
),
PasswordFeedback::UseAFewWordsAvoidCommonPhrases => {
write!(f, "Use a few words and avoid common phrases.")
}
PasswordFeedback::UseALongerKeyboardPatternWithMoreTurns => {
write!(
f,
"The password included keyboard patterns across too much of a single row."
)
}
}
}
}
#[cfg(test)]
mod tests {
use super::{TotpAlgo, TotpSecret};
#[test]
fn totp_to_string() {
let totp = TotpSecret {
accountname: "william".to_string(),
issuer: "blackhats".to_string(),
secret: vec![0xaa, 0xbb, 0xcc, 0xdd],
step: 30,
algo: TotpAlgo::Sha256,
digits: 6,
};
let s = totp.to_uri();
assert!(s == "otpauth://totp/blackhats:william?secret=VK54ZXI&issuer=blackhats&algorithm=SHA256&digits=6&period=30");
// check that invalid issuer/accounts are cleaned up.
let totp = TotpSecret {
accountname: "william:%3A".to_string(),
issuer: "blackhats australia".to_string(),
secret: vec![0xaa, 0xbb, 0xcc, 0xdd],
step: 30,
algo: TotpAlgo::Sha256,
digits: 6,
};
let s = totp.to_uri();
println!("{}", s);
assert!(s == "otpauth://totp/blackhats%20australia:william%3A%253A?secret=VK54ZXI&issuer=blackhats%20australia&algorithm=SHA256&digits=6&period=30");
}
}

147
proto/src/internal/error.rs Normal file
View file

@ -0,0 +1,147 @@
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
use uuid::Uuid;
use super::credupdate::PasswordFeedback;
/* ===== errors ===== */
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum SchemaError {
NotImplemented,
NoClassFound,
InvalidClass(Vec<String>),
MissingMustAttribute(Vec<String>),
InvalidAttribute(String),
InvalidAttributeSyntax(String),
AttributeNotValidForClass(String),
SupplementsNotSatisfied(Vec<String>),
ExcludesNotSatisfied(Vec<String>),
EmptyFilter,
Corrupted,
PhantomAttribute(String),
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum PluginError {
AttrUnique(String),
Base(String),
ReferentialIntegrity(String),
CredImport(String),
Oauth2Secrets,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum ConsistencyError {
Unknown,
// Class, Attribute
SchemaClassMissingAttribute(String, String),
SchemaClassPhantomAttribute(String, String),
SchemaUuidNotUnique(Uuid),
QueryServerSearchFailure,
EntryUuidCorrupt(u64),
UuidIndexCorrupt(String),
UuidNotUnique(String),
RefintNotUpheld(u64),
MemberOfInvalid(u64),
InvalidAttributeType(String),
DuplicateUniqueAttribute,
InvalidSpn(u64),
SqliteIntegrityFailure,
BackendAllIdsSync,
BackendIndexSync,
ChangelogDesynchronised(u64),
ChangeStateDesynchronised(u64),
RuvInconsistent(String),
DeniedName(Uuid),
}
#[derive(Serialize, Deserialize, Debug, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum OperationError {
SessionExpired,
EmptyRequest,
Backend,
NoMatchingEntries,
NoMatchingAttributes,
CorruptedEntry(u64),
CorruptedIndex(String),
// TODO: this should just be a vec of the ConsistencyErrors, surely?
ConsistencyError(Vec<Result<(), ConsistencyError>>),
SchemaViolation(SchemaError),
Plugin(PluginError),
FilterGeneration,
FilterUuidResolution,
InvalidAttributeName(String),
InvalidAttribute(String),
InvalidDbState,
InvalidCacheState,
InvalidValueState,
InvalidEntryId,
InvalidRequestState,
InvalidSyncState,
InvalidState,
InvalidEntryState,
InvalidUuid,
InvalidReplChangeId,
InvalidAcpState(String),
InvalidSchemaState(String),
InvalidAccountState(String),
MissingEntries,
ModifyAssertionFailed,
BackendEngine,
SqliteError, //(RusqliteError)
FsError,
SerdeJsonError,
SerdeCborError,
AccessDenied,
NotAuthenticated,
NotAuthorised,
InvalidAuthState(String),
InvalidSessionState,
SystemProtectedObject,
SystemProtectedAttribute,
PasswordQuality(Vec<PasswordFeedback>),
CryptographyError,
ResourceLimit,
QueueDisconnected,
Webauthn,
#[serde(with = "time::serde::timestamp")]
Wait(time::OffsetDateTime),
ReplReplayFailure,
ReplEntryNotChanged,
ReplInvalidRUVState,
ReplDomainLevelUnsatisfiable,
ReplDomainUuidMismatch,
ReplServerUuidSplitDataState,
TransactionAlreadyCommitted,
/// when you ask for a gid that's lower than a safe minimum
GidOverlapsSystemMin(u32),
/// When a name is denied by the system config
ValueDenyName,
// What about something like this for unique errors?
// Credential Update Errors
CU0001WebauthnAttestationNotTrusted,
CU0002WebauthnRegistrationError,
// ValueSet errors
VS0001IncomingReplSshPublicKey,
// Value Errors
VL0001ValueSshPublicKeyString,
// SCIM
SC0001IncomingSshPublicKey,
// Migration
MG0001InvalidReMigrationLevel,
MG0002RaiseDomainLevelExceedsMaximum,
MG0003ServerPhaseInvalidForMigration,
}
impl PartialEq for OperationError {
fn eq(&self, other: &Self) -> bool {
// We do this to avoid InvalidPassword being checked as it's not
// derive PartialEq. Generally we only use the PartialEq for TESTING
// anyway.
std::mem::discriminant(self) == std::mem::discriminant(other)
}
}

View file

@ -1,12 +1,29 @@
//! Kanidm internal elements
//!
//! Items defined in this module *may* change between releases without notice.
use crate::constants::{ use crate::constants::{
CONTENT_TYPE_GIF, CONTENT_TYPE_JPG, CONTENT_TYPE_PNG, CONTENT_TYPE_SVG, CONTENT_TYPE_WEBP, CONTENT_TYPE_GIF, CONTENT_TYPE_JPG, CONTENT_TYPE_PNG, CONTENT_TYPE_SVG, CONTENT_TYPE_WEBP,
}; };
use crate::v1::ApiTokenPurpose;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::fmt;
use std::str::FromStr;
use url::Url; use url::Url;
use utoipa::ToSchema; use utoipa::ToSchema;
use uuid::Uuid; use uuid::Uuid;
use num_enum::TryFromPrimitive;
mod credupdate;
mod error;
mod raw;
mod token;
pub use self::credupdate::*;
pub use self::error::*;
pub use self::raw::*;
pub use self::token::*;
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Clone)]
/// This is a description of a linked or connected application for a user. This is /// This is a description of a linked or connected application for a user. This is
/// used in the UI to render applications on the dashboard for a user to access. /// used in the UI to render applications on the dashboard for a user to access.
@ -20,15 +37,40 @@ pub enum AppLink {
}, },
} }
#[derive(Debug, Serialize, Deserialize, Clone)] #[derive(Debug, Serialize, Deserialize, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]
pub struct ScimSyncToken { #[derive(TryFromPrimitive)]
// uuid of the token? #[repr(u16)]
pub token_id: Uuid, pub enum UiHint {
#[serde(with = "time::serde::timestamp")] ExperimentalFeatures = 0,
pub issued_at: time::OffsetDateTime, PosixAccount = 1,
#[serde(default)] CredentialUpdate = 2,
pub purpose: ApiTokenPurpose, SynchronisedAccount = 3,
}
impl fmt::Display for UiHint {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
UiHint::PosixAccount => write!(f, "PosixAccount"),
UiHint::CredentialUpdate => write!(f, "CredentialUpdate"),
UiHint::ExperimentalFeatures => write!(f, "ExperimentalFeatures"),
UiHint::SynchronisedAccount => write!(f, "SynchronisedAccount"),
}
}
}
impl FromStr for UiHint {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"CredentialUpdate" => Ok(UiHint::CredentialUpdate),
"PosixAccount" => Ok(UiHint::PosixAccount),
"ExperimentalFeatures" => Ok(UiHint::ExperimentalFeatures),
"SynchronisedAccount" => Ok(UiHint::SynchronisedAccount),
_ => Err(()),
}
}
} }
// State machine states and transitions for the identity verification system feature! // State machine states and transitions for the identity verification system feature!

113
proto/src/internal/raw.rs Normal file
View file

@ -0,0 +1,113 @@
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
use crate::v1::Entry;
#[derive(Debug, Serialize, Deserialize, Clone, Ord, PartialOrd, Eq, PartialEq, Hash, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum Filter {
// This is attr - value
#[serde(alias = "Eq")]
Eq(String, String),
#[serde(alias = "Cnt")]
Cnt(String, String),
#[serde(alias = "Pres")]
Pres(String),
#[serde(alias = "Or")]
Or(Vec<Filter>),
#[serde(alias = "And")]
And(Vec<Filter>),
#[serde(alias = "AndNot")]
AndNot(Box<Filter>),
#[serde(rename = "self", alias = "Self")]
SelfUuid,
}
#[derive(Serialize, Deserialize, Debug, Clone, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum Modify {
Present(String, String),
Removed(String, String),
Purged(String),
}
#[derive(Serialize, Deserialize, Debug, Clone, ToSchema)]
pub struct ModifyList {
pub mods: Vec<Modify>,
}
impl ModifyList {
pub fn new_list(mods: Vec<Modify>) -> Self {
ModifyList { mods }
}
}
#[derive(Debug, Serialize, Deserialize, ToSchema)]
pub struct SearchRequest {
pub filter: Filter,
}
impl SearchRequest {
pub fn new(filter: Filter) -> Self {
SearchRequest { filter }
}
}
#[derive(Debug, Serialize, Deserialize, ToSchema)]
pub struct SearchResponse {
pub entries: Vec<Entry>,
}
impl SearchResponse {
pub fn new(entries: Vec<Entry>) -> Self {
SearchResponse { entries }
}
}
#[derive(Debug, Serialize, Deserialize, ToSchema)]
pub struct CreateRequest {
pub entries: Vec<Entry>,
}
impl CreateRequest {
pub fn new(entries: Vec<Entry>) -> Self {
CreateRequest { entries }
}
}
#[derive(Debug, Serialize, Deserialize, ToSchema)]
pub struct DeleteRequest {
pub filter: Filter,
}
impl DeleteRequest {
pub fn new(filter: Filter) -> Self {
DeleteRequest { filter }
}
}
#[derive(Debug, Serialize, Deserialize, ToSchema)]
pub struct ModifyRequest {
// Probably needs a modlist?
pub filter: Filter,
pub modlist: ModifyList,
}
impl ModifyRequest {
pub fn new(filter: Filter, modlist: ModifyList) -> Self {
ModifyRequest { filter, modlist }
}
}
#[cfg(test)]
mod tests {
use super::Filter as ProtoFilter;
use crate::constants::ATTR_CLASS;
#[test]
fn test_protofilter_simple() {
let pf: ProtoFilter = ProtoFilter::Pres(ATTR_CLASS.to_string());
println!("{:?}", serde_json::to_string(&pf).expect("JSON failure"));
}
}

200
proto/src/internal/token.rs Normal file
View file

@ -0,0 +1,200 @@
use super::UiHint;
use serde::{Deserialize, Serialize};
use std::collections::BTreeSet;
use std::fmt;
use time::OffsetDateTime;
use utoipa::ToSchema;
use uuid::Uuid;
use serde_with::skip_serializing_none;
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum UatPurpose {
ReadOnly,
ReadWrite {
/// If none, there is no expiry, and this is always rw. If there is
/// an expiry, check that the current time < expiry.
#[serde(with = "time::serde::timestamp::option")]
expiry: Option<time::OffsetDateTime>,
},
}
/// The currently authenticated user, and any required metadata for them
/// to properly authorise them. This is similar in nature to oauth and the krb
/// PAC/PAD structures. This information is transparent to clients and CAN
/// be parsed by them!
///
/// This structure and how it works will *very much* change over time from this
/// point onward! This means on updates, that sessions will invalidate in many
/// cases.
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
#[skip_serializing_none]
#[serde(rename_all = "lowercase")]
pub struct UserAuthToken {
pub session_id: Uuid,
#[serde(with = "time::serde::timestamp")]
pub issued_at: time::OffsetDateTime,
/// If none, there is no expiry, and this is always valid. If there is
/// an expiry, check that the current time < expiry.
#[serde(with = "time::serde::timestamp::option")]
pub expiry: Option<time::OffsetDateTime>,
pub purpose: UatPurpose,
pub uuid: Uuid,
pub displayname: String,
pub spn: String,
pub mail_primary: Option<String>,
pub ui_hints: BTreeSet<UiHint>,
pub limit_search_max_results: Option<u64>,
pub limit_search_max_filter_test: Option<u64>,
}
impl fmt::Display for UserAuthToken {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "spn: {}", self.spn)?;
writeln!(f, "uuid: {}", self.uuid)?;
writeln!(f, "display: {}", self.displayname)?;
if let Some(exp) = self.expiry {
writeln!(f, "expiry: {}", exp)?;
} else {
writeln!(f, "expiry: -")?;
}
match &self.purpose {
UatPurpose::ReadOnly => writeln!(f, "purpose: read only")?,
UatPurpose::ReadWrite {
expiry: Some(expiry),
} => writeln!(f, "purpose: read write (expiry: {})", expiry)?,
UatPurpose::ReadWrite { expiry: None } => {
writeln!(f, "purpose: read write (expiry: none)")?
}
}
Ok(())
}
}
impl PartialEq for UserAuthToken {
fn eq(&self, other: &Self) -> bool {
self.session_id == other.session_id
}
}
impl Eq for UserAuthToken {}
impl UserAuthToken {
pub fn name(&self) -> &str {
self.spn.split_once('@').map(|x| x.0).unwrap_or(&self.spn)
}
/// Show if the uat at a current point in time has active read-write
/// capabilities.
pub fn purpose_readwrite_active(&self, ct: time::OffsetDateTime) -> bool {
match self.purpose {
UatPurpose::ReadWrite { expiry: Some(exp) } => ct < exp,
_ => false,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone, Default, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum ApiTokenPurpose {
#[default]
ReadOnly,
ReadWrite,
Synchronise,
}
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
#[serde(rename_all = "lowercase")]
pub struct ApiToken {
// The account this is associated with.
pub account_id: Uuid,
pub token_id: Uuid,
pub label: String,
#[serde(with = "time::serde::timestamp::option")]
pub expiry: Option<time::OffsetDateTime>,
#[serde(with = "time::serde::timestamp")]
pub issued_at: time::OffsetDateTime,
// Defaults to ReadOnly if not present
#[serde(default)]
pub purpose: ApiTokenPurpose,
}
impl fmt::Display for ApiToken {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "account_id: {}", self.account_id)?;
writeln!(f, "token_id: {}", self.token_id)?;
writeln!(f, "label: {}", self.label)?;
writeln!(f, "issued at: {}", self.issued_at)?;
if let Some(expiry) = self.expiry {
// if this fails we're in trouble!
#[allow(clippy::expect_used)]
let expiry_str = expiry
.to_offset(
time::UtcOffset::local_offset_at(OffsetDateTime::UNIX_EPOCH)
.unwrap_or(time::UtcOffset::UTC),
)
.format(&time::format_description::well_known::Rfc3339)
.expect("Failed to format timestamp to RFC3339");
writeln!(f, "token expiry: {}", expiry_str)
} else {
writeln!(f, "token expiry: never")
}
}
}
impl PartialEq for ApiToken {
fn eq(&self, other: &Self) -> bool {
self.token_id == other.token_id
}
}
impl Eq for ApiToken {}
// This is similar to uat, but omits claims (they have no role in radius), and adds
// the radius secret field.
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
pub struct RadiusAuthToken {
pub name: String,
pub displayname: String,
pub uuid: String,
pub secret: String,
pub groups: Vec<Group>,
}
impl fmt::Display for RadiusAuthToken {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "name: {}", self.name)?;
writeln!(f, "displayname: {}", self.displayname)?;
writeln!(f, "uuid: {}", self.uuid)?;
writeln!(f, "secret: {}", self.secret)?;
self.groups
.iter()
.try_for_each(|g| writeln!(f, "group: {}", g))
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
#[serde(rename_all = "lowercase")]
pub struct ScimSyncToken {
// uuid of the token?
pub token_id: Uuid,
#[serde(with = "time::serde::timestamp")]
pub issued_at: time::OffsetDateTime,
#[serde(default)]
pub purpose: ApiTokenPurpose,
}
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
pub struct Group {
pub spn: String,
pub uuid: String,
}
impl fmt::Display for Group {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[ spn: {}, ", self.spn)?;
write!(f, "uuid: {} ]", self.uuid)
}
}

View file

@ -1,5 +1,14 @@
//! Kanidm JSON protocol definitions
//!
//! This library defines the elements that are used by Kanidm's http APIs.
//! Each module has different support levels which define the projects policy
//! on change for the module.
#![deny(warnings)] #![deny(warnings)]
#![warn(unused_extern_crates)] #![warn(unused_extern_crates)]
// #![warn(missing_docs)]
#![deny(clippy::todo)]
#![deny(clippy::unimplemented)]
#![deny(clippy::unwrap_used)] #![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)] #![deny(clippy::expect_used)]
#![deny(clippy::panic)] #![deny(clippy::panic)]

View file

@ -1,3 +1,5 @@
//! Oauth2 RFC protocol definitions.
use std::collections::{BTreeMap, BTreeSet}; use std::collections::{BTreeMap, BTreeSet};
use base64urlsafedata::Base64UrlSafeData; use base64urlsafedata::Base64UrlSafeData;
@ -20,6 +22,8 @@ pub struct PkceRequest {
pub code_challenge_method: CodeChallengeMethod, pub code_challenge_method: CodeChallengeMethod,
} }
/// An OAuth2 client redirects to the authorisation server with Authorisation Request
/// parameters.
#[skip_serializing_none] #[skip_serializing_none]
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct AuthorisationRequest { pub struct AuthorisationRequest {
@ -40,6 +44,8 @@ pub struct AuthorisationRequest {
pub unknown_keys: BTreeMap<String, serde_json::value::Value>, pub unknown_keys: BTreeMap<String, serde_json::value::Value>,
} }
/// An OIDC client redirects to the authorisation server with Authorisation Request
/// parameters.
#[skip_serializing_none] #[skip_serializing_none]
#[derive(Serialize, Deserialize, Debug, Clone, Default)] #[derive(Serialize, Deserialize, Debug, Clone, Default)]
pub struct AuthorisationRequestOidc { pub struct AuthorisationRequestOidc {
@ -53,8 +59,9 @@ pub struct AuthorisationRequestOidc {
pub acr: Option<String>, pub acr: Option<String>,
} }
/// When we request to authorise, it can either prompt us for consent, /// In response to an Authorisation request, the user may be prompted to consent to the
/// or it can immediately be granted due the past grant. /// scopes requested by the OAuth2 client. If they have previously consented, they will
/// immediately proceed.
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub enum AuthorisationResponse { pub enum AuthorisationResponse {
ConsentRequested { ConsentRequested {
@ -74,7 +81,6 @@ pub enum AuthorisationResponse {
#[serde_as] #[serde_as]
#[skip_serializing_none] #[skip_serializing_none]
// this is the equivalent of serde(skip_serializing_if = "Option::is_none") applied to ALL the options
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
#[serde(tag = "grant_type", rename_all = "snake_case")] #[serde(tag = "grant_type", rename_all = "snake_case")]
pub enum GrantTypeReq { pub enum GrantTypeReq {
@ -96,6 +102,7 @@ pub enum GrantTypeReq {
}, },
} }
/// An Access Token request. This requires a set of grant-type parameters to satisfy the request.
#[skip_serializing_none] #[skip_serializing_none]
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct AccessTokenRequest { pub struct AccessTokenRequest {
@ -117,43 +124,45 @@ impl From<GrantTypeReq> for AccessTokenRequest {
} }
} }
#[skip_serializing_none] /// The
#[derive(Serialize, Deserialize, Debug)]
pub struct TokenRevokeRequest {
pub token: String,
/// Generally not needed. See:
/// <https://datatracker.ietf.org/doc/html/rfc7009#section-4.1.2>
pub token_type_hint: Option<String>,
}
// The corresponding Response to a revoke request is empty body with 200.
#[skip_serializing_none] #[skip_serializing_none]
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct AccessTokenResponse { pub struct AccessTokenResponse {
// Could be Base64UrlSafeData
pub access_token: String, pub access_token: String,
// Enum?
pub token_type: String, pub token_type: String,
// seconds. /// Expiration relative to `now` in seconds.
pub expires_in: u32, pub expires_in: u32,
pub refresh_token: Option<String>, pub refresh_token: Option<String>,
/// Space separated list of scopes that were approved, if this differs from the /// Space separated list of scopes that were approved, if this differs from the
/// original request. /// original request.
pub scope: Option<String>, pub scope: Option<String>,
/// Oidc puts the token here. /// If the `openid` scope was requested, an `id_token` may be present in the response.
pub id_token: Option<String>, pub id_token: Option<String>,
} }
/// Request revocation of an Access or Refresh token. On success the response is OK 200
/// with no body.
#[skip_serializing_none] #[skip_serializing_none]
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct AccessTokenIntrospectRequest { pub struct TokenRevokeRequest {
pub token: String, pub token: String,
/// Generally not needed. See: /// Not required for Kanidm.
/// <https://datatracker.ietf.org/doc/html/rfc7009#section-4.1.2> /// <https://datatracker.ietf.org/doc/html/rfc7009#section-4.1.2>
pub token_type_hint: Option<String>, pub token_type_hint: Option<String>,
} }
/// Request to introspect the identity of the account associated to a token.
#[skip_serializing_none]
#[derive(Serialize, Deserialize, Debug)]
pub struct AccessTokenIntrospectRequest {
pub token: String,
/// Not required for Kanidm.
/// <https://datatracker.ietf.org/doc/html/rfc7009#section-4.1.2>
pub token_type_hint: Option<String>,
}
/// Response to an introspection request. If the token is inactive or revoked, only
/// `active` will be set to the value of `false`.
#[skip_serializing_none] #[skip_serializing_none]
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
pub struct AccessTokenIntrospectResponse { pub struct AccessTokenIntrospectResponse {
@ -235,8 +244,9 @@ pub enum PkceAlg {
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
#[serde(rename_all = "UPPERCASE")] #[serde(rename_all = "UPPERCASE")]
// WE REFUSE TO SUPPORT NONE. DONT EVEN ASK. IT WON'T HAPPEN. /// Algorithms supported for token signatures. Prefers `ES256`
pub enum IdTokenSignAlg { pub enum IdTokenSignAlg {
// WE REFUSE TO SUPPORT NONE. DONT EVEN ASK. IT WON'T HAPPEN.
ES256, ES256,
RS256, RS256,
} }
@ -292,9 +302,10 @@ fn require_request_uri_parameter_supported_default() -> bool {
false false
} }
/// The response to an OpenID connect discovery request
/// <https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata>
#[skip_serializing_none] #[skip_serializing_none]
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
// https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
pub struct OidcDiscoveryResponse { pub struct OidcDiscoveryResponse {
pub issuer: Url, pub issuer: Url,
pub authorization_endpoint: Url, pub authorization_endpoint: Url,
@ -354,9 +365,9 @@ pub struct OidcDiscoveryResponse {
pub code_challenge_methods_supported: Vec<PkceAlg>, pub code_challenge_methods_supported: Vec<PkceAlg>,
} }
/// The response to an OAuth2 rfc8414 metadata request
#[skip_serializing_none] #[skip_serializing_none]
#[derive(Serialize, Deserialize, Debug)] #[derive(Serialize, Deserialize, Debug)]
// https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderMetadata
pub struct Oauth2Rfc8414MetadataResponse { pub struct Oauth2Rfc8414MetadataResponse {
pub issuer: Url, pub issuer: Url,
pub authorization_endpoint: Url, pub authorization_endpoint: Url,

3
proto/src/scim_v1/mod.rs Normal file
View file

@ -0,0 +1,3 @@
mod synch;
pub use self::synch::*;

View file

@ -60,11 +60,14 @@ pub const SCIM_DIGITS: &str = "digits";
pub const SCIM_SECRET: &str = "secret"; pub const SCIM_SECRET: &str = "secret";
pub const SCIM_STEP: &str = "step"; pub const SCIM_STEP: &str = "step";
pub const SCIM_SCHEMA_SYNC: &str = "urn:ietf:params:scim:schemas:kanidm:1.0:"; pub const SCIM_SCHEMA_SYNC_1: &str = "urn:ietf:params:scim:schemas:kanidm:sync:1:";
pub const SCIM_SCHEMA_SYNC_PERSON: &str = "urn:ietf:params:scim:schemas:kanidm:1.0:person"; pub const SCIM_SCHEMA_SYNC_ACCOUNT: &str = "urn:ietf:params:scim:schemas:kanidm:sync:1:account";
pub const SCIM_SCHEMA_SYNC_ACCOUNT: &str = "urn:ietf:params:scim:schemas:kanidm:1.0:account"; pub const SCIM_SCHEMA_SYNC_GROUP: &str = "urn:ietf:params:scim:schemas:kanidm:sync:1:group";
pub const SCIM_SCHEMA_SYNC_PERSON: &str = "urn:ietf:params:scim:schemas:kanidm:sync:1:person";
pub const SCIM_SCHEMA_SYNC_POSIXACCOUNT: &str = pub const SCIM_SCHEMA_SYNC_POSIXACCOUNT: &str =
"urn:ietf:params:scim:schemas:kanidm:1.0:posixaccount"; "urn:ietf:params:scim:schemas:kanidm:sync:1:posixaccount";
pub const SCIM_SCHEMA_SYNC_POSIXGROUP: &str =
"urn:ietf:params:scim:schemas:kanidm:sync:1:posixgroup";
#[derive(Serialize, Debug, Clone)] #[derive(Serialize, Debug, Clone)]
pub struct ScimTotp { pub struct ScimTotp {
@ -206,9 +209,6 @@ impl Into<ScimEntry> for ScimSyncPerson {
} }
} }
pub const SCIM_SCHEMA_SYNC_GROUP: &str = "urn:ietf:params:scim:schemas:kanidm:1.0:group";
pub const SCIM_SCHEMA_SYNC_POSIXGROUP: &str = "urn:ietf:params:scim:schemas:kanidm:1.0:posixgroup";
#[derive(Serialize, Debug, Clone)] #[derive(Serialize, Debug, Clone)]
pub struct ScimExternalMember { pub struct ScimExternalMember {
pub external_id: String, pub external_id: String,

File diff suppressed because it is too large Load diff

189
proto/src/v1/auth.rs Normal file
View file

@ -0,0 +1,189 @@
use serde::{Deserialize, Serialize};
use std::cmp::Ordering;
use std::fmt;
use utoipa::ToSchema;
use uuid::Uuid;
use webauthn_rs_proto::PublicKeyCredential;
use webauthn_rs_proto::RequestChallengeResponse;
/// Authentication to Kanidm is a stepped process.
///
/// The session is fist initialised with the requested username.
///
/// In response the list of supported authentication mechanisms is provided.
///
/// The user chooses the authentication mechanism to proceed with.
///
/// The server responds with a challenge that the user provides a credential
/// to satisfy. This challenge and response process continues until a credential
/// fails to validate, an error occurs, or successful authentication is complete.
#[derive(Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum AuthStep {
/// Initialise a new authentication session
Init(String),
/// Initialise a new authentication session with extra flags
/// for requesting different types of session tokens or
/// immediate access to privileges.
Init2 {
username: String,
issue: AuthIssueSession,
#[serde(default)]
/// If true, the session will have r/w access.
privileged: bool,
},
/// Request the named authentication mechanism to proceed
Begin(AuthMech),
/// Provide a credential in response to a challenge
Cred(AuthCredential),
}
/// The response to an AuthStep request.
#[derive(Debug, Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum AuthState {
/// You need to select how you want to proceed.
Choose(Vec<AuthMech>),
/// Continue to auth, allowed mechanisms/challenges listed.
Continue(Vec<AuthAllowed>),
/// Something was bad, your session is terminated and no cookie.
Denied(String),
/// Everything is good, your bearer token has been issued and is within.
Success(String),
}
/// The credential challenge provided by a user.
#[derive(Serialize, Deserialize, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum AuthCredential {
Anonymous,
Password(String),
Totp(u32),
SecurityKey(Box<PublicKeyCredential>),
BackupCode(String),
// Should this just be discoverable?
Passkey(Box<PublicKeyCredential>),
}
impl fmt::Debug for AuthCredential {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
match self {
AuthCredential::Anonymous => write!(fmt, "Anonymous"),
AuthCredential::Password(_) => write!(fmt, "Password(_)"),
AuthCredential::Totp(_) => write!(fmt, "TOTP(_)"),
AuthCredential::SecurityKey(_) => write!(fmt, "SecurityKey(_)"),
AuthCredential::BackupCode(_) => write!(fmt, "BackupCode(_)"),
AuthCredential::Passkey(_) => write!(fmt, "Passkey(_)"),
}
}
}
/// The mechanisms that may proceed in this authentication
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialOrd, Ord, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum AuthMech {
Anonymous,
Password,
PasswordMfa,
Passkey,
}
impl PartialEq for AuthMech {
fn eq(&self, other: &Self) -> bool {
std::mem::discriminant(self) == std::mem::discriminant(other)
}
}
impl fmt::Display for AuthMech {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AuthMech::Anonymous => write!(f, "Anonymous (no credentials)"),
AuthMech::Password => write!(f, "Password"),
AuthMech::PasswordMfa => write!(f, "TOTP/Backup Code and Password"),
AuthMech::Passkey => write!(f, "Passkey"),
}
}
}
/// The type of session that should be issued to the client.
#[derive(Debug, Serialize, Deserialize, Copy, Clone, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum AuthIssueSession {
// Previously supported other types beside token.
Token,
}
/// A request for the next step of an authentication.
#[derive(Debug, Serialize, Deserialize, ToSchema)]
pub struct AuthRequest {
pub step: AuthStep,
}
/// A challenge containing the list of allowed authentication types
/// that can satisfy the next step. These may have inner types with
/// required context.
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum AuthAllowed {
Anonymous,
BackupCode,
Password,
Totp,
SecurityKey(RequestChallengeResponse),
Passkey(RequestChallengeResponse),
}
impl PartialEq for AuthAllowed {
fn eq(&self, other: &Self) -> bool {
std::mem::discriminant(self) == std::mem::discriminant(other)
}
}
impl From<&AuthAllowed> for u8 {
fn from(a: &AuthAllowed) -> u8 {
match a {
AuthAllowed::Anonymous => 0,
AuthAllowed::Password => 1,
AuthAllowed::BackupCode => 2,
AuthAllowed::Totp => 3,
AuthAllowed::Passkey(_) => 4,
AuthAllowed::SecurityKey(_) => 5,
}
}
}
impl Eq for AuthAllowed {}
impl Ord for AuthAllowed {
fn cmp(&self, other: &Self) -> Ordering {
let self_ord: u8 = self.into();
let other_ord: u8 = other.into();
self_ord.cmp(&other_ord)
}
}
impl PartialOrd for AuthAllowed {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl fmt::Display for AuthAllowed {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
AuthAllowed::Anonymous => write!(f, "Anonymous (no credentials)"),
AuthAllowed::Password => write!(f, "Password"),
AuthAllowed::BackupCode => write!(f, "Backup Code"),
AuthAllowed::Totp => write!(f, "TOTP"),
AuthAllowed::SecurityKey(_) => write!(f, "Security Token"),
AuthAllowed::Passkey(_) => write!(f, "Passkey"),
}
}
}
#[derive(Debug, Serialize, Deserialize, ToSchema)]
pub struct AuthResponse {
pub sessionid: Uuid,
pub state: AuthState,
}

149
proto/src/v1/mod.rs Normal file
View file

@ -0,0 +1,149 @@
//! Kanidm Version 1
//!
//! Items defined in this module will remain stable, or change in ways that are forward
//! compatible with newer releases.
#![allow(non_upper_case_globals)]
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use std::fmt;
use utoipa::ToSchema;
use uuid::Uuid;
mod auth;
mod unix;
pub use self::auth::*;
pub use self::unix::*;
/// The type of Account in use.
#[derive(Clone, Copy, Debug, ToSchema)]
pub enum AccountType {
Person,
ServiceAccount,
}
impl ToString for AccountType {
fn to_string(&self) -> String {
match self {
AccountType::Person => "person".to_string(),
AccountType::ServiceAccount => "service_account".to_string(),
}
}
}
/* ===== higher level types ===== */
// These are all types that are conceptually layers on top of entry and
// friends. They allow us to process more complex requests and provide
// domain specific fields for the purposes of IDM, over the normal
// entry/ava/filter types. These related deeply to schema.
/// The current purpose of a User Auth Token. It may be read-only, read-write
/// or privilige capable (able to step up to read-write after re-authentication).
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum UatPurposeStatus {
ReadOnly,
ReadWrite,
PrivilegeCapable,
}
/// The expiry of the User Auth Token.
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
#[serde(rename_all = "lowercase")]
pub enum UatStatusState {
#[serde(with = "time::serde::timestamp")]
ExpiresAt(time::OffsetDateTime),
NeverExpires,
Revoked,
}
impl fmt::Display for UatStatusState {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
UatStatusState::ExpiresAt(odt) => write!(f, "expires at {}", odt),
UatStatusState::NeverExpires => write!(f, "never expires"),
UatStatusState::Revoked => write!(f, "revoked"),
}
}
}
/// The status of a User Auth Token
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
#[serde(rename_all = "lowercase")]
pub struct UatStatus {
pub account_id: Uuid,
pub session_id: Uuid,
pub state: UatStatusState,
#[serde(with = "time::serde::timestamp")]
pub issued_at: time::OffsetDateTime,
pub purpose: UatPurposeStatus,
}
impl fmt::Display for UatStatus {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "account_id: {}", self.account_id)?;
writeln!(f, "session_id: {}", self.session_id)?;
writeln!(f, "state: {}", self.state)?;
writeln!(f, "issued_at: {}", self.issued_at)?;
match &self.purpose {
UatPurposeStatus::ReadOnly => writeln!(f, "purpose: read only")?,
UatPurposeStatus::ReadWrite => writeln!(f, "purpose: read write")?,
UatPurposeStatus::PrivilegeCapable => writeln!(f, "purpose: privilege capable")?,
}
Ok(())
}
}
/// A request to generate a new API token for a service account
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
#[serde(rename_all = "lowercase")]
pub struct ApiTokenGenerate {
pub label: String,
#[serde(with = "time::serde::timestamp::option")]
pub expiry: Option<time::OffsetDateTime>,
pub read_write: bool,
}
/* ===== low level proto types ===== */
/// A limited view of an entry in Kanidm.
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, Default, ToSchema)]
pub struct Entry {
pub attrs: BTreeMap<String, Vec<String>>,
}
impl fmt::Display for Entry {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "---")?;
self.attrs
.iter()
.try_for_each(|(k, vs)| vs.iter().try_for_each(|v| writeln!(f, "{}: {}", k, v)))
}
}
/// A response to a whoami request
#[derive(Debug, Serialize, Deserialize, Clone, PartialEq, Eq, ToSchema)]
pub struct WhoamiResponse {
// Should we just embed the entry? Or destructure it?
pub youare: Entry,
}
impl WhoamiResponse {
pub fn new(youare: Entry) -> Self {
WhoamiResponse { youare }
}
}
// Simple string value provision.
#[derive(Debug, Serialize, Deserialize, ToSchema)]
pub struct SingleStringRequest {
pub value: String,
}
impl SingleStringRequest {
pub fn new(s: String) -> Self {
SingleStringRequest { value: s }
}
}

80
proto/src/v1/unix.rs Normal file
View file

@ -0,0 +1,80 @@
use serde::{Deserialize, Serialize};
use std::fmt;
use utoipa::ToSchema;
use uuid::Uuid;
use serde_with::skip_serializing_none;
use crate::constants::{ATTR_GROUP, ATTR_LDAP_SSHPUBLICKEY};
/// A token representing the details of a unix group
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
pub struct UnixGroupToken {
pub name: String,
pub spn: String,
pub uuid: Uuid,
pub gidnumber: u32,
}
impl fmt::Display for UnixGroupToken {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "[ spn: {}, ", self.spn)?;
write!(f, "gidnumber: {} ", self.gidnumber)?;
write!(f, "name: {}, ", self.name)?;
write!(f, "uuid: {} ]", self.uuid)
}
}
/// Request addition of unix attributes to a group.
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
pub struct GroupUnixExtend {
pub gidnumber: Option<u32>,
}
/// A token representing the details of a unix user
#[skip_serializing_none]
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
pub struct UnixUserToken {
pub name: String,
pub spn: String,
pub displayname: String,
pub gidnumber: u32,
pub uuid: Uuid,
pub shell: Option<String>,
pub groups: Vec<UnixGroupToken>,
pub sshkeys: Vec<String>,
// The default value of bool is false.
#[serde(default)]
pub valid: bool,
}
impl fmt::Display for UnixUserToken {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
writeln!(f, "---")?;
writeln!(f, "spn: {}", self.spn)?;
writeln!(f, "name: {}", self.name)?;
writeln!(f, "displayname: {}", self.displayname)?;
writeln!(f, "uuid: {}", self.uuid)?;
match &self.shell {
Some(s) => writeln!(f, "shell: {}", s)?,
None => writeln!(f, "shell: <none>")?,
}
self.sshkeys
.iter()
.try_for_each(|s| writeln!(f, "{}: {}", ATTR_LDAP_SSHPUBLICKEY, s))?;
self.groups
.iter()
.try_for_each(|g| writeln!(f, "{}: {}", ATTR_GROUP, g))
}
}
/// Request addition of unix attributes to an account
#[derive(Debug, Serialize, Deserialize, Clone, ToSchema)]
#[serde(deny_unknown_fields)]
pub struct AccountUnixExtend {
pub gidnumber: Option<u32>,
// TODO: rename shell to loginshell everywhere we can find
/// The internal attribute is "loginshell" but we use shell in the API currently
#[serde(alias = "loginshell")]
pub shell: Option<String>,
}

View file

@ -54,7 +54,6 @@ toml = { workspace = true }
tower = { version = "0.4.13", features = ["tokio-stream", "tracing"] } tower = { version = "0.4.13", features = ["tokio-stream", "tracing"] }
tower-http = { version = "0.4.4", features = [ tower-http = { version = "0.4.4", features = [
"compression-gzip", "compression-gzip",
"compression-zstd",
"fs", "fs",
"tokio", "tokio",
"trace", "trace",

View file

@ -1,3 +1,4 @@
fn main() { fn main() {
profiles::apply_profile(); profiles::apply_profile();
println!("cargo:rerun-if-changed=build.rs");
} }

View file

@ -4,11 +4,14 @@ use std::net::IpAddr;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::Arc; use std::sync::Arc;
use kanidm_proto::internal::{AppLink, IdentifyUserRequest, IdentifyUserResponse, ImageValue}; use kanidm_proto::internal::{
ApiToken, AppLink, BackupCodesView, CURequest, CUSessionToken, CUStatus, CredentialStatus,
IdentifyUserRequest, IdentifyUserResponse, ImageValue, OperationError, RadiusAuthToken,
SearchRequest, SearchResponse, UserAuthToken,
};
use kanidm_proto::v1::{ use kanidm_proto::v1::{
ApiToken, AuthIssueSession, AuthRequest, BackupCodesView, CURequest, CUSessionToken, CUStatus, AuthIssueSession, AuthRequest, Entry as ProtoEntry, UatStatus, UnixGroupToken, UnixUserToken,
CredentialStatus, Entry as ProtoEntry, OperationError, RadiusAuthToken, SearchRequest, WhoamiResponse,
SearchResponse, UatStatus, UnixGroupToken, UnixUserToken, UserAuthToken, WhoamiResponse,
}; };
use kanidmd_lib::idm::identityverification::{ use kanidmd_lib::idm::identityverification::{
IdentifyUserDisplayCodeEvent, IdentifyUserStartEvent, IdentifyUserSubmitCodeEvent, IdentifyUserDisplayCodeEvent, IdentifyUserStartEvent, IdentifyUserSubmitCodeEvent,

View file

@ -1,13 +1,12 @@
use std::{iter, sync::Arc}; use std::{iter, sync::Arc};
use kanidm_proto::internal::DomainInfo as ProtoDomainInfo; use kanidm_proto::internal::{
use kanidm_proto::internal::ImageValue; CUIntentToken, CUSessionToken, CUStatus, CreateRequest, DeleteRequest,
use kanidm_proto::internal::Oauth2ClaimMapJoin as ProtoOauth2ClaimMapJoin; DomainInfo as ProtoDomainInfo, ImageValue, Modify as ProtoModify,
use kanidm_proto::v1::{ ModifyList as ProtoModifyList, ModifyRequest, Oauth2ClaimMapJoin as ProtoOauth2ClaimMapJoin,
AccountUnixExtend, CUIntentToken, CUSessionToken, CUStatus, CreateRequest, DeleteRequest, OperationError,
Entry as ProtoEntry, GroupUnixExtend, Modify as ProtoModify, ModifyList as ProtoModifyList,
ModifyRequest, OperationError,
}; };
use kanidm_proto::v1::{AccountUnixExtend, Entry as ProtoEntry, GroupUnixExtend};
use time::OffsetDateTime; use time::OffsetDateTime;
use tracing::{info, instrument, span, trace, Instrument, Level}; use tracing::{info, instrument, span, trace, Instrument, Level};
use uuid::Uuid; use uuid::Uuid;

View file

@ -1,5 +1,5 @@
use axum::{middleware::from_fn, response::Redirect, routing::get, Router}; use axum::{middleware::from_fn, response::Redirect, routing::get, Router};
use kanidm_proto::{scim_v1, v1}; use kanidm_proto::{internal, scim_v1, v1};
use utoipa::{ use utoipa::{
openapi::security::{HttpAuthScheme, HttpBuilder, SecurityScheme}, openapi::security::{HttpAuthScheme, HttpBuilder, SecurityScheme},
Modify, OpenApi, Modify, OpenApi,
@ -189,57 +189,56 @@ impl Modify for SecurityAddon {
// TODO: can't add Entry/ProtoEntry to schema as this was only recently supported utoipa v3.5.0 doesn't support it - ref <https://github.com/juhaku/utoipa/pull/756/files> // TODO: can't add Entry/ProtoEntry to schema as this was only recently supported utoipa v3.5.0 doesn't support it - ref <https://github.com/juhaku/utoipa/pull/756/files>
// v1::Entry, // v1::Entry,
v1::AccountUnixExtend, v1::AccountUnixExtend,
v1::ApiToken, internal::ApiToken,
v1::ApiTokenGenerate, v1::ApiTokenGenerate,
v1::AuthRequest, v1::AuthRequest,
v1::AuthResponse, v1::AuthResponse,
v1::AuthState, v1::AuthState,
v1::BackupCodesView, internal::BackupCodesView,
v1::Claim, internal::CreateRequest,
v1::CreateRequest, internal::CredentialDetail,
v1::CredentialDetail, internal::CredentialStatus,
v1::CredentialStatus, internal::CUIntentToken,
v1::CUIntentToken, internal::CUSessionToken,
v1::CUSessionToken, internal::CUStatus,
v1::CUStatus, internal::DeleteRequest,
v1::DeleteRequest, internal::Group,
v1::Group,
v1::GroupUnixExtend, v1::GroupUnixExtend,
v1::ModifyList, internal::ModifyList,
v1::ModifyRequest, internal::ModifyRequest,
v1::PasskeyDetail, internal::PasskeyDetail,
v1::RadiusAuthToken, internal::RadiusAuthToken,
v1::SearchRequest, internal::SearchRequest,
v1::SearchResponse, internal::SearchResponse,
v1::SingleStringRequest, v1::SingleStringRequest,
v1::TotpSecret, internal::TotpSecret,
v1::TotpAlgo, internal::TotpAlgo,
v1::UatStatus, v1::UatStatus,
v1::UnixGroupToken, v1::UnixGroupToken,
v1::UnixUserToken, v1::UnixUserToken,
v1::UserAuthToken, internal::UserAuthToken,
v1::WhoamiResponse, v1::WhoamiResponse,
v1::ApiTokenPurpose, internal::ApiTokenPurpose,
v1::AuthStep, v1::AuthStep,
v1::AuthIssueSession, v1::AuthIssueSession,
v1::AuthMech, v1::AuthMech,
v1::AuthCredential, v1::AuthCredential,
v1::AuthAllowed, v1::AuthAllowed,
v1::CUExtPortal, internal::CUExtPortal,
v1::CURegState, internal::CURegState,
v1::CredentialDetailType, internal::CredentialDetailType,
v1::Entry, v1::Entry,
v1::Filter, internal::Filter,
v1::Modify, internal::Modify,
v1::UatStatusState, v1::UatStatusState,
v1::UatPurposeStatus, v1::UatPurposeStatus,
v1::UatPurpose, internal::UatPurpose,
v1::OperationError, internal::OperationError,
v1::SchemaError, internal::SchemaError,
v1::PluginError, internal::PluginError,
v1::PasswordFeedback, internal::PasswordFeedback,
kanidm_proto::internal::IdentifyUserRequest, internal::IdentifyUserRequest,
// terrible workaround for other things // terrible workaround for other things
response_schema::CreationChallengeResponse, response_schema::CreationChallengeResponse,
// terrible workaround for other things // terrible workaround for other things

View file

@ -4,7 +4,7 @@
use axum::http::header::ACCESS_CONTROL_ALLOW_ORIGIN; use axum::http::header::ACCESS_CONTROL_ALLOW_ORIGIN;
use axum::http::{HeaderValue, StatusCode}; use axum::http::{HeaderValue, StatusCode};
use axum::response::{IntoResponse, Response}; use axum::response::{IntoResponse, Response};
use kanidm_proto::v1::OperationError; use kanidm_proto::internal::OperationError;
use utoipa::ToSchema; use utoipa::ToSchema;
/// The web app's top level error type, this takes an `OperationError` and converts it into a HTTP response. /// The web app's top level error type, this takes an `OperationError` and converts it into a HTTP response.

View file

@ -12,13 +12,15 @@ use serde::{Deserialize, Serialize};
use std::net::IpAddr; use std::net::IpAddr;
use uuid::Uuid; use uuid::Uuid;
use kanidm_proto::internal::{AppLink, IdentifyUserRequest, IdentifyUserResponse}; use kanidm_proto::internal::{
ApiToken, AppLink, CUIntentToken, CURequest, CUSessionToken, CUStatus, CreateRequest,
CredentialStatus, DeleteRequest, IdentifyUserRequest, IdentifyUserResponse, ModifyRequest,
RadiusAuthToken, SearchRequest, SearchResponse, UserAuthToken,
};
use kanidm_proto::v1::{ use kanidm_proto::v1::{
AccountUnixExtend, ApiToken, ApiTokenGenerate, AuthIssueSession, AuthRequest, AuthResponse, AccountUnixExtend, ApiTokenGenerate, AuthIssueSession, AuthRequest, AuthResponse,
AuthState as ProtoAuthState, CUIntentToken, CURequest, CUSessionToken, CUStatus, CreateRequest, AuthState as ProtoAuthState, Entry as ProtoEntry, GroupUnixExtend, SingleStringRequest,
CredentialStatus, DeleteRequest, Entry as ProtoEntry, GroupUnixExtend, ModifyRequest, UatStatus, UnixGroupToken, UnixUserToken, WhoamiResponse,
RadiusAuthToken, SearchRequest, SearchResponse, SingleStringRequest, UatStatus, UnixGroupToken,
UnixUserToken, UserAuthToken, WhoamiResponse,
}; };
use kanidmd_lib::idm::event::AuthResult; use kanidmd_lib::idm::event::AuthResult;
use kanidmd_lib::idm::AuthState; use kanidmd_lib::idm::AuthState;

View file

@ -40,7 +40,7 @@ use std::sync::Arc;
use crate::utils::touch_file_or_quit; use crate::utils::touch_file_or_quit;
use compact_jwt::JwsHs256Signer; use compact_jwt::JwsHs256Signer;
use kanidm_proto::v1::OperationError; use kanidm_proto::internal::OperationError;
use kanidmd_lib::be::{Backend, BackendConfig, BackendTransaction}; use kanidmd_lib::be::{Backend, BackendConfig, BackendTransaction};
use kanidmd_lib::idm::ldap::LdapServer; use kanidmd_lib::idm::ldap::LdapServer;
use kanidmd_lib::prelude::*; use kanidmd_lib::prelude::*;

View file

@ -11,6 +11,9 @@ include!("src/opt.rs");
fn main() { fn main() {
profiles::apply_profile(); profiles::apply_profile();
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-env-changed=OUT_DIR");
println!("cargo:rerun-if-changed=src/opt.rs");
let outdir = match env::var_os("OUT_DIR") { let outdir = match env::var_os("OUT_DIR") {
None => return, None => return,
Some(outdir) => outdir, Some(outdir) => outdir,

View file

@ -1,10 +1,10 @@
// include!("src/lib/audit_loglevel.rs");
use hashbrown::HashMap; use hashbrown::HashMap;
use std::env; use std::env;
fn main() { fn main() {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-env-changed=DEP_OPENSSL_VERSION_NUMBER");
if let Ok(v) = env::var("DEP_OPENSSL_VERSION_NUMBER") { if let Ok(v) = env::var("DEP_OPENSSL_VERSION_NUMBER") {
let version = u64::from_str_radix(&v, 16).unwrap(); let version = u64::from_str_radix(&v, 16).unwrap();
@ -16,6 +16,7 @@ fn main() {
profiles::apply_profile(); profiles::apply_profile();
// check we don't have duplicate UUIDs // check we don't have duplicate UUIDs
println!("cargo:rerun-if-changed=src/constants/uuids.rs");
let uuid_filename = format!( let uuid_filename = format!(
"{}/{}", "{}/{}",
env!("CARGO_MANIFEST_DIR"), env!("CARGO_MANIFEST_DIR"),

View file

@ -10,7 +10,7 @@ use concread::cowcell::*;
use hashbrown::HashMap; use hashbrown::HashMap;
use idlset::v2::IDLBitRange; use idlset::v2::IDLBitRange;
use idlset::AndNot; use idlset::AndNot;
use kanidm_proto::v1::{ConsistencyError, OperationError}; use kanidm_proto::internal::{ConsistencyError, OperationError};
use tracing::trace; use tracing::trace;
use uuid::Uuid; use uuid::Uuid;

View file

@ -9,7 +9,7 @@ use super::keystorage::{KeyHandle, KeyHandleId};
// use crate::valueset; // use crate::valueset;
use hashbrown::HashMap; use hashbrown::HashMap;
use idlset::v2::IDLBitRange; use idlset::v2::IDLBitRange;
use kanidm_proto::v1::{ConsistencyError, OperationError}; use kanidm_proto::internal::{ConsistencyError, OperationError};
use rusqlite::vtab::array::Array; use rusqlite::vtab::array::Array;
use rusqlite::{Connection, OpenFlags, OptionalExtension}; use rusqlite::{Connection, OpenFlags, OptionalExtension};
use uuid::Uuid; use uuid::Uuid;

View file

@ -14,7 +14,7 @@ use concread::cowcell::*;
use hashbrown::{HashMap as Map, HashSet}; use hashbrown::{HashMap as Map, HashSet};
use idlset::v2::IDLBitRange; use idlset::v2::IDLBitRange;
use idlset::AndNot; use idlset::AndNot;
use kanidm_proto::v1::{ConsistencyError, OperationError}; use kanidm_proto::internal::{ConsistencyError, OperationError};
use smartstring::alias::String as AttrString; use smartstring::alias::String as AttrString;
use tracing::{trace, trace_span}; use tracing::{trace, trace_span};
use uuid::Uuid; use uuid::Uuid;

View file

@ -5,7 +5,7 @@ use crate::constants::uuids::*;
use crate::entry::EntryInitNew; use crate::entry::EntryInitNew;
use crate::prelude::*; use crate::prelude::*;
use crate::value::Value; use crate::value::Value;
use kanidm_proto::v1::Filter as ProtoFilter; use kanidm_proto::internal::Filter as ProtoFilter;
lazy_static! { lazy_static! {
/// either recycled or tombstone /// either recycled or tombstone

View file

@ -10,7 +10,8 @@ use crate::idm::account::Account;
use crate::value::PartialValue; use crate::value::PartialValue;
use crate::value::Value; use crate::value::Value;
use kanidm_proto::constants::*; use kanidm_proto::constants::*;
use kanidm_proto::v1::{AccountType, OperationError}; use kanidm_proto::internal::OperationError;
use kanidm_proto::v1::AccountType;
#[cfg(test)] #[cfg(test)]
use uuid::uuid; use uuid::uuid;

View file

@ -1,7 +1,7 @@
use crate::entry::EntryInitNew; use crate::entry::EntryInitNew;
use crate::prelude::*; use crate::prelude::*;
use kanidm_proto::v1::{Filter, OperationError, UiHint}; use kanidm_proto::internal::{Filter, OperationError, UiHint};
#[derive(Clone, Debug, Default)] #[derive(Clone, Debug, Default)]
/// Built-in group definitions /// Built-in group definitions

View file

@ -1,7 +1,9 @@
use std::convert::TryFrom; use std::convert::TryFrom;
use hashbrown::{HashMap as Map, HashSet}; use hashbrown::{HashMap as Map, HashSet};
use kanidm_proto::v1::{BackupCodesView, CredentialDetail, CredentialDetailType, OperationError}; use kanidm_proto::internal::{
BackupCodesView, CredentialDetail, CredentialDetailType, OperationError,
};
use uuid::Uuid; use uuid::Uuid;
use webauthn_rs::prelude::{AuthenticationResult, Passkey, SecurityKey}; use webauthn_rs::prelude::{AuthenticationResult, Passkey, SecurityKey};
use webauthn_rs_core::proto::{Credential as WebauthnCredential, CredentialV3}; use webauthn_rs_core::proto::{Credential as WebauthnCredential, CredentialV3};

View file

@ -1,7 +1,7 @@
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
use std::time::{Duration, SystemTime}; use std::time::{Duration, SystemTime};
use kanidm_proto::v1::{TotpAlgo as ProtoTotpAlgo, TotpSecret as ProtoTotp}; use kanidm_proto::internal::{TotpAlgo as ProtoTotpAlgo, TotpSecret as ProtoTotp};
use openssl::hash::MessageDigest; use openssl::hash::MessageDigest;
use openssl::pkey::PKey; use openssl::pkey::PKey;
use openssl::sign::Signer; use openssl::sign::Signer;

View file

@ -32,10 +32,10 @@ use std::sync::Arc;
use compact_jwt::JwsEs256Signer; use compact_jwt::JwsEs256Signer;
use hashbrown::{HashMap, HashSet}; use hashbrown::{HashMap, HashSet};
use kanidm_proto::internal::ImageValue; use kanidm_proto::internal::ImageValue;
use kanidm_proto::v1::{ use kanidm_proto::internal::{
ConsistencyError, Entry as ProtoEntry, Filter as ProtoFilter, OperationError, SchemaError, ConsistencyError, Filter as ProtoFilter, OperationError, SchemaError, UiHint,
UiHint,
}; };
use kanidm_proto::v1::Entry as ProtoEntry;
use ldap3_proto::simple::{LdapPartialAttribute, LdapSearchResultEntry}; use ldap3_proto::simple::{LdapPartialAttribute, LdapSearchResultEntry};
use openssl::ec::EcKey; use openssl::ec::EcKey;
use openssl::pkey::{Private, Public}; use openssl::pkey::{Private, Public};

View file

@ -19,10 +19,11 @@ use std::collections::BTreeSet;
#[cfg(test)] #[cfg(test)]
use std::sync::Arc; use std::sync::Arc;
use kanidm_proto::v1::{ use kanidm_proto::internal::{
CreateRequest, DeleteRequest, Entry as ProtoEntry, ModifyList as ProtoModifyList, CreateRequest, DeleteRequest, ModifyList as ProtoModifyList, ModifyRequest, OperationError,
ModifyRequest, OperationError, SearchRequest, SearchResponse, WhoamiResponse, SearchRequest, SearchResponse,
}; };
use kanidm_proto::v1::{Entry as ProtoEntry, WhoamiResponse};
use ldap3_proto::simple::LdapFilter; use ldap3_proto::simple::LdapFilter;
use uuid::Uuid; use uuid::Uuid;

View file

@ -20,7 +20,7 @@ use hashbrown::HashMap;
#[cfg(test)] #[cfg(test)]
use hashbrown::HashSet; use hashbrown::HashSet;
use kanidm_proto::constants::ATTR_UUID; use kanidm_proto::constants::ATTR_UUID;
use kanidm_proto::v1::{Filter as ProtoFilter, OperationError, SchemaError}; use kanidm_proto::internal::{Filter as ProtoFilter, OperationError, SchemaError};
use ldap3_proto::proto::{LdapFilter, LdapSubstringFilter}; use ldap3_proto::proto::{LdapFilter, LdapSubstringFilter};
// use smartstring::alias::String as AttrString; // use smartstring::alias::String as AttrString;
use serde::Deserialize; use serde::Deserialize;
@ -1574,7 +1574,7 @@ mod tests {
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::time::Duration; use std::time::Duration;
use kanidm_proto::v1::Filter as ProtoFilter; use kanidm_proto::internal::Filter as ProtoFilter;
use ldap3_proto::simple::LdapFilter; use ldap3_proto::simple::LdapFilter;
use crate::event::{CreateEvent, DeleteEvent}; use crate::event::{CreateEvent, DeleteEvent};

View file

@ -1,10 +1,10 @@
use std::collections::{BTreeMap, BTreeSet}; use std::collections::{BTreeMap, BTreeSet};
use std::time::Duration; use std::time::Duration;
use kanidm_proto::v1::{ use kanidm_proto::internal::{
BackupCodesView, CredentialStatus, OperationError, UatPurpose, UatStatus, UatStatusState, BackupCodesView, CredentialStatus, UatPurpose, UiHint, UserAuthToken,
UiHint, UserAuthToken,
}; };
use kanidm_proto::v1::{UatStatus, UatStatusState};
use time::OffsetDateTime; use time::OffsetDateTime;
use uuid::Uuid; use uuid::Uuid;
use webauthn_rs::prelude::{ use webauthn_rs::prelude::{
@ -925,7 +925,7 @@ mod tests {
use crate::idm::account::Account; use crate::idm::account::Account;
use crate::idm::accountpolicy::ResolvedAccountPolicy; use crate::idm::accountpolicy::ResolvedAccountPolicy;
use crate::prelude::*; use crate::prelude::*;
use kanidm_proto::v1::UiHint; use kanidm_proto::internal::UiHint;
#[test] #[test]
fn test_idm_account_from_anonymous() { fn test_idm_account_from_anonymous() {

View file

@ -9,9 +9,8 @@ use std::time::Duration;
use compact_jwt::{Jws, JwsEs256Signer, JwsSigner}; use compact_jwt::{Jws, JwsEs256Signer, JwsSigner};
use hashbrown::HashSet; use hashbrown::HashSet;
use kanidm_proto::v1::{ use kanidm_proto::internal::UserAuthToken;
AuthAllowed, AuthCredential, AuthIssueSession, AuthMech, OperationError, UserAuthToken, use kanidm_proto::v1::{AuthAllowed, AuthCredential, AuthIssueSession, AuthMech};
};
use nonempty::{nonempty, NonEmpty}; use nonempty::{nonempty, NonEmpty};
use tokio::sync::mpsc::UnboundedSender as Sender; use tokio::sync::mpsc::UnboundedSender as Sender;
use uuid::Uuid; use uuid::Uuid;
@ -1482,9 +1481,8 @@ mod tests {
use compact_jwt::{JwsCompact, JwsEs256Signer, JwsEs256Verifier, JwsVerifier}; use compact_jwt::{JwsCompact, JwsEs256Signer, JwsEs256Verifier, JwsVerifier};
use hashbrown::HashSet; use hashbrown::HashSet;
use kanidm_proto::v1::{ use kanidm_proto::internal::{UatPurpose, UserAuthToken};
AuthAllowed, AuthCredential, AuthIssueSession, AuthMech, UatPurpose, UserAuthToken, use kanidm_proto::v1::{AuthAllowed, AuthCredential, AuthIssueSession, AuthMech};
};
use tokio::sync::mpsc::unbounded_channel as unbounded; use tokio::sync::mpsc::unbounded_channel as unbounded;
use webauthn_authenticator_rs::softpasskey::SoftPasskey; use webauthn_authenticator_rs::softpasskey::SoftPasskey;
use webauthn_authenticator_rs::WebauthnAuthenticator; use webauthn_authenticator_rs::WebauthnAuthenticator;

View file

@ -7,7 +7,7 @@ use std::time::Duration;
use sshkey_attest::proto::PublicKey as SshPublicKey; use sshkey_attest::proto::PublicKey as SshPublicKey;
use hashbrown::HashSet; use hashbrown::HashSet;
use kanidm_proto::v1::{ use kanidm_proto::internal::{
CUCredState, CUExtPortal, CURegState, CURegWarning, CUStatus, CredentialDetail, PasskeyDetail, CUCredState, CUExtPortal, CURegState, CURegWarning, CUStatus, CredentialDetail, PasskeyDetail,
PasswordFeedback, TotpSecret, PasswordFeedback, TotpSecret,
}; };
@ -2312,10 +2312,8 @@ impl<'a> IdmServerCredUpdateTransaction<'a> {
mod tests { mod tests {
use std::time::Duration; use std::time::Duration;
use kanidm_proto::v1::{ use kanidm_proto::internal::{CUExtPortal, CredentialDetailType, PasswordFeedback};
AuthAllowed, AuthIssueSession, AuthMech, CUExtPortal, CredentialDetailType, use kanidm_proto::v1::{AuthAllowed, AuthIssueSession, AuthMech};
PasswordFeedback,
};
use uuid::uuid; use uuid::uuid;
use webauthn_authenticator_rs::softpasskey::SoftPasskey; use webauthn_authenticator_rs::softpasskey::SoftPasskey;
use webauthn_authenticator_rs::softtoken::{self, SoftToken}; use webauthn_authenticator_rs::softtoken::{self, SoftToken};

View file

@ -1,6 +1,5 @@
use crate::idm::AuthState; use crate::idm::AuthState;
use crate::prelude::*; use crate::prelude::*;
use kanidm_proto::v1::OperationError;
use kanidm_proto::v1::{AuthCredential, AuthIssueSession, AuthMech, AuthRequest, AuthStep}; use kanidm_proto::v1::{AuthCredential, AuthIssueSession, AuthMech, AuthRequest, AuthStep};
#[cfg(test)] #[cfg(test)]

View file

@ -1,7 +1,6 @@
use std::collections::BTreeSet; use std::collections::BTreeSet;
use kanidm_proto::v1::UiHint; use kanidm_proto::internal::{Group as ProtoGroup, UiHint};
use kanidm_proto::v1::{Group as ProtoGroup, OperationError};
use uuid::Uuid; use uuid::Uuid;
use super::accountpolicy::{AccountPolicy, ResolvedAccountPolicy}; use super::accountpolicy::{AccountPolicy, ResolvedAccountPolicy};

View file

@ -1,6 +1,7 @@
use crate::prelude::*;
use std::time::SystemTime; use std::time::SystemTime;
use kanidm_proto::{internal::IdentifyUserResponse, v1::OperationError}; use kanidm_proto::internal::IdentifyUserResponse;
use openssl::ec::EcKey; use openssl::ec::EcKey;
use openssl::pkey::{PKey, Private, Public}; use openssl::pkey::{PKey, Private, Public};
use openssl::pkey_ctx::PkeyCtx; use openssl::pkey_ctx::PkeyCtx;
@ -8,7 +9,6 @@ use sketching::admin_error;
use uuid::Uuid; use uuid::Uuid;
use crate::credential::totp::{Totp, TotpAlgo, TotpDigits}; use crate::credential::totp::{Totp, TotpAlgo, TotpDigits};
use crate::prelude::{tagged_event, Attribute, EventTag};
use crate::server::QueryServerTransaction; use crate::server::QueryServerTransaction;
use crate::{event::SearchEvent, server::identity::Identity}; use crate::{event::SearchEvent, server::identity::Identity};

View file

@ -5,7 +5,7 @@ use std::collections::BTreeSet;
use std::iter; use std::iter;
use kanidm_proto::constants::*; use kanidm_proto::constants::*;
use kanidm_proto::v1::{ApiToken, OperationError, UserAuthToken}; use kanidm_proto::internal::{ApiToken, UserAuthToken};
use ldap3_proto::simple::*; use ldap3_proto::simple::*;
use regex::Regex; use regex::Regex;
use std::net::IpAddr; use std::net::IpAddr;
@ -621,7 +621,7 @@ mod tests {
use compact_jwt::{JwsCompact, JwsEs256Verifier, JwsVerifier}; use compact_jwt::{JwsCompact, JwsEs256Verifier, JwsVerifier};
use hashbrown::HashSet; use hashbrown::HashSet;
use kanidm_proto::v1::ApiToken; use kanidm_proto::internal::ApiToken;
use ldap3_proto::proto::{LdapFilter, LdapOp, LdapSearchScope, LdapSubstringFilter}; use ldap3_proto::proto::{LdapFilter, LdapOp, LdapSearchScope, LdapSubstringFilter};
use ldap3_proto::simple::*; use ldap3_proto::simple::*;

View file

@ -2551,8 +2551,8 @@ mod tests {
OidcSubject, OidcUnverified, OidcSubject, OidcUnverified,
}; };
use kanidm_proto::constants::*; use kanidm_proto::constants::*;
use kanidm_proto::internal::UserAuthToken;
use kanidm_proto::oauth2::*; use kanidm_proto::oauth2::*;
use kanidm_proto::v1::UserAuthToken;
use openssl::sha; use openssl::sha;
use crate::idm::accountpolicy::ResolvedAccountPolicy; use crate::idm::accountpolicy::ResolvedAccountPolicy;

View file

@ -1,6 +1,6 @@
use std::time::Duration; use std::time::Duration;
use kanidm_proto::v1::{OperationError, RadiusAuthToken}; use kanidm_proto::internal::RadiusAuthToken;
use time::OffsetDateTime; use time::OffsetDateTime;
use uuid::Uuid; use uuid::Uuid;

View file

@ -3,9 +3,8 @@ use std::time::Duration;
use base64urlsafedata::Base64UrlSafeData; use base64urlsafedata::Base64UrlSafeData;
use compact_jwt::{Jws, JwsEs256Signer, JwsSigner}; use compact_jwt::{Jws, JwsEs256Signer, JwsSigner};
use kanidm_proto::internal::ScimSyncToken; use kanidm_proto::internal::{ApiTokenPurpose, ScimSyncToken};
use kanidm_proto::scim_v1::*; use kanidm_proto::scim_v1::*;
use kanidm_proto::v1::ApiTokenPurpose;
use std::collections::{BTreeMap, BTreeSet}; use std::collections::{BTreeMap, BTreeSet};
use crate::credential::totp::{Totp, TotpAlgo, TotpDigits}; use crate::credential::totp::{Totp, TotpAlgo, TotpDigits};
@ -1150,7 +1149,7 @@ impl<'a> IdmServerProxyWriteTransaction<'a> {
// What classes did they request for this entry to sync? // What classes did they request for this entry to sync?
let requested_classes = scim_ent.schemas.iter() let requested_classes = scim_ent.schemas.iter()
.map(|schema| { .map(|schema| {
schema.as_str().strip_prefix(SCIM_SCHEMA_SYNC) schema.as_str().strip_prefix(SCIM_SCHEMA_SYNC_1)
.ok_or_else(|| { .ok_or_else(|| {
error!(?schema, "Invalid requested schema - Not a kanidm sync schema."); error!(?schema, "Invalid requested schema - Not a kanidm sync schema.");
OperationError::InvalidEntryState OperationError::InvalidEntryState
@ -1537,8 +1536,8 @@ mod tests {
use crate::prelude::*; use crate::prelude::*;
use base64urlsafedata::Base64UrlSafeData; use base64urlsafedata::Base64UrlSafeData;
use compact_jwt::{Jws, JwsSigner}; use compact_jwt::{Jws, JwsSigner};
use kanidm_proto::internal::ApiTokenPurpose;
use kanidm_proto::scim_v1::*; use kanidm_proto::scim_v1::*;
use kanidm_proto::v1::ApiTokenPurpose;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
@ -2094,7 +2093,7 @@ mod tests {
assert!(apply_phase_3_test( assert!(apply_phase_3_test(
idms, idms,
vec![ScimEntry { vec![ScimEntry {
schemas: vec![format!("{SCIM_SCHEMA_SYNC}system")], schemas: vec![format!("{SCIM_SCHEMA_SYNC_1}system")],
id: user_sync_uuid, id: user_sync_uuid,
external_id: Some("cn=testgroup,ou=people,dc=test".to_string()), external_id: Some("cn=testgroup,ou=people,dc=test".to_string()),
meta: None, meta: None,
@ -3168,9 +3167,9 @@ mod tests {
"entries": [ "entries": [
{ {
"schemas": [ "schemas": [
"urn:ietf:params:scim:schemas:kanidm:1.0:person", "urn:ietf:params:scim:schemas:kanidm:sync:1:person",
"urn:ietf:params:scim:schemas:kanidm:1.0:account", "urn:ietf:params:scim:schemas:kanidm:sync:1:account",
"urn:ietf:params:scim:schemas:kanidm:1.0:posixaccount" "urn:ietf:params:scim:schemas:kanidm:sync:1:posixaccount"
], ],
"id": "babb8302-43a1-11ed-a50d-919b4b1a5ec0", "id": "babb8302-43a1-11ed-a50d-919b4b1a5ec0",
"externalId": "uid=testuser,cn=users,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au", "externalId": "uid=testuser,cn=users,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au",
@ -3194,7 +3193,7 @@ mod tests {
}, },
{ {
"schemas": [ "schemas": [
"urn:ietf:params:scim:schemas:kanidm:1.0:group" "urn:ietf:params:scim:schemas:kanidm:sync:1:group"
], ],
"id": "d547c581-5f26-11ed-a50d-919b4b1a5ec0", "id": "d547c581-5f26-11ed-a50d-919b4b1a5ec0",
"externalId": "cn=testgroup,cn=groups,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au", "externalId": "cn=testgroup,cn=groups,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au",
@ -3208,7 +3207,7 @@ mod tests {
}, },
{ {
"schemas": [ "schemas": [
"urn:ietf:params:scim:schemas:kanidm:1.0:group" "urn:ietf:params:scim:schemas:kanidm:sync:1:group"
], ],
"id": "d547c583-5f26-11ed-a50d-919b4b1a5ec0", "id": "d547c583-5f26-11ed-a50d-919b4b1a5ec0",
"externalId": "cn=testexternal,cn=groups,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au", "externalId": "cn=testexternal,cn=groups,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au",
@ -3216,8 +3215,8 @@ mod tests {
}, },
{ {
"schemas": [ "schemas": [
"urn:ietf:params:scim:schemas:kanidm:1.0:group", "urn:ietf:params:scim:schemas:kanidm:sync:1:group",
"urn:ietf:params:scim:schemas:kanidm:1.0:posixgroup" "urn:ietf:params:scim:schemas:kanidm:sync:1:posixgroup"
], ],
"id": "f90b0b81-5f26-11ed-a50d-919b4b1a5ec0", "id": "f90b0b81-5f26-11ed-a50d-919b4b1a5ec0",
"externalId": "cn=testposix,cn=groups,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au", "externalId": "cn=testposix,cn=groups,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au",
@ -3249,7 +3248,7 @@ mod tests {
"entries": [ "entries": [
{ {
"schemas": [ "schemas": [
"urn:ietf:params:scim:schemas:kanidm:1.0:group" "urn:ietf:params:scim:schemas:kanidm:sync:1:group"
], ],
"id": "d547c583-5f26-11ed-a50d-919b4b1a5ec0", "id": "d547c583-5f26-11ed-a50d-919b4b1a5ec0",
"externalId": "cn=testexternal2,cn=groups,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au", "externalId": "cn=testexternal2,cn=groups,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au",
@ -3262,8 +3261,8 @@ mod tests {
}, },
{ {
"schemas": [ "schemas": [
"urn:ietf:params:scim:schemas:kanidm:1.0:group", "urn:ietf:params:scim:schemas:kanidm:sync:1:group",
"urn:ietf:params:scim:schemas:kanidm:1.0:posixgroup" "urn:ietf:params:scim:schemas:kanidm:sync:1:posixgroup"
], ],
"id": "f90b0b81-5f26-11ed-a50d-919b4b1a5ec0", "id": "f90b0b81-5f26-11ed-a50d-919b4b1a5ec0",
"externalId": "cn=testposix,cn=groups,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au", "externalId": "cn=testposix,cn=groups,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au",
@ -3290,9 +3289,9 @@ mod tests {
"entries": [ "entries": [
{ {
"schemas": [ "schemas": [
"urn:ietf:params:scim:schemas:kanidm:1.0:person", "urn:ietf:params:scim:schemas:kanidm:sync:1:person",
"urn:ietf:params:scim:schemas:kanidm:1.0:account", "urn:ietf:params:scim:schemas:kanidm:sync:1:account",
"urn:ietf:params:scim:schemas:kanidm:1.0:posixaccount" "urn:ietf:params:scim:schemas:kanidm:sync:1:posixaccount"
], ],
"id": "babb8302-43a1-11ed-a50d-919b4b1a5ec0", "id": "babb8302-43a1-11ed-a50d-919b4b1a5ec0",
"externalId": "uid=testuser,cn=users,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au", "externalId": "uid=testuser,cn=users,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au",
@ -3307,7 +3306,7 @@ mod tests {
}, },
{ {
"schemas": [ "schemas": [
"urn:ietf:params:scim:schemas:kanidm:1.0:group" "urn:ietf:params:scim:schemas:kanidm:sync:1:group"
], ],
"id": "d547c581-5f26-11ed-a50d-919b4b1a5ec0", "id": "d547c581-5f26-11ed-a50d-919b4b1a5ec0",
"externalId": "cn=testgroup,cn=groups,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au", "externalId": "cn=testgroup,cn=groups,cn=accounts,dc=dev,dc=blackhats,dc=net,dc=au",

View file

@ -11,11 +11,11 @@ use concread::cowcell::{CowCellReadTxn, CowCellWriteTxn};
use concread::hashmap::HashMap; use concread::hashmap::HashMap;
use concread::CowCell; use concread::CowCell;
use fernet::Fernet; use fernet::Fernet;
use kanidm_proto::internal::ScimSyncToken; use kanidm_proto::internal::{
use kanidm_proto::v1::{ ApiToken, BackupCodesView, CredentialStatus, PasswordFeedback, RadiusAuthToken, ScimSyncToken,
ApiToken, BackupCodesView, CredentialStatus, PasswordFeedback, RadiusAuthToken, UatPurpose, UatPurpose, UserAuthToken,
UnixGroupToken, UnixUserToken, UserAuthToken,
}; };
use kanidm_proto::v1::{UnixGroupToken, UnixUserToken};
use rand::prelude::*; use rand::prelude::*;
use tokio::sync::mpsc::{ use tokio::sync::mpsc::{
unbounded_channel as unbounded, UnboundedReceiver as Receiver, UnboundedSender as Sender, unbounded_channel as unbounded, UnboundedReceiver as Receiver, UnboundedSender as Sender,
@ -2165,7 +2165,7 @@ mod tests {
use std::convert::TryFrom; use std::convert::TryFrom;
use std::time::Duration; use std::time::Duration;
use kanidm_proto::v1::{AuthAllowed, AuthIssueSession, AuthMech, OperationError}; use kanidm_proto::v1::{AuthAllowed, AuthIssueSession, AuthMech};
use time::OffsetDateTime; use time::OffsetDateTime;
use uuid::Uuid; use uuid::Uuid;
@ -3592,7 +3592,7 @@ mod tests {
idms: &IdmServer, idms: &IdmServer,
idms_delayed: &mut IdmServerDelayed, idms_delayed: &mut IdmServerDelayed,
) { ) {
use kanidm_proto::v1::UserAuthToken; use kanidm_proto::internal::UserAuthToken;
use std::str::FromStr; use std::str::FromStr;
let ct = Duration::from_secs(TEST_CURRENT_TIME); let ct = Duration::from_secs(TEST_CURRENT_TIME);

View file

@ -2,7 +2,7 @@ use std::collections::BTreeMap;
use std::time::Duration; use std::time::Duration;
use compact_jwt::{Jws, JwsEs256Signer, JwsSigner}; use compact_jwt::{Jws, JwsEs256Signer, JwsSigner};
use kanidm_proto::v1::ApiToken as ProtoApiToken; use kanidm_proto::internal::ApiToken as ProtoApiToken;
use time::OffsetDateTime; use time::OffsetDateTime;
use crate::credential::Credential; use crate::credential::Credential;
@ -14,21 +14,6 @@ use crate::prelude::*;
use crate::utils::password_from_random; use crate::utils::password_from_random;
use crate::value::ApiToken; use crate::value::ApiToken;
// Need to add KID to es256 der for lookups ✅
// Need to generate the es256 on the account on modifies ✅
// Add migration to generate the es256 on startup at least once. ✅
// Create new valueset type to store sessions w_ labels ✅
// Able to lookup from KID to get service account
// Able to take token -> ident
// -- check still valid
// revoke
macro_rules! try_from_entry { macro_rules! try_from_entry {
($value:expr) => {{ ($value:expr) => {{
// Check the classes // Check the classes
@ -432,7 +417,7 @@ mod tests {
use std::time::Duration; use std::time::Duration;
use compact_jwt::{JwsCompact, JwsEs256Verifier, JwsVerifier}; use compact_jwt::{JwsCompact, JwsEs256Verifier, JwsVerifier};
use kanidm_proto::v1::ApiToken; use kanidm_proto::internal::ApiToken;
use super::{DestroyApiTokenEvent, GenerateApiTokenEvent}; use super::{DestroyApiTokenEvent, GenerateApiTokenEvent};
use crate::event::CreateEvent; use crate::event::CreateEvent;

View file

@ -2,7 +2,7 @@ use std::iter;
// use crossbeam::channel::Sender; // use crossbeam::channel::Sender;
use std::time::Duration; use std::time::Duration;
use kanidm_proto::v1::{OperationError, UnixGroupToken, UnixUserToken}; use kanidm_proto::v1::{UnixGroupToken, UnixUserToken};
use time::OffsetDateTime; use time::OffsetDateTime;
use tokio::sync::mpsc::UnboundedSender as Sender; use tokio::sync::mpsc::UnboundedSender as Sender;
use uuid::Uuid; use uuid::Uuid;

View file

@ -63,7 +63,7 @@ pub mod testkit;
/// help make imports cleaner. /// help make imports cleaner.
pub mod prelude { pub mod prelude {
pub use kanidm_proto::constants::*; pub use kanidm_proto::constants::*;
pub use kanidm_proto::v1::{ConsistencyError, OperationError, SchemaError}; pub use kanidm_proto::internal::{ConsistencyError, OperationError, PluginError, SchemaError};
pub use sketching::{ pub use sketching::{
admin_debug, admin_error, admin_info, admin_warn, filter_error, filter_info, filter_trace, admin_debug, admin_error, admin_info, admin_warn, filter_error, filter_info, filter_trace,
filter_warn, perf_trace, request_error, request_info, request_trace, request_warn, filter_warn, perf_trace, request_error, request_info, request_trace, request_warn,

View file

@ -4,10 +4,10 @@
use std::slice; use std::slice;
use kanidm_proto::v1::{ use kanidm_proto::internal::{
Entry as ProtoEntry, Modify as ProtoModify, ModifyList as ProtoModifyList, OperationError, Modify as ProtoModify, ModifyList as ProtoModifyList, OperationError, SchemaError,
SchemaError,
}; };
use kanidm_proto::v1::Entry as ProtoEntry;
// Should this be std? // Should this be std?
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use smartstring::alias::String as AttrString; use smartstring::alias::String as AttrString;

View file

@ -8,7 +8,6 @@ use std::collections::VecDeque;
use std::collections::{BTreeMap, BTreeSet}; use std::collections::{BTreeMap, BTreeSet};
use std::sync::Arc; use std::sync::Arc;
use kanidm_proto::v1::{ConsistencyError, PluginError};
use tracing::trace; use tracing::trace;
use crate::event::{CreateEvent, ModifyEvent}; use crate::event::{CreateEvent, ModifyEvent};
@ -491,8 +490,6 @@ impl Plugin for AttrUnique {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use kanidm_proto::v1::PluginError;
use crate::prelude::*; use crate::prelude::*;
// Test entry in db, and same name, reject. // Test entry in db, and same name, reject.

View file

@ -3,7 +3,6 @@ use std::iter::once;
use std::sync::Arc; use std::sync::Arc;
use hashbrown::HashSet; use hashbrown::HashSet;
use kanidm_proto::v1::{ConsistencyError, PluginError};
use crate::event::{CreateEvent, ModifyEvent}; use crate::event::{CreateEvent, ModifyEvent};
use crate::modify::Modify; use crate::modify::Modify;
@ -241,7 +240,6 @@ impl Plugin for Base {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use crate::prelude::*; use crate::prelude::*;
use kanidm_proto::v1::PluginError;
use std::sync::Arc; use std::sync::Arc;
const UUID_TEST_ACCOUNT: Uuid = uuid::uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63930"); const UUID_TEST_ACCOUNT: Uuid = uuid::uuid!("cc8e95b4-c24f-4d68-ba54-8bed76f63930");

View file

@ -3,8 +3,6 @@ use std::convert::TryFrom;
use std::iter::once; use std::iter::once;
use std::sync::Arc; use std::sync::Arc;
use kanidm_proto::v1::PluginError;
use crate::credential::{Credential, Password}; use crate::credential::{Credential, Password};
use crate::event::{CreateEvent, ModifyEvent}; use crate::event::{CreateEvent, ModifyEvent};
use crate::plugins::Plugin; use crate::plugins::Plugin;
@ -171,7 +169,6 @@ mod tests {
use crate::credential::{Credential, CredentialType}; use crate::credential::{Credential, CredentialType};
use crate::prelude::*; use crate::prelude::*;
use kanidm_lib_crypto::CryptoPolicy; use kanidm_lib_crypto::CryptoPolicy;
use kanidm_proto::v1::PluginError;
const IMPORT_HASH: &str = const IMPORT_HASH: &str =
"pbkdf2_sha256$36000$xIEozuZVAoYm$uW1b35DUKyhvQAf1mBqMvoBDcqSD06juzyO/nmyV0+w="; "pbkdf2_sha256$36000$xIEozuZVAoYm$uW1b35DUKyhvQAf1mBqMvoBDcqSD06juzyO/nmyV0+w=";

View file

@ -8,7 +8,6 @@ use std::iter::once;
use std::sync::Arc; use std::sync::Arc;
use compact_jwt::JwsEs256Signer; use compact_jwt::JwsEs256Signer;
use kanidm_proto::v1::OperationError;
use rand::prelude::*; use rand::prelude::*;
use regex::Regex; use regex::Regex;
use tracing::trace; use tracing::trace;

View file

@ -1,7 +1,7 @@
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::sync::Arc; use std::sync::Arc;
use kanidm_proto::v1::Filter as ProtoFilter; use kanidm_proto::internal::Filter as ProtoFilter;
use crate::filter::FilterInvalid; use crate::filter::FilterInvalid;
use crate::prelude::*; use crate::prelude::*;
@ -378,7 +378,7 @@ impl DynGroup {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use kanidm_proto::v1::Filter as ProtoFilter; use kanidm_proto::internal::Filter as ProtoFilter;
use crate::prelude::*; use crate::prelude::*;

View file

@ -2,6 +2,7 @@ use openssl::ec::{EcGroup, EcKey};
use openssl::nid::Nid; use openssl::nid::Nid;
use crate::prelude::*; use crate::prelude::*;
use std::sync::Arc;
use super::Plugin; use super::Plugin;
@ -62,21 +63,21 @@ impl Plugin for EcdhKeyGen {
#[instrument(level = "debug", name = "ecdhkeygen::pre_modify", skip_all)] #[instrument(level = "debug", name = "ecdhkeygen::pre_modify", skip_all)]
fn pre_modify( fn pre_modify(
_qs: &mut crate::server::QueryServerWriteTransaction, _qs: &mut QueryServerWriteTransaction,
_pre_cand: &[std::sync::Arc<crate::prelude::EntrySealedCommitted>], _pre_cand: &[Arc<EntrySealedCommitted>],
cand: &mut Vec<crate::prelude::EntryInvalidCommitted>, cand: &mut Vec<EntryInvalidCommitted>,
_me: &crate::event::ModifyEvent, _me: &ModifyEvent,
) -> Result<(), kanidm_proto::v1::OperationError> { ) -> Result<(), OperationError> {
Self::generate_key(cand) Self::generate_key(cand)
} }
#[instrument(level = "debug", name = "ecdhkeygen::pre_batch_modify", skip_all)] #[instrument(level = "debug", name = "ecdhkeygen::pre_batch_modify", skip_all)]
fn pre_batch_modify( fn pre_batch_modify(
_qs: &mut crate::server::QueryServerWriteTransaction, _qs: &mut QueryServerWriteTransaction,
_pre_cand: &[std::sync::Arc<crate::prelude::EntrySealedCommitted>], _pre_cand: &[Arc<EntrySealedCommitted>],
cand: &mut Vec<crate::prelude::EntryInvalidCommitted>, cand: &mut Vec<EntryInvalidCommitted>,
_me: &crate::server::batch_modify::BatchModifyEvent, _me: &BatchModifyEvent,
) -> Result<(), kanidm_proto::v1::OperationError> { ) -> Result<(), OperationError> {
Self::generate_key(cand) Self::generate_key(cand)
} }
} }
@ -86,7 +87,7 @@ mod tests {
use openssl::ec::EcKey; use openssl::ec::EcKey;
use uuid::Uuid; use uuid::Uuid;
use crate::plugins::eckeygen::DEFAULT_KEY_GROUP; use super::DEFAULT_KEY_GROUP;
use crate::prelude::*; use crate::prelude::*;
use crate::value::Value; use crate::value::Value;
use crate::valueset; use crate::valueset;

View file

@ -14,7 +14,6 @@ use std::collections::BTreeSet;
use std::sync::Arc; use std::sync::Arc;
use hashbrown::HashMap; use hashbrown::HashMap;
use kanidm_proto::v1::{ConsistencyError, OperationError};
use crate::entry::{Entry, EntryCommitted, EntrySealed, EntryTuple}; use crate::entry::{Entry, EntryCommitted, EntrySealed, EntryTuple};
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent}; use crate::event::{CreateEvent, DeleteEvent, ModifyEvent};

View file

@ -6,8 +6,6 @@
use std::collections::BTreeSet; use std::collections::BTreeSet;
use std::sync::Arc; use std::sync::Arc;
use kanidm_proto::v1::{ConsistencyError, OperationError};
use crate::entry::{Entry, EntryCommitted, EntryInvalid, EntryNew, EntrySealed}; use crate::entry::{Entry, EntryCommitted, EntryInvalid, EntryNew, EntrySealed};
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent}; use crate::event::{CreateEvent, DeleteEvent, ModifyEvent};
use crate::prelude::*; use crate::prelude::*;

View file

@ -1,7 +1,5 @@
use std::sync::Arc; use std::sync::Arc;
use kanidm_proto::v1::OperationError;
use crate::entry::{EntryInvalidCommitted, EntrySealedCommitted}; use crate::entry::{EntryInvalidCommitted, EntrySealedCommitted};
use crate::event::ModifyEvent; use crate::event::ModifyEvent;
use crate::plugins::Plugin; use crate::plugins::Plugin;

View file

@ -13,7 +13,6 @@ use std::collections::BTreeSet;
use std::sync::Arc; use std::sync::Arc;
use hashbrown::HashSet; use hashbrown::HashSet;
use kanidm_proto::v1::ConsistencyError;
use crate::event::{CreateEvent, DeleteEvent, ModifyEvent}; use crate::event::{CreateEvent, DeleteEvent, ModifyEvent};
use crate::filter::{f_eq, FC}; use crate::filter::{f_eq, FC};
@ -439,18 +438,15 @@ impl ReferentialIntegrity {
error!(?missing); error!(?missing);
} }
Err(OperationError::Plugin( Err(OperationError::Plugin(PluginError::ReferentialIntegrity(
kanidm_proto::v1::PluginError::ReferentialIntegrity( "Uuid referenced not found in database".to_string(),
"Uuid referenced not found in database".to_string(), )))
),
))
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use kanidm_proto::v1::Filter as ProtoFilter; use kanidm_proto::internal::Filter as ProtoFilter;
use kanidm_proto::v1::PluginError;
use crate::event::CreateEvent; use crate::event::CreateEvent;
use crate::prelude::*; use crate::prelude::*;

View file

@ -4,9 +4,6 @@ use std::collections::BTreeSet;
use std::iter::once; use std::iter::once;
use std::sync::Arc; use std::sync::Arc;
// use crate::value::{PartialValue, Value};
use kanidm_proto::v1::{ConsistencyError, OperationError};
use crate::entry::{Entry, EntryCommitted, EntryInvalid, EntryNew, EntrySealed}; use crate::entry::{Entry, EntryCommitted, EntryInvalid, EntryNew, EntrySealed};
use crate::event::{CreateEvent, ModifyEvent}; use crate::event::{CreateEvent, ModifyEvent};
use crate::plugins::Plugin; use crate::plugins::Plugin;

View file

@ -3,7 +3,6 @@ use std::time::Duration;
use crate::be::dbvalue::DbCidV1; use crate::be::dbvalue::DbCidV1;
use crate::prelude::*; use crate::prelude::*;
use kanidm_proto::v1::OperationError;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, PartialEq, Clone, Eq, PartialOrd, Ord, Hash)] #[derive(Serialize, Deserialize, PartialEq, Clone, Eq, PartialOrd, Ord, Hash)]

View file

@ -8,7 +8,6 @@ use std::time::Duration;
use concread::bptree::{BptreeMap, BptreeMapReadSnapshot, BptreeMapReadTxn, BptreeMapWriteTxn}; use concread::bptree::{BptreeMap, BptreeMapReadSnapshot, BptreeMapReadTxn, BptreeMapWriteTxn};
use idlset::v2::IDLBitRange; use idlset::v2::IDLBitRange;
use kanidm_proto::v1::ConsistencyError;
use crate::prelude::*; use crate::prelude::*;
use crate::repl::cid::Cid; use crate::repl::cid::Cid;

View file

@ -20,7 +20,6 @@ use std::collections::BTreeSet;
use concread::cowcell::*; use concread::cowcell::*;
use hashbrown::{HashMap, HashSet}; use hashbrown::{HashMap, HashSet};
use kanidm_proto::v1::{ConsistencyError, OperationError, SchemaError};
use tracing::trace; use tracing::trace;
use uuid::Uuid; use uuid::Uuid;
@ -2268,13 +2267,11 @@ impl Schema {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use kanidm_proto::v1::{ConsistencyError, SchemaError};
use uuid::Uuid;
use crate::prelude::*; use crate::prelude::*;
use crate::schema::{ use crate::schema::{
IndexType, Schema, SchemaAttribute, SchemaClass, SchemaTransaction, SyntaxType, IndexType, Schema, SchemaAttribute, SchemaClass, SchemaTransaction, SyntaxType,
}; };
use uuid::Uuid;
// use crate::proto_v1::Filter as ProtoFilter; // use crate::proto_v1::Filter as ProtoFilter;

View file

@ -21,7 +21,6 @@ use std::sync::Arc;
use concread::arcache::{ARCache, ARCacheBuilder, ARCacheReadTxn}; use concread::arcache::{ARCache, ARCacheBuilder, ARCacheReadTxn};
use concread::cowcell::*; use concread::cowcell::*;
use kanidm_proto::v1::OperationError;
use tracing::trace; use tracing::trace;
use uuid::Uuid; use uuid::Uuid;

View file

@ -3,7 +3,7 @@ use std::collections::BTreeSet;
use crate::filter::{Filter, FilterValid, FilterValidResolved}; use crate::filter::{Filter, FilterValid, FilterValidResolved};
use kanidm_proto::v1::Filter as ProtoFilter; use kanidm_proto::internal::Filter as ProtoFilter;
// ========================================================================= // =========================================================================
// PARSE ENTRY TO ACP, AND ACP MANAGEMENT // PARSE ENTRY TO ACP, AND ACP MANAGEMENT

View file

@ -10,7 +10,7 @@ use std::net::IpAddr;
use std::sync::Arc; use std::sync::Arc;
use uuid::uuid; use uuid::uuid;
use kanidm_proto::v1::{ApiTokenPurpose, UatPurpose}; use kanidm_proto::internal::{ApiTokenPurpose, UatPurpose};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};

View file

@ -1,5 +1,4 @@
use crate::value::CredentialType; use crate::value::CredentialType;
use kanidm_proto::v1::SchemaError;
use std::time::Duration; use std::time::Duration;
use crate::prelude::*; use crate::prelude::*;

View file

@ -11,8 +11,7 @@ use std::collections::BTreeSet;
use tokio::sync::{Semaphore, SemaphorePermit}; use tokio::sync::{Semaphore, SemaphorePermit};
use tracing::trace; use tracing::trace;
use kanidm_proto::internal::DomainInfo as ProtoDomainInfo; use kanidm_proto::internal::{DomainInfo as ProtoDomainInfo, UiHint};
use kanidm_proto::v1::{ConsistencyError, UiHint};
use crate::be::{Backend, BackendReadTransaction, BackendTransaction, BackendWriteTransaction}; use crate::be::{Backend, BackendReadTransaction, BackendTransaction, BackendWriteTransaction};
// We use so many, we just import them all ... // We use so many, we just import them all ...

View file

@ -39,10 +39,8 @@ use crate::repl::cid::Cid;
use crate::server::identity::IdentityId; use crate::server::identity::IdentityId;
use crate::valueset::image::ImageValueThings; use crate::valueset::image::ImageValueThings;
use crate::valueset::uuid_to_proto_string; use crate::valueset::uuid_to_proto_string;
use kanidm_proto::v1::ApiTokenPurpose; use kanidm_proto::internal::{ApiTokenPurpose, Filter as ProtoFilter, UiHint};
use kanidm_proto::v1::Filter as ProtoFilter;
use kanidm_proto::v1::UatPurposeStatus; use kanidm_proto::v1::UatPurposeStatus;
use kanidm_proto::v1::UiHint;
use std::hash::Hash; use std::hash::Hash;
lazy_static! { lazy_static! {

View file

@ -4,7 +4,6 @@ use crate::be::dbvalue::DbValueSetV2;
use crate::prelude::*; use crate::prelude::*;
use crate::repl::proto::ReplAttrV1; use crate::repl::proto::ReplAttrV1;
use crate::value::{PartialValue, SyntaxType, Value}; use crate::value::{PartialValue, SyntaxType, Value};
use kanidm_proto::v1::OperationError;
use openssl::ec::EcKey; use openssl::ec::EcKey;
use openssl::pkey::{Private, Public}; use openssl::pkey::{Private, Public};
@ -73,10 +72,7 @@ impl ValueSetEcKeyPrivate {
} }
impl ValueSetT for ValueSetEcKeyPrivate { impl ValueSetT for ValueSetEcKeyPrivate {
fn insert_checked( fn insert_checked(&mut self, value: crate::value::Value) -> Result<bool, OperationError> {
&mut self,
value: crate::value::Value,
) -> Result<bool, kanidm_proto::v1::OperationError> {
match value { match value {
Value::EcKeyPrivate(k) => Ok(self.push(&k)), Value::EcKeyPrivate(k) => Ok(self.push(&k)),
_ => { _ => {
@ -190,7 +186,7 @@ impl ValueSetT for ValueSetEcKeyPrivate {
}) })
} }
fn merge(&mut self, other: &super::ValueSet) -> Result<(), kanidm_proto::v1::OperationError> { fn merge(&mut self, other: &super::ValueSet) -> Result<(), OperationError> {
if let Some(other_key) = other.as_ec_key_private() { if let Some(other_key) = other.as_ec_key_private() {
let priv_key = other_key.clone(); let priv_key = other_key.clone();
let pub_key = Self::private_key_to_public_key(&priv_key) let pub_key = Self::private_key_to_public_key(&priv_key)

View file

@ -1,4 +1,4 @@
use kanidm_proto::v1::Filter as ProtoFilter; use kanidm_proto::internal::Filter as ProtoFilter;
use smolset::SmolSet; use smolset::SmolSet;
use crate::prelude::*; use crate::prelude::*;

View file

@ -14,8 +14,7 @@ use webauthn_rs::prelude::AttestationCaList;
use webauthn_rs::prelude::AttestedPasskey as AttestedPasskeyV4; use webauthn_rs::prelude::AttestedPasskey as AttestedPasskeyV4;
use webauthn_rs::prelude::Passkey as PasskeyV4; use webauthn_rs::prelude::Passkey as PasskeyV4;
use kanidm_proto::v1::Filter as ProtoFilter; use kanidm_proto::internal::{Filter as ProtoFilter, UiHint};
use kanidm_proto::v1::UiHint;
use crate::be::dbvalue::DbValueSetV2; use crate::be::dbvalue::DbValueSetV2;
use crate::credential::{totp::Totp, Credential}; use crate::credential::{totp::Totp, Credential};

View file

@ -5,7 +5,7 @@ use crate::repl::proto::ReplAttrV1;
use crate::schema::SchemaAttribute; use crate::schema::SchemaAttribute;
use crate::valueset::{DbValueSetV2, ValueSet}; use crate::valueset::{DbValueSetV2, ValueSet};
use kanidm_proto::v1::UiHint; use kanidm_proto::internal::UiHint;
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ValueSetUiHint { pub struct ValueSetUiHint {

View file

@ -1,3 +1,4 @@
fn main() { fn main() {
profiles::apply_profile(); profiles::apply_profile();
println!("cargo:rerun-if-changed=build.rs");
} }

View file

@ -15,7 +15,7 @@ use std::sync::atomic::{AtomicU16, Ordering};
use kanidm_client::{KanidmClient, KanidmClientBuilder}; use kanidm_client::{KanidmClient, KanidmClientBuilder};
use kanidm_proto::v1::{Filter, Modify, ModifyList}; use kanidm_proto::internal::{Filter, Modify, ModifyList};
use kanidmd_core::config::{Configuration, IntegrationTestConfig}; use kanidmd_core::config::{Configuration, IntegrationTestConfig};
use kanidmd_core::{create_server_core, CoreHandle}; use kanidmd_core::{create_server_core, CoreHandle};
use kanidmd_lib::prelude::{Attribute, BUILTIN_GROUP_IDM_ADMINS_V1}; use kanidmd_lib::prelude::{Attribute, BUILTIN_GROUP_IDM_ADMINS_V1};

View file

@ -1,5 +1,6 @@
use core::result::Result::Err; use core::result::Result::Err;
use kanidm_client::KanidmClient; use kanidm_client::KanidmClient;
use kanidm_proto::internal::OperationError;
use kanidm_proto::internal::{IdentifyUserRequest, IdentifyUserResponse}; use kanidm_proto::internal::{IdentifyUserRequest, IdentifyUserResponse};
use kanidmd_lib::prelude::Attribute; use kanidmd_lib::prelude::Attribute;
@ -57,7 +58,7 @@ async fn test_non_existing_user_id(rsclient: KanidmClient) {
.idm_person_identify_user(non_existing_user, IdentifyUserRequest::Start) .idm_person_identify_user(non_existing_user, IdentifyUserRequest::Start)
.await; .await;
assert!( assert!(
matches!(dbg!(res), Err(err) if matches!(err, kanidm_client::ClientError::Http(StatusCode::NOT_FOUND, Some(kanidm_proto::v1::OperationError::NoMatchingEntries), .. ))) matches!(dbg!(res), Err(err) if matches!(err, kanidm_client::ClientError::Http(StatusCode::NOT_FOUND, Some(OperationError::NoMatchingEntries), .. )))
); );
let res = rsclient let res = rsclient
@ -65,7 +66,7 @@ async fn test_non_existing_user_id(rsclient: KanidmClient) {
.await; .await;
assert!( assert!(
matches!(dbg!(res), Err(err) if matches!(err, kanidm_client::ClientError::Http(StatusCode::NOT_FOUND, Some(kanidm_proto::v1::OperationError::NoMatchingEntries), .. ))) matches!(dbg!(res), Err(err) if matches!(err, kanidm_client::ClientError::Http(StatusCode::NOT_FOUND, Some(OperationError::NoMatchingEntries), .. )))
); );
let res = rsclient let res = rsclient
@ -76,7 +77,7 @@ async fn test_non_existing_user_id(rsclient: KanidmClient) {
.await; .await;
assert!( assert!(
matches!(dbg!(res), Err(err) if matches!(err, kanidm_client::ClientError::Http(StatusCode::NOT_FOUND, Some(kanidm_proto::v1::OperationError::NoMatchingEntries), .. ))) matches!(dbg!(res), Err(err) if matches!(err, kanidm_client::ClientError::Http(StatusCode::NOT_FOUND, Some(OperationError::NoMatchingEntries), .. )))
); );
} }

View file

@ -3,10 +3,12 @@ use std::path::Path;
use std::time::SystemTime; use std::time::SystemTime;
use kanidm_proto::constants::KSESSIONID; use kanidm_proto::constants::KSESSIONID;
use kanidm_proto::internal::ImageValue; use kanidm_proto::internal::{
ApiToken, CURegState, Filter, ImageValue, Modify, ModifyList, UatPurpose, UserAuthToken,
};
use kanidm_proto::v1::{ use kanidm_proto::v1::{
ApiToken, AuthCredential, AuthIssueSession, AuthMech, AuthRequest, AuthResponse, AuthState, AuthCredential, AuthIssueSession, AuthMech, AuthRequest, AuthResponse, AuthState, AuthStep,
AuthStep, CURegState, Entry, Filter, Modify, ModifyList, UatPurpose, UserAuthToken, Entry,
}; };
use kanidmd_lib::credential::totp::Totp; use kanidmd_lib::credential::totp::Totp;
use kanidmd_lib::prelude::{ use kanidmd_lib::prelude::{

View file

@ -1,8 +1,8 @@
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
use gloo::console; use gloo::console;
use gloo::storage::{LocalStorage, SessionStorage as TemporaryStorage, Storage}; use gloo::storage::{LocalStorage, SessionStorage as TemporaryStorage, Storage};
use kanidm_proto::internal::{CUSessionToken, CUStatus};
use kanidm_proto::oauth2::AuthorisationRequest; use kanidm_proto::oauth2::AuthorisationRequest;
use kanidm_proto::v1::{CUSessionToken, CUStatus};
use wasm_bindgen::UnwrapThrowExt; use wasm_bindgen::UnwrapThrowExt;
use crate::constants::URL_USER_HOME; use crate::constants::URL_USER_HOME;

View file

@ -1,4 +1,5 @@
use kanidm_proto::v1::{SingleStringRequest, UserAuthToken}; use kanidm_proto::internal::UserAuthToken;
use kanidm_proto::v1::SingleStringRequest;
use kanidmd_web_ui_shared::constants::ID_UNIX_PASSWORDCHANGE; use kanidmd_web_ui_shared::constants::ID_UNIX_PASSWORDCHANGE;
use kanidmd_web_ui_shared::do_request; use kanidmd_web_ui_shared::do_request;
use kanidmd_web_ui_shared::error::FetchError; use kanidmd_web_ui_shared::error::FetchError;

View file

@ -1,6 +1,6 @@
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
use gloo::console; use gloo::console;
use kanidm_proto::v1::{CUIntentToken, UserAuthToken}; use kanidm_proto::internal::{CUIntentToken, UserAuthToken};
use kanidmd_web_ui_shared::constants::{ID_CRED_RESET_CODE, URL_RESET}; use kanidmd_web_ui_shared::constants::{ID_CRED_RESET_CODE, URL_RESET};
use kanidmd_web_ui_shared::error::FetchError; use kanidmd_web_ui_shared::error::FetchError;
use kanidmd_web_ui_shared::utils::{document, modal_hide_by_id, origin}; use kanidmd_web_ui_shared::utils::{document, modal_hide_by_id, origin};

View file

@ -1,6 +1,6 @@
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
use gloo::console; use gloo::console;
use kanidm_proto::v1::{CUSessionToken, CUStatus, UiHint, UserAuthToken}; use kanidm_proto::internal::{CUSessionToken, CUStatus, UiHint, UserAuthToken};
use kanidmd_web_ui_shared::models::{ use kanidmd_web_ui_shared::models::{
push_cred_update_session, push_login_hint, push_return_location, push_cred_update_session, push_login_hint, push_return_location,
}; };

View file

@ -1,6 +1,6 @@
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
use gloo::console; use gloo::console;
use kanidm_proto::v1::{CURequest, CUSessionToken, CUStatus}; use kanidm_proto::internal::{CURequest, CUSessionToken, CUStatus};
use kanidmd_web_ui_shared::error::FetchError; use kanidmd_web_ui_shared::error::FetchError;
use kanidmd_web_ui_shared::utils::modal_hide_by_id; use kanidmd_web_ui_shared::utils::modal_hide_by_id;
use serde::Serialize; use serde::Serialize;

View file

@ -1,5 +1,5 @@
use gloo::console; use gloo::console;
use kanidm_proto::v1::{CURegState, CURequest, CUSessionToken, CUStatus}; use kanidm_proto::internal::{CURegState, CURequest, CUSessionToken, CUStatus};
use kanidm_proto::webauthn::{CreationChallengeResponse, RegisterPublicKeyCredential}; use kanidm_proto::webauthn::{CreationChallengeResponse, RegisterPublicKeyCredential};
use kanidmd_web_ui_shared::constants::CLASS_BUTTON_SUCCESS; use kanidmd_web_ui_shared::constants::CLASS_BUTTON_SUCCESS;
use kanidmd_web_ui_shared::error::FetchError; use kanidmd_web_ui_shared::error::FetchError;

View file

@ -1,6 +1,6 @@
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
use gloo::console; use gloo::console;
use kanidm_proto::v1::{CURegState, CURequest, CUSessionToken, CUStatus}; use kanidm_proto::internal::{CURegState, CURequest, CUSessionToken, CUStatus};
use serde::Serialize; use serde::Serialize;
use uuid::Uuid; use uuid::Uuid;
use wasm_bindgen::UnwrapThrowExt; use wasm_bindgen::UnwrapThrowExt;

View file

@ -1,5 +1,7 @@
use gloo::console; use gloo::console;
use kanidm_proto::v1::{CURequest, CUSessionToken, CUStatus, OperationError, PasswordFeedback}; use kanidm_proto::internal::{
CURequest, CUSessionToken, CUStatus, OperationError, PasswordFeedback,
};
use wasm_bindgen::UnwrapThrowExt; use wasm_bindgen::UnwrapThrowExt;
use serde::Serialize; use serde::Serialize;

View file

@ -1,5 +1,5 @@
use gloo::console; use gloo::console;
use kanidm_proto::v1::{ use kanidm_proto::internal::{
CUCredState, CUExtPortal, CUIntentToken, CURegWarning, CUSessionToken, CUStatus, CUCredState, CUExtPortal, CUIntentToken, CURegWarning, CUSessionToken, CUStatus,
CredentialDetail, CredentialDetailType, PasskeyDetail, CredentialDetail, CredentialDetailType, PasskeyDetail,
}; };

View file

@ -1,6 +1,6 @@
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
use gloo::console; use gloo::console;
use kanidm_proto::v1::{CURegState, CURequest, CUSessionToken, CUStatus, TotpSecret}; use kanidm_proto::internal::{CURegState, CURequest, CUSessionToken, CUStatus, TotpSecret};
use qrcode::render::svg; use qrcode::render::svg;
use qrcode::QrCode; use qrcode::QrCode;
use wasm_bindgen::UnwrapThrowExt; use wasm_bindgen::UnwrapThrowExt;

View file

@ -1,7 +1,7 @@
use super::reset::{EventBusMsg, TotpRemoveProps}; use super::reset::{EventBusMsg, TotpRemoveProps};
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
use gloo::console; use gloo::console;
use kanidm_proto::v1::{CURequest, CUSessionToken, CUStatus}; use kanidm_proto::internal::{CURequest, CUSessionToken, CUStatus};
use kanidmd_web_ui_shared::RequestMethod; use kanidmd_web_ui_shared::RequestMethod;
use kanidmd_web_ui_shared::{do_request, error::FetchError}; use kanidmd_web_ui_shared::{do_request, error::FetchError};
use serde::Serialize; use serde::Serialize;

View file

@ -2,7 +2,7 @@
#![allow(non_camel_case_types)] #![allow(non_camel_case_types)]
use gloo::console; use gloo::console;
use kanidm_proto::constants::uri::V1_AUTH_VALID; use kanidm_proto::constants::uri::V1_AUTH_VALID;
use kanidm_proto::v1::{UiHint, UserAuthToken}; use kanidm_proto::internal::{UiHint, UserAuthToken};
use kanidmd_web_ui_shared::constants::{ use kanidmd_web_ui_shared::constants::{
CSS_ALERT_DANGER, CSS_NAVBAR_BRAND, CSS_NAVBAR_LINKS_UL, CSS_NAVBAR_NAV, CSS_NAV_LINK, CSS_ALERT_DANGER, CSS_NAVBAR_BRAND, CSS_NAVBAR_LINKS_UL, CSS_NAVBAR_NAV, CSS_NAV_LINK,
ID_NAVBAR_COLLAPSE, IMG_LOGO_SQUARE, URL_ADMIN, URL_LOGIN, ID_NAVBAR_COLLAPSE, IMG_LOGO_SQUARE, URL_ADMIN, URL_LOGIN,

View file

@ -15,6 +15,10 @@ include!("src/opt/kanidm.rs");
fn main() -> Result<(), Error> { fn main() -> Result<(), Error> {
profiles::apply_profile(); profiles::apply_profile();
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-env-changed=OUT_DIR");
println!("cargo:rerun-if-changed=src/opt/kanidm.rs");
println!("cargo:rerun-if-changed=src/opt/ssh_authorizedkeys.rs");
let outdir = match env::var_os("OUT_DIR") { let outdir = match env::var_os("OUT_DIR") {
None => return Ok(()), None => return Ok(()),
Some(outdir) => outdir, Some(outdir) => outdir,

Some files were not shown because too many files have changed in this diff Show more