error handling and web server logging fixes (#1960)

* Fixing the setup_dev_environment script
* clippy calming
* handle_internalunixusertokenread throwing 500's without context
Fixes #1958
This commit is contained in:
James Hodgkinson 2023-08-14 20:47:49 +10:00 committed by GitHub
parent aba9f6a724
commit 83f189fed3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 399 additions and 239 deletions

View file

@ -204,7 +204,7 @@ impl KanidmClientBuilder {
let verify_ca = kcc.verify_ca.unwrap_or(verify_ca);
let verify_hostnames = kcc.verify_hostnames.unwrap_or(verify_hostnames);
let ca = match kcc.ca_path {
Some(ca_path) => Some(Self::parse_certificate(ca_path.as_str())?),
Some(ca_path) => Some(Self::parse_certificate(&ca_path)?),
None => ca,
};
@ -271,7 +271,7 @@ impl KanidmClientBuilder {
ClientError::ConfigParseIssue(format!("{:?}", e))
})?;
let config: KanidmClientConfig = toml::from_str(contents.as_str()).map_err(|e| {
let config: KanidmClientConfig = toml::from_str(&contents).map_err(|e| {
error!("{:?}", e);
ClientError::ConfigParseIssue(format!("{:?}", e))
})?;
@ -396,7 +396,7 @@ impl KanidmClientBuilder {
}
};
self.display_warnings(address.as_str());
self.display_warnings(&address);
let client_builder = reqwest::Client::builder()
.user_agent(KanidmClientBuilder::user_agent())
@ -442,13 +442,49 @@ impl KanidmClientBuilder {
}
}
#[test]
fn test_make_url() {
let client: KanidmClient = KanidmClientBuilder::new()
.address("https://localhost:8080".to_string())
.build()
.unwrap();
assert_eq!(
client.get_url(),
Url::parse("https://localhost:8080").unwrap()
);
assert_eq!(
client.make_url("/hello"),
Url::parse("https://localhost:8080/hello").unwrap()
);
let client: KanidmClient = KanidmClientBuilder::new()
.address("https://localhost:8080/cheese/".to_string())
.build()
.unwrap();
assert_eq!(
client.make_url("hello"),
Url::parse("https://localhost:8080/cheese/hello").unwrap()
);
}
impl KanidmClient {
pub fn get_origin(&self) -> &Url {
&self.origin
}
pub fn get_url(&self) -> &str {
self.addr.as_str()
/// Returns the base URL of the server
pub fn get_url(&self) -> Url {
#[allow(clippy::panic)]
match self.addr.parse::<Url>() {
Ok(val) => val,
Err(err) => panic!("Failed to parse {} into URL: {:?}", self.addr, err),
}
}
/// Get a URL based on adding an endpoint to the base URL of the server
pub fn make_url(&self, endpoint: &str) -> Url {
#[allow(clippy::expect_used)]
self.get_url().join(endpoint).expect("Failed to join URL")
}
pub async fn set_token(&self, new_token: String) {
@ -474,6 +510,7 @@ impl KanidmClient {
Ok(())
}
/// Check that we're getting the right version back from the server.
async fn expect_version(&self, response: &reqwest::Response) {
let mut guard = self.check_version.lock().await;
@ -508,13 +545,11 @@ impl KanidmClient {
dest: &str,
request: &R,
) -> Result<T, ClientError> {
let dest = format!("{}{}", self.get_url(), dest);
let req_string = serde_json::to_string(request).map_err(ClientError::JsonEncode)?;
let response = self
.client
.post(dest.as_str())
.post(self.make_url(dest))
.body(req_string)
.header(CONTENT_TYPE, APPLICATION_JSON);
@ -552,13 +587,12 @@ impl KanidmClient {
dest: &str,
request: R,
) -> Result<T, ClientError> {
let dest = format!("{}{}", self.get_url(), dest);
trace!("perform_auth_post_request connecting to {}", dest);
let req_string = serde_json::to_string(&request).map_err(ClientError::JsonEncode)?;
let response = self
.client
.post(dest.as_str())
.post(self.make_url(dest))
.body(req_string)
.header(CONTENT_TYPE, APPLICATION_JSON);
@ -626,12 +660,10 @@ impl KanidmClient {
dest: &str,
request: R,
) -> Result<T, ClientError> {
let dest = format!("{}{}", self.get_url(), dest);
let req_string = serde_json::to_string(&request).map_err(ClientError::JsonEncode)?;
let response = self
.client
.post(dest.as_str())
.post(self.make_url(dest))
.body(req_string)
.header(CONTENT_TYPE, APPLICATION_JSON);
@ -678,13 +710,11 @@ impl KanidmClient {
dest: &str,
request: R,
) -> Result<T, ClientError> {
let dest = format!("{}{}", self.get_url(), dest);
let req_string = serde_json::to_string(&request).map_err(ClientError::JsonEncode)?;
let response = self
.client
.put(dest.as_str())
.put(self.make_url(dest))
.header(CONTENT_TYPE, APPLICATION_JSON);
let response = {
let tguard = self.bearer_token.read().await;
@ -734,12 +764,10 @@ impl KanidmClient {
dest: &str,
request: R,
) -> Result<T, ClientError> {
let dest = format!("{}{}", self.get_url(), dest);
let req_string = serde_json::to_string(&request).map_err(ClientError::JsonEncode)?;
let response = self
.client
.patch(dest.as_str())
.patch(self.make_url(dest))
.body(req_string)
.header(CONTENT_TYPE, APPLICATION_JSON);
@ -782,10 +810,11 @@ impl KanidmClient {
}
#[instrument(level = "debug", skip(self))]
async fn perform_get_request<T: DeserializeOwned>(&self, dest: &str) -> Result<T, ClientError> {
let dest = format!("{}{}", self.get_url(), dest);
let response = self.client.get(dest.as_str());
pub async fn perform_get_request<T: DeserializeOwned>(
&self,
dest: &str,
) -> Result<T, ClientError> {
let response = self.client.get(self.make_url(dest));
let response = {
let tguard = self.bearer_token.read().await;
if let Some(token) = &(*tguard) {
@ -826,11 +855,9 @@ impl KanidmClient {
}
async fn perform_delete_request(&self, dest: &str) -> Result<(), ClientError> {
let dest = format!("{}{}", self.get_url(), dest);
let response = self
.client
.delete(dest.as_str())
.delete(self.make_url(dest))
.header(CONTENT_TYPE, APPLICATION_JSON);
let response = {
@ -876,12 +903,10 @@ impl KanidmClient {
dest: &str,
request: R,
) -> Result<(), ClientError> {
let dest = format!("{}{}", self.get_url(), dest);
let req_string = serde_json::to_string(&request).map_err(ClientError::JsonEncode)?;
let response = self
.client
.delete(dest.as_str())
.delete(self.make_url(dest))
.body(req_string)
.header(CONTENT_TYPE, APPLICATION_JSON);
@ -1352,10 +1377,7 @@ impl KanidmClient {
}
pub async fn whoami(&self) -> Result<Option<Entry>, ClientError> {
let whoami_dest = [self.addr.as_str(), "/v1/self"].concat();
// format!("{}/v1/self", self.addr);
debug!("{:?}", whoami_dest);
let response = self.client.get(whoami_dest.as_str());
let response = self.client.get(self.make_url("/v1/self"));
let response = {
let tguard = self.bearer_token.read().await;
@ -1429,15 +1451,14 @@ impl KanidmClient {
}
pub async fn idm_group_get(&self, id: &str) -> Result<Option<Entry>, ClientError> {
self.perform_get_request(format!("/v1/group/{}", id).as_str())
.await
self.perform_get_request(&format!("/v1/group/{}", id)).await
}
pub async fn idm_group_get_members(
&self,
id: &str,
) -> Result<Option<Vec<String>>, ClientError> {
self.perform_get_request(format!("/v1/group/{}/_attr/member", id).as_str())
self.perform_get_request(&format!("/v1/group/{}/_attr/member", id))
.await
}
@ -1457,7 +1478,7 @@ impl KanidmClient {
members: &[&str],
) -> Result<(), ClientError> {
let m: Vec<_> = members.iter().map(|v| (*v).to_string()).collect();
self.perform_put_request(format!("/v1/group/{}/_attr/member", id).as_str(), m)
self.perform_put_request(&format!("/v1/group/{}/_attr/member", id), m)
.await
}
@ -1467,7 +1488,7 @@ impl KanidmClient {
members: &[&str],
) -> Result<(), ClientError> {
let m: Vec<_> = members.iter().map(|v| (*v).to_string()).collect();
self.perform_post_request(["/v1/group/", id, "/_attr/member"].concat().as_str(), m)
self.perform_post_request(&format!("/v1/group/{}/_attr/member", id), m)
.await
}
@ -1477,24 +1498,19 @@ impl KanidmClient {
members: &[&str],
) -> Result<(), ClientError> {
debug!(
"{}",
&[
"Asked to remove members ",
&members.join(","),
" from ",
group
]
.concat()
"Asked to remove members {} from {}",
&members.join(","),
group
);
self.perform_delete_request_with_body(
["/v1/group/", group, "/_attr/member"].concat().as_str(),
&format!("/v1/group/{}/_attr/member", group),
&members,
)
.await
}
pub async fn idm_group_purge_members(&self, id: &str) -> Result<(), ClientError> {
self.perform_delete_request(format!("/v1/group/{}/_attr/member", id).as_str())
self.perform_delete_request(&format!("/v1/group/{}/_attr/member", id))
.await
}
@ -1504,26 +1520,24 @@ impl KanidmClient {
gidnumber: Option<u32>,
) -> Result<(), ClientError> {
let gx = GroupUnixExtend { gidnumber };
self.perform_post_request(format!("/v1/group/{}/_unix", id).as_str(), gx)
self.perform_post_request(&format!("/v1/group/{}/_unix", id), gx)
.await
}
pub async fn idm_group_unix_token_get(&self, id: &str) -> Result<UnixGroupToken, ClientError> {
self.perform_get_request(["/v1/group/", id, "/_unix/_token"].concat().as_str())
self.perform_get_request(&format!("/v1/group/{}/_unix/_token", id))
.await
}
pub async fn idm_group_delete(&self, id: &str) -> Result<(), ClientError> {
self.perform_delete_request(["/v1/group/", id].concat().as_str())
self.perform_delete_request(&format!("/v1/group/{}", id))
.await
}
// ==== ACCOUNTS
pub async fn idm_account_unix_token_get(&self, id: &str) -> Result<UnixUserToken, ClientError> {
// Format doesn't work in async
// format!("/v1/account/{}/_unix/_token", id).as_str()
self.perform_get_request(["/v1/account/", id, "/_unix/_token"].concat().as_str())
self.perform_get_request(&format!("/v1/account/{}/_unix/_token", id))
.await
}
@ -1535,15 +1549,14 @@ impl KanidmClient {
ttl: Option<u32>,
) -> Result<CUIntentToken, ClientError> {
if let Some(ttl) = ttl {
self.perform_get_request(
format!("/v1/person/{}/_credential/_update_intent?ttl={}", id, ttl).as_str(),
)
self.perform_get_request(&format!(
"/v1/person/{}/_credential/_update_intent?ttl={}",
id, ttl
))
.await
} else {
self.perform_get_request(
format!("/v1/person/{}/_credential/_update_intent", id).as_str(),
)
.await
self.perform_get_request(&format!("/v1/person/{}/_credential/_update_intent", id))
.await
}
}
@ -1551,7 +1564,7 @@ impl KanidmClient {
&self,
id: &str,
) -> Result<(CUSessionToken, CUStatus), ClientError> {
self.perform_get_request(format!("/v1/person/{}/_credential/_update", id).as_str())
self.perform_get_request(&format!("/v1/person/{}/_credential/_update", id))
.await
}
@ -1692,7 +1705,7 @@ impl KanidmClient {
&self,
id: &str,
) -> Result<RadiusAuthToken, ClientError> {
self.perform_get_request(format!("/v1/account/{}/_radius/_token", id).as_str())
self.perform_get_request(&format!("/v1/account/{}/_radius/_token", id))
.await
}
@ -1704,7 +1717,7 @@ impl KanidmClient {
let req = SingleStringRequest {
value: cred.to_string(),
};
self.perform_post_request(["/v1/account/", id, "/_unix/_auth"].concat().as_str(), req)
self.perform_post_request(&format!("/v1/account/{}/_unix/_auth", id), req)
.await
}
@ -1714,12 +1727,12 @@ impl KanidmClient {
id: &str,
tag: &str,
) -> Result<Option<String>, ClientError> {
self.perform_get_request(format!("/v1/account/{}/_ssh_pubkeys/{}", id, tag).as_str())
self.perform_get_request(&format!("/v1/account/{}/_ssh_pubkeys/{}", id, tag))
.await
}
pub async fn idm_account_get_ssh_pubkeys(&self, id: &str) -> Result<Vec<String>, ClientError> {
self.perform_get_request(format!("/v1/account/{}/_ssh_pubkeys", id).as_str())
self.perform_get_request(&format!("/v1/account/{}/_ssh_pubkeys", id))
.await
}
@ -1783,7 +1796,7 @@ impl KanidmClient {
&self,
id: &str,
) -> Result<Option<Entry>, ClientError> {
self.perform_get_request(format!("/v1/schema/attributetype/{}", id).as_str())
self.perform_get_request(&format!("/v1/schema/attributetype/{}", id))
.await
}
@ -1792,7 +1805,7 @@ impl KanidmClient {
}
pub async fn idm_schema_classtype_get(&self, id: &str) -> Result<Option<Entry>, ClientError> {
self.perform_get_request(format!("/v1/schema/classtype/{}", id).as_str())
self.perform_get_request(&format!("/v1/schema/classtype/{}", id))
.await
}
@ -1802,12 +1815,12 @@ impl KanidmClient {
}
pub async fn recycle_bin_get(&self, id: &str) -> Result<Option<Entry>, ClientError> {
self.perform_get_request(format!("/v1/recycle_bin/{}", id).as_str())
self.perform_get_request(&format!("/v1/recycle_bin/{}", id))
.await
}
pub async fn recycle_bin_revive(&self, id: &str) -> Result<(), ClientError> {
self.perform_post_request(format!("/v1/recycle_bin/{}/_revive", id).as_str(), ())
self.perform_post_request(&format!("/v1/recycle_bin/{}/_revive", id), ())
.await
}
}

View file

@ -6,7 +6,7 @@ use base64::{engine::general_purpose, Engine as _};
// We do this here so it's only actually run and checked once.
fn determine_git_rev() -> Option<String> {
let path = PathBuf::from("../../");
let repo = git2::Repository::open(&path).ok()?;
let repo = git2::Repository::open(path).ok()?;
let head = repo.head().ok()?;
let commit = head.peel_to_commit().ok()?;
let mut commit_id = commit.id().to_string();

View file

@ -1,3 +1,5 @@
#![allow(non_upper_case_globals)]
use num_enum::TryFromPrimitive;
use serde::{Deserialize, Serialize};
use serde_with::skip_serializing_none;
@ -294,14 +296,6 @@ pub struct Claim {
// pub expiry: DateTime
}
/*
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Application {
pub name: String,
pub uuid: String,
}
*/
#[derive(Debug, Serialize, Deserialize, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
#[serde(rename_all = "lowercase")]
#[derive(TryFromPrimitive)]

View file

@ -25,31 +25,34 @@ if [ -z "${REMOVE_TEST_DB}" ]; then
fi
fi
if [ ! -f run_insecure_dev_server.sh ]; then
echo "Please run from the server/daemon dir!"
exit 1
fi
# defaults
KANIDM_CONFIG_FILE="../../examples/insecure_server.toml"
KANIDM_URL="$(rg origin "${KANIDM_CONFIG_FILE}" | awk '{print $NF}' | tr -d '"')"
KANIDM_CA_PATH="/tmp/kanidm/ca.pem"
# wait for them to shut down the server if it's running...
while true
do
if [ "$(pgrep kanidmd | wc -l )" -eq 0 ]; then
while true; do
if [ "$(pgrep kanidmd | wc -l)" -eq 1 ]; then
break
fi
echo "Stop the kanidmd server first please!"
sleep 1
done
echo "Start the kanidmd server first please!"
# defaults
KANIDM_CONFIG="../../examples/insecure_server.toml"
KANIDM_URL="$(rg origin "${KANIDM_CONFIG}" | awk '{print $NF}' | tr -d '"')"
KANIDM_CA_PATH="/tmp/kanidm/ca.pem"
while true; do
echo "Waiting for you to start the server... testing ${KANIDM_URL}"
curl --cacert "${KANIDM_CA_PATH}" -fs "${KANIDM_URL}" >/dev/null && break
sleep 2
done
done
# needed for the CLI tools to do their thing
export KANIDM_URL
export KANIDM_CA_PATH
export KANIDM_CONFIG
export KANIDM_CONFIG_FILE
# string things
TEST_USER_NAME="testuser"
@ -68,19 +71,20 @@ if [ "${REMOVE_TEST_DB}" -eq 1 ]; then
fi
echo "Reset the admin user"
ADMIN_PASS=$(${KANIDMD} recover-account admin -o json 2>&1 | rg recovery | rg result | jq -r .result )
ADMIN_PASS=$(${KANIDMD} recover-account admin -o json 2>&1 | rg password | jq -r .password)
if [ -z "${ADMIN_PASS}" ] || [ "${ADMIN_PASS}" == "null " ]; then
echo "Failed to reset admin password!"
exit 1
fi
echo "admin pass: '${ADMIN_PASS}'"
echo "Reset the idm_admin user"
IDM_ADMIN_PASS=$(${KANIDMD} recover-account idm_admin -o json 2>&1 | rg recovery | rg result | jq -r .result)
IDM_ADMIN_PASS=$(${KANIDMD} recover-account idm_admin -o json 2>&1 | rg password | jq -r .password)
if [ -z "${IDM_ADMIN_PASS}" ] || [ "${IDM_ADMIN_PASS}" == "null " ]; then
echo "Failed to reset admin password!"
exit 1
fi
echo "idm_admin pass: '${IDM_ADMIN_PASS}'"
while true
do
echo "Waiting for you to start the server... testing ${KANIDM_URL}"
curl --cacert "${KANIDM_CA_PATH}" -fs "${KANIDM_URL}" > /dev/null && break
sleep 2
done
echo "login with admin"
${KANIDM} login -D admin --password "${ADMIN_PASS}"
echo "login with idm_admin"
@ -96,7 +100,7 @@ echo "Adding ${TEST_USER_NAME} to ${TEST_GROUP}"
${KANIDM} group add-members "${TEST_GROUP}" "${TEST_USER_NAME}" -D idm_admin
echo "Enable experimental UI for admin idm_admin ${TEST_USER_NAME}"
${KANIDM} group add-members idm_ui_enable_experimental_features admin idm_admin "${TEST_USER_NAME}" -D idm_admin
${KANIDM} group add-members idm_ui_enable_experimental_features admin idm_admin "${TEST_USER_NAME}" -D idm_admin
# create oauth2 rp
echo "Creating the OAuth2 RP"

View file

@ -2,12 +2,16 @@
# makes sure the repos are configured because the containers are derpy sometimes
set -e
#disable the openh264 repo
if [ "$(zypper lr | grep -ci 'repo-openh264')" -eq 1 ]; then
zypper mr -d -f -n 'repo-openh264'
echo "Disabling openh264 repo"
zypper mr -d -f repo-openh264
fi
# add the non-oss repo if it doesn't exist
echo "Adding the non-oss repo"
if [ "$(zypper lr | grep -c 'repo-non-oss')" -eq 0 ]; then
zypper ar -f -n 'Non-OSS' http://download.opensuse.org/tumbleweed/repo/non-oss/ repo-non-oss
fi

View file

@ -618,10 +618,16 @@ impl QueryServerReadV1 {
.qs_read
.name_to_uuid(uuid_or_name.as_str())
.map_err(|e| {
// sometimes it comes back as empty which is bad, it's safe to start with `<empty` here
// because a valid username/uuid can never start with that and we're only logging it
let uuid_or_name_val = match uuid_or_name.is_empty() {
true => "<empty uuid_or_name>",
false => &uuid_or_name,
};
admin_info!(
err = ?e,
"Error resolving {} as gidnumber continuing ...",
uuid_or_name
uuid_or_name_val
);
e
})?;

View file

@ -70,7 +70,7 @@ pub async fn are_we_json_yet<B>(request: Request<B>, next: Next<B>) -> Response
}
/// This runs at the start of the request, adding an extension with `KOpId` which has useful things inside it.
#[instrument(name = "request", skip_all)]
#[instrument(name = "kopid_middleware", skip_all, level = "DEBUG")]
pub async fn kopid_middleware<B>(
auth: Option<TypedHeader<Authorization<Bearer>>>,
mut request: Request<B>,
@ -86,10 +86,11 @@ pub async fn kopid_middleware<B>(
request.extensions_mut().insert(KOpId { eventid, uat });
let mut response = next.run(request).await;
#[allow(clippy::unwrap_used)]
#[allow(clippy::expect_used)]
response.headers_mut().insert(
"X-KANIDM-OPID",
HeaderValue::from_str(&eventid.as_hyphenated().to_string()).unwrap(),
HeaderValue::from_str(&eventid.as_hyphenated().to_string())
.expect("Failed to set X-KANIDM-OPID header in response!"),
);
response

View file

@ -5,6 +5,7 @@ mod manifest;
mod middleware;
mod oauth2;
mod tests;
mod trace;
mod ui;
mod v1;
mod v1_scim;
@ -37,6 +38,7 @@ use tokio_openssl::SslStream;
use futures_util::future::poll_fn;
use serde::Serialize;
use tokio::net::TcpListener;
use tracing::Level;
use std::io::ErrorKind;
use std::path::PathBuf;
@ -45,7 +47,7 @@ use std::sync::Arc;
use std::{net::SocketAddr, str::FromStr};
use tokio::sync::broadcast;
use tower_http::services::ServeDir;
use tower_http::trace::TraceLayer;
use tower_http::trace::{DefaultOnRequest, TraceLayer};
use uuid::Uuid;
use crate::CoreAction;
@ -235,6 +237,12 @@ pub async fn create_https_server(
}
};
// this sets up the default span which logs the URL etc.
let trace_layer = TraceLayer::new_for_http()
.make_span_with(trace::DefaultMakeSpanKanidmd::new())
// setting these to trace because all they do is print "started processing request", and we are already doing that enough!
.on_request(DefaultOnRequest::new().level(Level::TRACE));
let app = app
.merge(static_routes)
.layer(from_fn_with_state(
@ -244,19 +252,19 @@ pub async fn create_https_server(
.layer(from_fn(middleware::version_middleware))
.layer(from_fn(
middleware::hsts_header::strict_transport_security_layer,
))
.layer(TraceLayer::new_for_http())
// This must be the LAST middleware.
// This is because the last middleware here is the first to be entered and the last
// to be exited, and this middleware sets up ids' and other bits for for logging
// coherence to be maintained.
.layer(from_fn(middleware::kopid_middleware));
));
// layer which checks the responses have a content-type of JSON when we're in debug mode
#[cfg(debug_assertions)]
let app = app.layer(from_fn(middleware::are_we_json_yet));
let app = app
.layer(trace_layer)
// This must be the LAST middleware.
// This is because the last middleware here is the first to be entered and the last
// to be exited, and this middleware sets up ids' and other bits for for logging
// coherence to be maintained.
.layer(from_fn(middleware::kopid_middleware))
.with_state(state)
// the connect_info bit here lets us pick up the remote address of the client
.into_make_service_with_connect_info::<SocketAddr>();
@ -345,7 +353,6 @@ async fn server_loop(
}
}
// #[instrument(name = "handle-connection", level = "debug", skip_all)]
/// This handles an individual connection.
async fn handle_conn(
acceptor: SslAcceptor,

View file

@ -0,0 +1,37 @@
//! Reimplementation of [`tower-http`]'s [`DefaultMakeSpan`] that only runs at "INFO" level for our own needs.
use http::Request;
use tracing::{Level, Span};
/// The default way [`Span`]s will be created for [`Trace`].
///
/// [`Span`]: tracing::Span
/// [`Trace`]: super::Trace
#[derive(Debug, Clone)]
pub struct DefaultMakeSpanKanidmd {}
impl DefaultMakeSpanKanidmd {
/// Create a new `DefaultMakeSpanKanidmd`.
pub fn new() -> Self {
Self {}
}
}
impl Default for DefaultMakeSpanKanidmd {
fn default() -> Self {
Self::new()
}
}
impl<B> tower_http::trace::MakeSpan<B> for DefaultMakeSpanKanidmd {
#[instrument(name = "handle_request", skip_all)]
fn make_span(&mut self, request: &Request<B>) -> Span {
tracing::span!(
Level::INFO,
"request",
method = %request.method(),
uri = %request.uri(),
version = ?request.version(),
)
}
}

View file

@ -874,7 +874,7 @@ pub async fn account_delete_id_radius(
json_rest_event_delete_id_attr(state, id, attr, filter, None, kopid).await
}
pub async fn account_get_id_radius_token(
pub async fn account_id_radius_token(
State(state): State<ServerState>,
Path(id): Path<String>,
Extension(kopid): Extension<KOpId>,
@ -893,6 +893,7 @@ pub async fn account_get_id_radius_token(
}
/// Expects an `AccountUnixExtend` object
#[instrument(name = "account_post_id_unix", level = "INFO", skip(id, state, kopid))]
pub async fn account_post_id_unix(
State(state): State<ServerState>,
Path(id): Path<String>,
@ -906,15 +907,46 @@ pub async fn account_post_id_unix(
to_axum_response(res)
}
pub async fn account_get_id_unix_token(
#[instrument(name = "account_id_unix_token", level = "INFO", skip_all)]
pub async fn account_id_unix_token(
State(state): State<ServerState>,
Extension(kopid): Extension<KOpId>,
Path(id): Path<String>,
) -> impl IntoResponse {
// no point asking for an empty id
if id.is_empty() {
#[allow(clippy::unwrap_used)]
return Response::builder()
.status(StatusCode::BAD_REQUEST)
.body(Body::empty())
.unwrap();
}
let res = state
.qe_r_ref
.handle_internalunixusertokenread(kopid.uat, id, kopid.eventid)
.await;
if let Err(OperationError::InvalidAccountState(val)) = &res {
// if they're not a posix user we should just hide them
if *val == format!("Missing class: {}", "posixaccount") {
#[allow(clippy::unwrap_used)]
return Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Body::empty())
.unwrap();
}
};
// the was returning a 500 error which wasn't right
if let Err(OperationError::InvalidValueState) = &res {
#[allow(clippy::unwrap_used)]
return Response::builder()
.status(StatusCode::NOT_FOUND)
.body(Body::empty())
.unwrap();
};
to_axum_response(res)
}
@ -1480,8 +1512,8 @@ pub fn router(state: ServerState) -> Router<ServerState> {
)
.route(
"/v1/person/:id/_radius/_token",
get(account_get_id_radius_token),
) // TODO: make radius token cacheable
get(account_id_radius_token),
) // TODO: make this cacheable
.route("/v1/person/:id/_unix", post(account_post_id_unix))
.route(
"/v1/person/:id/_unix/_credential",
@ -1551,11 +1583,11 @@ pub fn router(state: ServerState) -> Router<ServerState> {
)
.route(
"/v1/account/:id/_unix/_token",
post(account_get_id_unix_token).get(account_get_id_unix_token), // TODO: make this cacheable
post(account_id_unix_token).get(account_id_unix_token), // TODO: make this cacheable
)
.route(
"/v1/account/:id/_radius/_token",
post(account_get_id_radius_token).get(account_get_id_radius_token), // TODO: make this cacheable
post(account_id_radius_token).get(account_id_radius_token), // TODO: make this cacheable
)
.route(
"/v1/account/:id/_ssh_pubkeys",

View file

@ -99,25 +99,24 @@ pub async fn create_user(rsclient: &KanidmClient, id: &str, group_name: &str) {
.expect("Failed to create the user");
// Create group and add to user to test read attr: member_of
#[allow(clippy::expect_used)]
#[allow(clippy::panic)]
if rsclient
.idm_group_get(group_name)
.await
.expect("Failed to get group")
.unwrap_or_else(|_| panic!("Failed to get group {}", group_name))
.is_none()
{
#[allow(clippy::expect_used)]
#[allow(clippy::panic)]
rsclient
.idm_group_create(group_name)
.await
.expect("Failed to create group");
.unwrap_or_else(|_| panic!("Failed to create group {}", group_name));
}
#[allow(clippy::expect_used)]
#[allow(clippy::panic)]
rsclient
.idm_group_add_members(group_name, &[id])
.await
.expect("Failed to set group membership for user");
.unwrap_or_else(|_| panic!("Failed to add user {} to group {}", id, group_name));
}
pub async fn create_user_with_all_attrs(

View file

@ -554,12 +554,15 @@ async fn test_self_write_mail_priv_people(rsclient: KanidmClient) {
#[kanidmd_testkit::test]
async fn test_https_robots_txt(rsclient: KanidmClient) {
// We need to do manual reqwests here.
let addr = rsclient.get_url();
let response = match reqwest::get(format!("{}/robots.txt", &addr)).await {
let response = match reqwest::get(rsclient.make_url("/robots.txt")).await {
Ok(value) => value,
Err(error) => {
panic!("Failed to query {:?} : {:#?}", addr, error);
panic!(
"Failed to query {:?} : {:#?}",
rsclient.make_url("/robots.txt"),
error
);
}
};
eprintln!("response: {:#?}", response);
@ -577,9 +580,7 @@ async fn test_https_robots_txt(rsclient: KanidmClient) {
// #[kanidmd_testkit::test]
// async fn test_https_routemap(rsclient: KanidmClient) {
// // We need to do manual reqwests here.
// let addr = rsclient.get_url();
// let response = match reqwest::get(format!("{}/v1/routemap", &addr)).await {
// let response = match reqwest::get(rsclient.make_url("/v1/routemap")).await {
// Ok(value) => value,
// Err(error) => {
// panic!("Failed to query {:?} : {:#?}", addr, error);
@ -598,7 +599,7 @@ async fn test_https_robots_txt(rsclient: KanidmClient) {
#[kanidmd_testkit::test]
async fn test_v1_raw_delete(rsclient: KanidmClient) {
// We need to do manual reqwests here.
let addr = rsclient.get_url();
let client = reqwest::ClientBuilder::new()
.danger_accept_invalid_certs(true)
.build()
@ -607,7 +608,7 @@ async fn test_v1_raw_delete(rsclient: KanidmClient) {
let post_body = serde_json::json!({"filter": "self"}).to_string();
let response = match client
.post(format!("{}/v1/raw/delete", &addr))
.post(rsclient.make_url("/v1/raw/delete"))
.header(CONTENT_TYPE, APPLICATION_JSON)
.body(post_body)
.send()
@ -615,7 +616,11 @@ async fn test_v1_raw_delete(rsclient: KanidmClient) {
{
Ok(value) => value,
Err(error) => {
panic!("Failed to query {:?} : {:#?}", addr, error);
panic!(
"Failed to query {:?} : {:#?}",
rsclient.make_url("/v1/raw/delete"),
error
);
}
};
eprintln!("response: {:#?}", response);
@ -629,16 +634,19 @@ async fn test_v1_raw_delete(rsclient: KanidmClient) {
#[kanidmd_testkit::test]
async fn test_v1_raw_logout(rsclient: KanidmClient) {
// We need to do manual reqwests here.
let addr = rsclient.get_url();
let client = reqwest::ClientBuilder::new()
.danger_accept_invalid_certs(true)
.build()
.unwrap();
let response = match client.get(format!("{}/v1/logout", &addr)).send().await {
let response = match client.get(rsclient.make_url("/v1/logout")).send().await {
Ok(value) => value,
Err(error) => {
panic!("Failed to query {:?} : {:#?}", addr, error);
panic!(
"Failed to query {:?} : {:#?}",
rsclient.make_url("/v1/logout"),
error
);
}
};
eprintln!("response: {:#?}", response);
@ -652,16 +660,19 @@ async fn test_v1_raw_logout(rsclient: KanidmClient) {
#[kanidmd_testkit::test]
async fn test_status_endpoint(rsclient: KanidmClient) {
// We need to do manual reqwests here.
let addr = rsclient.get_url();
let client = reqwest::ClientBuilder::new()
.danger_accept_invalid_certs(true)
.build()
.unwrap();
let response = match client.get(format!("{}/status", &addr)).send().await {
let response = match client.get(rsclient.make_url("/status")).send().await {
Ok(value) => value,
Err(error) => {
panic!("Failed to query {:?} : {:#?}", addr, error);
panic!(
"Failed to query {:?} : {:#?}",
rsclient.make_url("/status"),
error
);
}
};
eprintln!("response: {:#?}", response);

View file

@ -3,13 +3,16 @@ use kanidm_client::KanidmClient;
#[kanidmd_testkit::test]
async fn test_https_manifest(rsclient: KanidmClient) {
// We need to do manual reqwests here.
let addr = rsclient.get_url();
// here we test the /ui/ endpoint which should have the headers
let response = match reqwest::get(format!("{}/manifest.webmanifest", &addr)).await {
let response = match reqwest::get(rsclient.make_url("/manifest.webmanifest")).await {
Ok(value) => value,
Err(error) => {
panic!("Failed to query {:?} : {:#?}", addr, error);
panic!(
"Failed to query {:?} : {:#?}",
rsclient.make_url("/manifest.webmanifest"),
error
);
}
};
eprintln!("response: {:#?}", response);

View file

@ -3,13 +3,16 @@ use kanidm_client::KanidmClient;
#[kanidmd_testkit::test]
async fn test_https_middleware_headers(rsclient: KanidmClient) {
// We need to do manual reqwests here.
let addr = rsclient.get_url();
// here we test the /ui/ endpoint which should have the headers
let response = match reqwest::get(format!("{}/ui", &addr)).await {
let response = match reqwest::get(rsclient.make_url("/ui")).await {
Ok(value) => value,
Err(error) => {
panic!("Failed to query {:?} : {:#?}", addr, error);
panic!(
"Failed to query {:?} : {:#?}",
rsclient.make_url("/ui"),
error
);
}
};
eprintln!("response: {:#?}", response);
@ -21,10 +24,14 @@ async fn test_https_middleware_headers(rsclient: KanidmClient) {
assert_ne!(response.headers().get("content-security-policy"), None);
// here we test the /ui/login endpoint which should have the headers
let response = match reqwest::get(format!("{}/ui/login", &addr)).await {
let response = match reqwest::get(rsclient.make_url("/ui/login")).await {
Ok(value) => value,
Err(error) => {
panic!("Failed to query {:?} : {:#?}", addr, error);
panic!(
"Failed to query {:?} : {:#?}",
rsclient.make_url("/ui/login"),
error
);
}
};
eprintln!("response: {:#?}", response);

View file

@ -82,7 +82,7 @@ async fn test_webdriver_user_login(rsclient: kanidm_client::KanidmClient) {
handle_error!(
c,
c.goto(rsclient.get_url().to_string()).await,
c.goto(&rsclient.get_url().to_string()).await,
"Couldn't get URL"
);

View file

@ -121,8 +121,6 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) {
.await
.expect("No user auth token found");
let url = rsclient.get_url().to_string();
// We need a new reqwest client here.
// from here, we can now begin what would be a "interaction" to the oauth server.
@ -137,10 +135,7 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) {
let response = client
.request(
reqwest::Method::OPTIONS,
format!(
"{}/oauth2/openid/test_integration/.well-known/openid-configuration",
url
),
rsclient.make_url("/oauth2/openid/test_integration/.well-known/openid-configuration"),
)
.send()
.await
@ -156,10 +151,7 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) {
assert!(cors_header.eq("*"));
let response = client
.get(format!(
"{}/oauth2/openid/test_integration/.well-known/openid-configuration",
url
))
.get(rsclient.make_url("/oauth2/openid/test_integration/.well-known/openid-configuration"))
.send()
.await
.expect("Failed to send request.");
@ -176,36 +168,24 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) {
// Most values are checked in idm/oauth2.rs, but we want to sanity check
// the urls here as an extended function smoke test.
assert!(
discovery.issuer == Url::parse(&format!("{}/oauth2/openid/test_integration", url)).unwrap()
);
assert!(discovery.issuer == rsclient.make_url("/oauth2/openid/test_integration"));
assert!(discovery.authorization_endpoint == Url::parse(&format!("{}/ui/oauth2", url)).unwrap());
assert!(discovery.authorization_endpoint == rsclient.make_url("/ui/oauth2"));
assert!(discovery.token_endpoint == Url::parse(&format!("{}/oauth2/token", url)).unwrap());
assert!(discovery.token_endpoint == rsclient.make_url("/oauth2/token"));
assert!(
discovery.userinfo_endpoint
== Some(
Url::parse(&format!("{}/oauth2/openid/test_integration/userinfo", url)).unwrap()
)
== Some(rsclient.make_url("/oauth2/openid/test_integration/userinfo"))
);
assert!(
discovery.jwks_uri
== Url::parse(&format!(
"{}/oauth2/openid/test_integration/public_key.jwk",
url
))
.unwrap()
discovery.jwks_uri == rsclient.make_url("/oauth2/openid/test_integration/public_key.jwk")
);
// Step 0 - get the jwks public key.
let response = client
.get(format!(
"{}/oauth2/openid/test_integration/public_key.jwk",
url
))
.get(rsclient.make_url("/oauth2/openid/test_integration/public_key.jwk"))
.send()
.await
.expect("Failed to send request.");
@ -231,7 +211,7 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) {
let (pkce_code_challenge, pkce_code_verifier) = PkceCodeChallenge::new_random_sha256();
let response = client
.get(format!("{}/oauth2/authorise", url))
.get(rsclient.make_url("/oauth2/authorise"))
.bearer_auth(oauth_test_uat.clone())
.query(&[
("response_type", "code"),
@ -271,7 +251,7 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) {
// state and code.
let response = client
.get(format!("{}/oauth2/authorise/permit", url))
.get(rsclient.make_url("/oauth2/authorise/permit"))
.bearer_auth(oauth_test_uat)
.query(&[("token", consent_token.as_str())])
.send()
@ -312,7 +292,7 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) {
.into();
let response = client
.post(format!("{}/oauth2/token", url))
.post(rsclient.make_url("/oauth2/token"))
.basic_auth("test_integration", Some(client_secret.clone()))
.form(&form_req)
.send()
@ -339,7 +319,7 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) {
};
let response = client
.post(format!("{}/oauth2/token/introspect", url))
.post(rsclient.make_url("/oauth2/token/introspect"))
.basic_auth("test_integration", Some(client_secret))
.form(&intr_request)
.send()
@ -381,13 +361,13 @@ async fn test_oauth2_openid_basic_flow(rsclient: KanidmClient) {
// This is mostly checked inside of idm/oauth2.rs. This is more to check the oidc
// token and the userinfo endpoints.
assert!(oidc.iss == Url::parse(&format!("{}/oauth2/openid/test_integration", url)).unwrap());
assert!(oidc.iss == rsclient.make_url("/oauth2/openid/test_integration"));
eprintln!("{:?}", oidc.s_claims.email);
assert!(oidc.s_claims.email.as_deref() == Some("oauth_test@localhost"));
assert!(oidc.s_claims.email_verified == Some(true));
let response = client
.get(format!("{}/oauth2/openid/test_integration/userinfo", url))
.get(rsclient.make_url("/oauth2/openid/test_integration/userinfo"))
.bearer_auth(atr.access_token.clone())
.send()
.await
@ -486,8 +466,6 @@ async fn test_oauth2_openid_public_flow(rsclient: KanidmClient) {
.await
.expect("No user auth token found");
let url = rsclient.get_url().to_string();
// We need a new reqwest client here.
// from here, we can now begin what would be a "interaction" to the oauth server.
@ -500,10 +478,7 @@ async fn test_oauth2_openid_public_flow(rsclient: KanidmClient) {
// Step 0 - get the jwks public key.
let response = client
.get(format!(
"{}/oauth2/openid/test_integration/public_key.jwk",
url
))
.get(rsclient.make_url("/oauth2/openid/test_integration/public_key.jwk"))
.send()
.await
.expect("Failed to send request.");
@ -528,7 +503,7 @@ async fn test_oauth2_openid_public_flow(rsclient: KanidmClient) {
let (pkce_code_challenge, pkce_code_verifier) = PkceCodeChallenge::new_random_sha256();
let response = client
.get(format!("{}/oauth2/authorise", url))
.get(rsclient.make_url("/oauth2/authorise"))
.bearer_auth(oauth_test_uat.clone())
.query(&[
("response_type", "code"),
@ -567,7 +542,7 @@ async fn test_oauth2_openid_public_flow(rsclient: KanidmClient) {
// Step 2 - we now send the consent get to the server which yields a redirect with a
// state and code.
let response = client
.get(format!("{}/oauth2/authorise/permit", url))
.get(rsclient.make_url("/oauth2/authorise/permit"))
.bearer_auth(oauth_test_uat)
.query(&[("token", consent_token.as_str())])
.send()
@ -611,7 +586,7 @@ async fn test_oauth2_openid_public_flow(rsclient: KanidmClient) {
};
let response = client
.post(format!("{}/oauth2/token", url))
.post(rsclient.make_url("/oauth2/token"))
.form(&form_req)
.send()
.await
@ -636,7 +611,7 @@ async fn test_oauth2_openid_public_flow(rsclient: KanidmClient) {
// This is mostly checked inside of idm/oauth2.rs. This is more to check the oidc
// token and the userinfo endpoints.
assert!(oidc.iss == Url::parse(&format!("{}/oauth2/openid/test_integration", url)).unwrap());
assert!(oidc.iss == rsclient.make_url("/oauth2/openid/test_integration"));
eprintln!("{:?}", oidc.s_claims.email);
assert!(oidc.s_claims.email.as_deref() == Some("oauth_test@localhost"));
assert!(oidc.s_claims.email_verified == Some(true));
@ -645,7 +620,7 @@ async fn test_oauth2_openid_public_flow(rsclient: KanidmClient) {
let response = client
.request(
reqwest::Method::OPTIONS,
format!("{}/oauth2/openid/test_integration/userinfo", url),
rsclient.make_url("/oauth2/openid/test_integration/userinfo"),
)
.send()
.await
@ -661,7 +636,7 @@ async fn test_oauth2_openid_public_flow(rsclient: KanidmClient) {
assert!(cors_header.eq("*"));
let response = client
.get(format!("{}/oauth2/openid/test_integration/userinfo", url))
.get(rsclient.make_url("/oauth2/openid/test_integration/userinfo"))
.bearer_auth(atr.access_token.clone())
.send()
.await
@ -695,7 +670,6 @@ async fn test_oauth2_token_post_bad_bodies(rsclient: KanidmClient) {
.await;
assert!(res.is_ok());
let url = rsclient.get_url().to_string();
let client = reqwest::Client::builder()
.redirect(reqwest::redirect::Policy::none())
.no_proxy()
@ -704,7 +678,7 @@ async fn test_oauth2_token_post_bad_bodies(rsclient: KanidmClient) {
// test for a bad-body request on token
let response = client
.post(format!("{}/oauth2/token", url))
.post(rsclient.make_url("/oauth2/token"))
.form(&serde_json::json!({}))
// .bearer_auth(atr.access_token.clone())
.send()
@ -715,7 +689,7 @@ async fn test_oauth2_token_post_bad_bodies(rsclient: KanidmClient) {
// test for a bad-auth request
let response = client
.post(format!("{}/oauth2/token/introspect", url))
.post(rsclient.make_url("/oauth2/token/introspect"))
.form(&serde_json::json!({ "token": "lol" }))
.send()
.await
@ -731,7 +705,6 @@ async fn test_oauth2_token_revoke_post(rsclient: KanidmClient) {
.await;
assert!(res.is_ok());
let url = rsclient.get_url().to_string();
let client = reqwest::Client::builder()
.redirect(reqwest::redirect::Policy::none())
.no_proxy()
@ -740,7 +713,7 @@ async fn test_oauth2_token_revoke_post(rsclient: KanidmClient) {
// test for a bad-body request on token
let response = client
.post(format!("{}/oauth2/token/revoke", url))
.post(rsclient.make_url("/oauth2/token/revoke"))
.form(&serde_json::json!({}))
.bearer_auth("lolol")
.send()
@ -751,7 +724,7 @@ async fn test_oauth2_token_revoke_post(rsclient: KanidmClient) {
// test for a invalid format request on token
let response = client
.post(format!("{}/oauth2/token/revoke", url))
.post(rsclient.make_url("/oauth2/token/revoke"))
.json("")
.bearer_auth("lolol")
.send()
@ -763,7 +736,7 @@ async fn test_oauth2_token_revoke_post(rsclient: KanidmClient) {
// test for a bad-body request on token
let response = client
.post(format!("{}/oauth2/token/revoke", url))
.post(rsclient.make_url("/oauth2/token/revoke"))
.form(&serde_json::json!({}))
.bearer_auth("Basic lolol")
.send()
@ -774,7 +747,7 @@ async fn test_oauth2_token_revoke_post(rsclient: KanidmClient) {
// test for a bad-body request on token
let response = client
.post(format!("{}/oauth2/token/revoke", url))
.post(rsclient.make_url("/oauth2/token/revoke"))
.body(serde_json::json!({}).to_string())
.bearer_auth("Basic lolol")
.send()

View file

@ -6,7 +6,6 @@ use reqwest::header::CONTENT_TYPE;
#[kanidmd_testkit::test]
async fn test_v1_person_patch(rsclient: KanidmClient) {
// We need to do manual reqwests here.
let addr = rsclient.get_url();
let client = reqwest::ClientBuilder::new()
.danger_accept_invalid_certs(true)
.build()
@ -15,7 +14,7 @@ async fn test_v1_person_patch(rsclient: KanidmClient) {
let post_body = serde_json::json!({"attrs": { "email" : "crab@example.com"}}).to_string();
let response = match client
.patch(format!("{}/v1/person/foo", &addr))
.patch(rsclient.make_url("/v1/person/foo"))
.header(CONTENT_TYPE, APPLICATION_JSON)
.body(post_body)
.send()
@ -23,7 +22,11 @@ async fn test_v1_person_patch(rsclient: KanidmClient) {
{
Ok(value) => value,
Err(error) => {
panic!("Failed to query {:?} : {:#?}", addr, error);
panic!(
"Failed to query {:?} : {:#?}",
rsclient.make_url("/v1/person/foo"),
error
);
}
};
eprintln!("response: {:#?}", response);

View file

@ -120,6 +120,7 @@ async fn test_server_search(rsclient: KanidmClient) {
// First show we are un-authenticated.
let pre_res = rsclient.whoami().await;
// This means it was okay whoami, but no uat attached.
println!("Response: {:?}", pre_res);
assert!(pre_res.unwrap().is_none());
let res = rsclient

View file

@ -93,7 +93,6 @@ async fn test_sync_account_lifecycle(rsclient: KanidmClient) {
#[kanidmd_testkit::test]
async fn test_scim_sync_get(rsclient: KanidmClient) {
// We need to do manual reqwests here.
let addr = rsclient.get_url();
let mut headers = reqwest::header::HeaderMap::new();
headers.insert(
@ -107,10 +106,14 @@ async fn test_scim_sync_get(rsclient: KanidmClient) {
.build()
.unwrap();
// here we test the /ui/ endpoint which should have the headers
let response = match client.get(format!("{}/scim/v1/Sync", addr)).send().await {
let response = match client.get(rsclient.make_url("/scim/v1/Sync")).send().await {
Ok(value) => value,
Err(error) => {
panic!("Failed to query {:?} : {:#?}", addr, error);
panic!(
"Failed to query {:?} : {:#?}",
rsclient.make_url("/scim/v1/Sync"),
error
);
}
};
eprintln!("response: {:#?}", response);

View file

@ -4,20 +4,23 @@ use kanidm_client::KanidmClient;
#[kanidmd_testkit::test]
async fn test_v1_self_applinks(rsclient: KanidmClient) {
// We need to do manual reqwests here.
let addr = rsclient.get_url();
let client = reqwest::ClientBuilder::new()
.danger_accept_invalid_certs(true)
.build()
.unwrap();
let response = match client
.get(format!("{}/v1/self/_applinks", &addr))
.get(rsclient.make_url("/v1/self/_applinks"))
.send()
.await
{
Ok(value) => value,
Err(error) => {
panic!("Failed to query {:?} : {:#?}", addr, error);
panic!(
"Failed to query {:?} : {:#?}",
rsclient.make_url("/v1/self/_applinks"),
error
);
}
};
eprintln!("response: {:#?}", response);
@ -31,16 +34,19 @@ async fn test_v1_self_applinks(rsclient: KanidmClient) {
#[kanidmd_testkit::test]
async fn test_v1_self_whoami_uat(rsclient: KanidmClient) {
// We need to do manual reqwests here.
let addr = rsclient.get_url();
let client = reqwest::ClientBuilder::new()
.danger_accept_invalid_certs(true)
.build()
.unwrap();
let response = match client.get(format!("{}/v1/self/_uat", &addr)).send().await {
let response = match client.get(rsclient.make_url("/v1/self/_uat")).send().await {
Ok(value) => value,
Err(error) => {
panic!("Failed to query {:?} : {:#?}", addr, error);
panic!(
"Failed to query {:?} : {:#?}",
rsclient.make_url("/v1/self/_uat"),
error
);
}
};
eprintln!("response: {:#?}", response);

View file

@ -4,7 +4,6 @@ use kanidm_client::KanidmClient;
#[kanidmd_testkit::test]
async fn test_v1_service_account_id_attr_attr_delete(rsclient: KanidmClient) {
// We need to do manual reqwests here.
let addr = rsclient.get_url();
let client = reqwest::ClientBuilder::new()
.danger_accept_invalid_certs(true)
.build()
@ -13,13 +12,17 @@ async fn test_v1_service_account_id_attr_attr_delete(rsclient: KanidmClient) {
// let post_body = serde_json::json!({"filter": "self"}).to_string();
let response = match client
.delete(format!("{}/v1/service_account/admin/_attr/email", &addr))
.delete(rsclient.make_url("/v1/service_account/admin/_attr/email"))
.send()
.await
{
Ok(value) => value,
Err(error) => {
panic!("Failed to query {:?} : {:#?}", addr, error);
panic!(
"Failed to query {:?} : {:#?}",
rsclient.make_url("/v1/service_account/admin/_attr/email"),
error
);
}
};
eprintln!("response: {:#?}", response);

View file

@ -3,22 +3,24 @@ use kanidm_client::KanidmClient;
/// This literally tests that the thing exists and responds in a way we expect, probably worth testing it better...
#[kanidmd_testkit::test]
async fn test_v1_system_post_attr(rsclient: KanidmClient) {
// We need to do manual reqwests here.
let addr = rsclient.get_url();
let client = reqwest::ClientBuilder::new()
.danger_accept_invalid_certs(true)
.build()
.unwrap();
let response = match client
.post(format!("{}/v1/system/_attr/domain_name", &addr))
.post(rsclient.make_url("/v1/system/_attr/domain_name"))
.json(&serde_json::json!({"filter": "self"}))
.send()
.await
{
Ok(value) => value,
Err(error) => {
panic!("Failed to query {:?} : {:#?}", addr, error);
panic!(
"Failed to query {:?} : {:#?}",
rsclient.make_url("v1/system/_attr/domain_name"),
error
);
}
};
eprintln!("response: {:#?}", response);

View file

@ -0,0 +1,46 @@
use kanidm_client::KanidmClient;
use kanidmd_testkit::*;
#[kanidmd_testkit::test]
async fn account_id_unix_token(rsclient: KanidmClient) {
login_put_admin_idm_admins(&rsclient).await;
create_user(&rsclient, "group_manager", "idm_group_manage_priv").await;
// create test user without creating new groups
create_user(&rsclient, NOT_ADMIN_TEST_USERNAME, "idm_admins").await;
login_account(&rsclient, "group_manager").await;
let response = rsclient
.idm_account_unix_token_get(NOT_ADMIN_TEST_USERNAME)
.await;
assert!(response.is_err());
if let Err(val) = response {
assert!(format!("{:?}", val).contains("404"));
}
let response = rsclient.idm_account_unix_token_get("lol").await;
assert!(response.is_err());
if let Err(val) = response {
assert!(format!("{:?}", val).contains("404"));
}
// testing empty results
let response = rsclient.idm_account_unix_token_get("").await;
assert!(response.is_err());
if let Err(val) = response {
assert!(format!("{:?}", val).contains("400"));
}
login_put_admin_idm_admins(&rsclient).await;
rsclient
.idm_person_account_unix_extend(NOT_ADMIN_TEST_USERNAME, None, None)
.await
.unwrap();
// testing NOT_ADMIN_TEST_USERNAME has a token result, since we just added one
assert!(rsclient
.idm_account_unix_token_get(NOT_ADMIN_TEST_USERNAME)
.await
.is_ok());
}

View file

@ -16,7 +16,6 @@ use qrcode::render::unicode;
use qrcode::QrCode;
use time::format_description::well_known::Rfc3339;
use time::OffsetDateTime;
use url::Url;
use uuid::Uuid;
use crate::webauthn::get_authenticator;
@ -603,14 +602,7 @@ impl AccountCredential {
.await
{
Ok(cuintent_token) => {
let mut url = match Url::parse(client.get_url()) {
Ok(u) => u,
Err(e) => {
error!("Unable to parse url - {:?}", e);
return;
}
};
url.set_path("/ui/reset");
let mut url = client.make_url("/ui/reset");
url.query_pairs_mut()
.append_pair("token", cuintent_token.token.as_str());

View file

@ -78,11 +78,19 @@ pub struct DbTxn<'a> {
require_tpm: Option<&'a tpm::TpmConfig>,
}
#[derive(Debug)]
/// Errors coming back from the `Db` struct
pub enum DbError {
Sqlite,
Tpm,
}
impl Db {
pub fn new(path: &str, tpm_policy: &TpmPolicy) -> Result<Self, ()> {
pub fn new(path: &str, tpm_policy: &TpmPolicy) -> Result<Self, DbError> {
let before = unsafe { umask(0o0027) };
let conn = Connection::open(path).map_err(|e| {
error!(err = ?e, "rusqulite error");
DbError::Sqlite
})?;
let _ = unsafe { umask(before) };
// We only build a single thread. If we need more than one, we'll
@ -96,7 +104,9 @@ impl Db {
let require_tpm = match tpm_policy {
TpmPolicy::Ignore => None,
TpmPolicy::IfPossible(tcti_str) => Db::tpm_setup_context(tcti_str, &conn).ok(),
TpmPolicy::Required(tcti_str) => Some(Db::tpm_setup_context(tcti_str, &conn)?),
TpmPolicy::Required(tcti_str) => {
Some(Db::tpm_setup_context(tcti_str, &conn).map_err(|_| DbError::Tpm)?)
}
};
Ok(Db {
@ -784,16 +794,19 @@ impl<'a> Drop for DbTxn<'a> {
#[cfg(not(feature = "tpm"))]
pub(crate) mod tpm {
use super::Db;
use super::{Db, DbError};
use rusqlite::Connection;
pub struct TpmConfig {}
impl Db {
pub fn tpm_setup_context(_tcti_str: &str, _conn: &Connection) -> Result<TpmConfig, ()> {
pub fn tpm_setup_context(
_tcti_str: &str,
_conn: &Connection,
) -> Result<TpmConfig, DbError> {
warn!("tpm feature is not available in this build");
Err(())
Err(DbError::Tpm)
}
}
}