1use axum::{middleware::from_fn, response::Redirect, routing::get, Router};
2use kanidm_proto::{attribute, internal, scim_v1, v1};
3use utoipa::{
4 openapi::security::{HttpAuthScheme, HttpBuilder, SecurityScheme},
5 Modify, OpenApi,
6};
7use utoipa_swagger_ui::SwaggerUi;
8
9use super::{errors::WebError, ServerState};
10
11pub(crate) mod path_schema;
12pub(crate) mod response_schema;
13#[cfg(test)]
14pub(crate) mod tests;
15
16struct SecurityAddon;
17
18impl Modify for SecurityAddon {
19 fn modify(&self, openapi: &mut utoipa::openapi::OpenApi) {
20 if let Some(components) = openapi.components.as_mut() {
21 components.add_security_scheme(
22 "token_jwt",
23 SecurityScheme::Http(
24 HttpBuilder::new()
25 .scheme(HttpAuthScheme::Bearer)
26 .bearer_format("JWT")
27 .build(),
28 ),
29 )
30 }
31 }
32}
33
34#[derive(OpenApi)]
36#[openapi(
37 servers(
38 (url="https://{host}:{port}",
39 variables(
40 ("host" = (default="localhost", description="Server's hostname")),
41 ("port" = (default="8443", description="Server HTTPS port")),
42 )
43 )
44 ),
45 external_docs(url = "https://kanidm.com/docs", description = "Kanidm documentation page"),
46
47 paths(
48 super::generic::status,
49 super::generic::robots_txt,
50
51 super::oauth2::oauth2_image_get,
52
53 super::v1::raw_create,
54 super::v1::raw_delete,
55 super::v1::raw_modify,
56 super::v1::raw_search,
57
58 super::v1_oauth2::oauth2_id_image_delete,
59 super::v1_oauth2::oauth2_id_image_post,
60 super::v1_oauth2::oauth2_get,
61 super::v1_oauth2::oauth2_basic_post,
62 super::v1_oauth2::oauth2_public_post,
63 super::v1_oauth2::oauth2_id_get,
64 super::v1_oauth2::oauth2_id_patch,
65 super::v1_oauth2::oauth2_id_delete,
66 super::v1_oauth2::oauth2_id_image_post,
67 super::v1_oauth2::oauth2_id_image_delete,
68 super::v1_oauth2::oauth2_id_get_basic_secret,
69 super::v1_oauth2::oauth2_id_scopemap_post,
70 super::v1_oauth2::oauth2_id_scopemap_delete,
71 super::v1_oauth2::oauth2_id_sup_scopemap_post,
72 super::v1_oauth2::oauth2_id_sup_scopemap_delete,
73 super::v1_oauth2::oauth2_id_claimmap_join_post,
74 super::v1_oauth2::oauth2_id_claimmap_post,
75 super::v1_oauth2::oauth2_id_claimmap_delete,
76
77 super::v1_scim::scim_sync_post,
78 super::v1_scim::scim_sync_get,
79 super::v1_scim::scim_entry_id_get,
80 super::v1_scim::scim_person_id_get,
81 super::v1_scim::scim_person_id_application_create_password,
82 super::v1_scim::scim_person_id_application_delete_password,
83 super::v1_scim::scim_application_get,
84 super::v1_scim::scim_application_post,
85 super::v1_scim::scim_application_id_get,
86 super::v1_scim::scim_application_id_delete,
87 super::v1_scim::scim_schema_attribute_get,
88 super::v1_scim::scim_schema_class_get,
89
90 super::v1::schema_get,
91 super::v1::whoami,
92 super::v1::whoami_uat,
93 super::v1::applinks_get,
94 super::v1::schema_attributetype_get,
95 super::v1::schema_attributetype_get_id,
96 super::v1::schema_classtype_get,
97 super::v1::schema_classtype_get_id,
98 super::v1::person_get,
99 super::v1::person_post,
100 super::v1::service_account_credential_generate,
101 super::v1::service_account_api_token_delete,
102 super::v1::service_account_api_token_get,
103 super::v1::service_account_api_token_post,
104 super::v1::person_search_id,
105 super::v1::person_id_get,
106 super::v1::person_id_patch,
107 super::v1::person_id_delete,
108 super::v1::person_id_get_attr,
109 super::v1::person_id_put_attr,
110 super::v1::person_id_post_attr,
111 super::v1::person_id_delete_attr,
112 super::v1::person_get_id_certificate,
113 super::v1::person_post_id_certificate,
114 super::v1::person_get_id_credential_status,
115 super::v1::person_id_credential_update_get,
116 super::v1::person_id_credential_update_intent_get,
117 super::v1::person_id_credential_update_intent_ttl_get,
118
119 super::v1::service_account_id_ssh_pubkeys_get,
120 super::v1::service_account_id_ssh_pubkeys_post,
121
122 super::v1::person_id_ssh_pubkeys_get,
123 super::v1::person_id_ssh_pubkeys_post,
124 super::v1::person_id_ssh_pubkeys_tag_get,
125 super::v1::person_id_ssh_pubkeys_tag_delete,
126
127 super::v1::person_id_radius_get,
128 super::v1::person_id_radius_post,
129 super::v1::person_id_radius_delete,
130 super::v1::person_id_radius_token_get,
131
132 super::v1::account_id_ssh_pubkeys_get,
133 super::v1::account_id_radius_token_post,
134 super::v1::person_id_unix_post,
135 super::v1::person_id_unix_credential_put,
136 super::v1::person_id_unix_credential_delete,
137 super::v1::person_identify_user_post,
138 super::v1::service_account_get,
139 super::v1::service_account_post,
140 super::v1::service_account_get,
141 super::v1::service_account_post,
142 super::v1::service_account_id_get,
143 super::v1::service_account_id_delete,
144 super::v1::service_account_id_patch,
145 super::v1::service_account_id_get_attr,
146 super::v1::service_account_id_put_attr,
147 super::v1::service_account_id_post_attr,
148 super::v1::service_account_id_delete_attr,
149 super::v1::service_account_into_person,
150 super::v1::service_account_api_token_post,
151 super::v1::service_account_api_token_get,
152 super::v1::service_account_api_token_delete,
153 super::v1::service_account_credential_generate,
154 super::v1::service_account_id_credential_status_get,
155 super::v1::service_account_id_ssh_pubkeys_tag_get,
156 super::v1::service_account_id_ssh_pubkeys_tag_delete,
157 super::v1::service_account_id_unix_post,
158 super::v1::account_id_unix_auth_post,
159 super::v1::account_id_unix_token,
160 super::v1::account_id_unix_token,
161 super::v1::account_id_radius_token_post,
162 super::v1::account_id_radius_token_get,
163 super::v1::account_id_ssh_pubkeys_get,
164 super::v1::account_id_ssh_pubkeys_tag_get,
165 super::v1::account_id_user_auth_token_get,
166 super::v1::account_user_auth_token_delete,
167 super::v1::credential_update_exchange_intent,
168 super::v1::credential_update_status,
169 super::v1::credential_update_update,
170 super::v1::credential_update_commit,
171 super::v1::credential_update_cancel,
172 super::v1::domain_get,
173 super::v1::domain_attr_get,
174 super::v1::domain_attr_put,
175 super::v1::domain_attr_delete,
176 super::v1_domain::image_post,
177 super::v1_domain::image_delete,
178
179 super::v1::group_id_unix_token_get,
180 super::v1::group_id_unix_post,
181 super::v1::group_get,
182 super::v1::group_post,
183 super::v1::group_search_id,
184 super::v1::group_id_get,
185 super::v1::group_id_patch,
186 super::v1::group_id_delete,
187 super::v1::group_id_attr_delete,
188 super::v1::group_id_attr_get,
189 super::v1::group_id_attr_put,
190 super::v1::group_id_attr_post,
191 super::v1::system_get,
192 super::v1::system_attr_get,
193 super::v1::system_attr_post,
194 super::v1::system_attr_put,
195 super::v1::system_attr_delete,
196 super::v1::recycle_bin_get,
197 super::v1::recycle_bin_id_get,
198 super::v1::recycle_bin_revive_id_post,
199 super::v1::auth,
200 super::v1::auth_valid,
201 super::v1::logout,
202 super::v1::reauth,
203 super::v1_scim::sync_account_get,
204 super::v1_scim::sync_account_post,
205 super::v1_scim::sync_account_id_get,
206 super::v1_scim::sync_account_id_patch,
207 super::v1_scim::sync_account_id_attr_get,
208 super::v1_scim::sync_account_id_attr_put,
209 super::v1_scim::sync_account_id_finalise_get,
210 super::v1_scim::sync_account_id_terminate_get,
211 super::v1_scim::sync_account_token_post,
212 super::v1_scim::sync_account_token_delete,
213 super::v1::debug_ipinfo,
214 super::v1::public_jwk_key_id_get,
215
216 ),
217 components(
218 schemas(
219 attribute::Attribute,
220
221 scim_v1::ScimSyncState,
222 scim_v1::ScimSyncRequest,
223 scim_v1::ScimSyncRetentionMode,
224 scim_v1::ScimEntry,
225 scim_v1::ScimValue,
226 scim_v1::ScimMeta,
227 scim_v1::ScimAttr,
228 scim_v1::ScimApplicationPasswordCreate,
229 scim_v1::ScimApplicationPassword,
230 scim_v1::client::ScimEntryPostGeneric,
231
232 internal::ApiToken,
233 internal::ApiTokenPurpose,
234 internal::BackupCodesView,
235 internal::ConsistencyError,
236 internal::CreateRequest,
237 internal::CredentialDetail,
238 internal::CredentialDetailType,
239 internal::CredentialStatus,
240 internal::CUExtPortal,
241 internal::CUIntentToken,
242 internal::CURegState,
243 internal::CUSessionToken,
244 internal::CUStatus,
245 internal::DeleteRequest,
246 internal::Filter,
247 internal::Group,
248 internal::Modify,
249 internal::ModifyList,
250 internal::ModifyRequest,
251 internal::Oauth2ClaimMapJoin,
252 internal::OperationError,
253 internal::PasskeyDetail,
254 internal::PasswordFeedback,
255 internal::PluginError,
256 internal::RadiusAuthToken,
257 internal::SchemaError,
258 internal::SearchRequest,
259 internal::SearchResponse,
260 internal::TotpAlgo,
261 internal::TotpSecret,
262 internal::UatPurpose,
263 internal::UserAuthToken,
264 v1::AccountUnixExtend,
265 v1::ApiTokenGenerate,
266 v1::AuthAllowed,
267 v1::AuthCredential,
268 v1::AuthIssueSession,
269 v1::AuthMech,
270 v1::AuthRequest,
271 v1::AuthResponse,
272 v1::AuthState,
273 v1::AuthStep,
274 v1::Entry,
275 v1::GroupUnixExtend,
276 v1::PublicKeyKindSchema,
277 v1::SingleStringRequest,
278 v1::SshPublicKeySchema,
279 v1::KeyTypeKindSchema,
280 v1::KeyTypeSchema,
281 internal::UiHint,
282 v1::UatPurposeStatus,
283 v1::UatStatus,
284 v1::UatStatusState,
285 v1::UnixGroupToken,
286 v1::UnixUserToken,
287 v1::WhoamiResponse,
288 internal::CUCredState,
289 internal::CURegWarning,
290 internal::IdentifyUserResponse,
291 internal::AppLink,
292
293 internal::IdentifyUserRequest,
294 response_schema::CreationChallengeResponse,
296
297 response_schema::PublicKeyCredential,
299 response_schema::RequestChallengeResponse,
301 response_schema::Base64UrlSafeData,
303 response_schema::BTreeSet,
305 response_schema::Result,
307 response_schema::ScimEntry,
309 response_schema::ProtoEntry,
311 response_schema::Jwk,
313 response_schema::ScimComplexAttr,
314 WebError,
315 )
316 ),
317 modifiers(&SecurityAddon),
318 tags(
319 (name = "kanidm", description = "Kanidm API")
320 ),
321 info(
322 title = "Kanidm",
323 description = "API for interacting with the Kanidm system. This is a work in progress.",
324 contact( name="Kanidm Github",
326 url="https://github.com/kanidm/kanidm",
327 )
328 )
329)]
330pub(crate) struct ApiDoc;
331
332pub(crate) fn router() -> Router<ServerState> {
333 Router::new()
334 .route("/docs", get(Redirect::temporary("/docs/swagger-ui")))
335 .route("/docs/", get(Redirect::temporary("/docs/swagger-ui")))
336 .merge(SwaggerUi::new("/docs/swagger-ui").url("/docs/v1/openapi.json", ApiDoc::openapi()))
337 .layer(from_fn(super::middleware::version_middleware))
339}