manta_server/service/
template.rs1use manta_backend_dispatcher::error::Error;
4use manta_backend_dispatcher::interfaces::bos::{
5 ClusterSessionTrait, ClusterTemplateTrait,
6};
7use manta_backend_dispatcher::interfaces::hsm::group::GroupTrait;
8use manta_backend_dispatcher::types::bos::session::BosSession;
9use manta_backend_dispatcher::types::bos::session::Operation;
10use manta_backend_dispatcher::types::bos::session_template::BosSessionTemplate;
11
12use crate::server::common::app_context::InfraContext;
13use crate::service::authorization::{
14 validate_user_group_members_access, validate_user_group_vec_access,
15};
16use crate::service::node_ops::validate_xname_format;
17pub use manta_shared::types::api::template::{
18 ApplyTemplateParams, GetTemplateParams,
19};
20
21pub async fn get_templates(
30 infra: &InfraContext<'_>,
31 token: &str,
32 params: &GetTemplateParams,
33) -> Result<Vec<BosSessionTemplate>, Error> {
34 let target_group_vec: Vec<String> = if let Some(group) = ¶ms.group_name {
36 vec![group.clone()]
37 } else {
38 infra
39 .backend
40 .get_group_available(token)
41 .await?
42 .iter()
43 .map(|group| group.label.clone())
44 .collect()
45 };
46
47 validate_user_group_vec_access(infra, token, &target_group_vec).await?;
49
50 let hsm_member_vec = infra
51 .backend
52 .get_member_vec_from_group_name_vec(token, &target_group_vec)
53 .await?;
54
55 let limit_ref = params.limit.as_ref();
56
57 tracing::info!(
58 "Get BOS sessiontemplates for HSM groups: {:?}",
59 target_group_vec
60 );
61
62 let mut bos_sessiontemplate_vec = infra
63 .backend
64 .get_and_filter_templates(
65 token,
66 &target_group_vec,
67 &hsm_member_vec,
68 params.name.as_deref(),
69 limit_ref,
70 )
71 .await?;
72
73 bos_sessiontemplate_vec.sort_by(|a, b| a.name.cmp(&b.name));
74
75 Ok(bos_sessiontemplate_vec)
76}
77
78pub async fn validate_and_prepare_template_session(
90 infra: &InfraContext<'_>,
91 token: &str,
92 params: &ApplyTemplateParams,
93) -> Result<(BosSession, Vec<String>), Error> {
94 let bos_sessiontemplate_vec = infra
96 .backend
97 .get_and_filter_templates(
98 token,
99 &[],
100 &[],
101 Some(¶ms.bos_sessiontemplate_name),
102 None,
103 )
104 .await?;
105
106 let bos_sessiontemplate = if bos_sessiontemplate_vec.is_empty() {
107 return Err(Error::NotFound(format!(
108 "No BOS sessiontemplate '{}' found",
109 params.bos_sessiontemplate_name
110 )));
111 } else {
112 bos_sessiontemplate_vec.first().ok_or_else(|| {
113 Error::NotFound("BOS sessiontemplate list unexpectedly empty".to_string())
114 })?
115 };
116
117 tracing::info!(
119 "Validate user has access to HSM group in BOS sessiontemplate"
120 );
121 let target_hsm_vec = bos_sessiontemplate.get_target_hsm();
122 let target_xname_vec: Vec<String> = if !target_hsm_vec.is_empty() {
123 infra
124 .backend
125 .get_member_vec_from_group_name_vec(token, &target_hsm_vec)
126 .await
127 .unwrap_or_default()
128 } else {
129 bos_sessiontemplate.get_target_xname()
130 };
131
132 validate_user_group_members_access(infra, token, &target_xname_vec).await?;
133
134 tracing::info!("Validate user has access to xnames in BOS sessiontemplate");
136 let limit_vec: Vec<String> =
137 params.limit.split(',').map(str::to_string).collect();
138
139 let mut xnames_to_validate_access_vec = Vec::new();
140
141 for limit_value in &limit_vec {
142 tracing::info!("Check if limit value '{}', is an xname", limit_value);
143 if validate_xname_format(limit_value) {
144 tracing::info!("limit value '{}' is an xname", limit_value);
145 xnames_to_validate_access_vec.push(limit_value.clone());
146 } else {
147 let hsm_members_vec_rslt = infra
148 .backend
149 .get_member_vec_from_group_name_vec(
150 token,
151 std::slice::from_ref(limit_value),
152 )
153 .await;
154
155 if let Ok(mut hsm_members_vec) = hsm_members_vec_rslt {
156 tracing::info!(
157 "Check if limit value '{}', is an HSM group name",
158 limit_value
159 );
160 xnames_to_validate_access_vec.append(&mut hsm_members_vec);
161 } else {
162 return Err(Error::BadRequest(format!(
163 "Value '{limit_value}' in 'limit' argument does not match \
164 an xname or a HSM group name."
165 )));
166 }
167 }
168 }
169
170 tracing::info!("Validate list of xnames translated from 'limit argument'");
171 validate_user_group_members_access(
172 infra,
173 token,
174 &xnames_to_validate_access_vec,
175 )
176 .await?;
177
178 tracing::info!("Access to '{}' granted. Continue.", params.limit);
179
180 let bos_session = BosSession {
182 name: params.bos_session_name.clone(),
183 tenant: None,
184 operation: Some(
185 Operation::from_str(¶ms.bos_session_operation).map_err(|_| {
186 Error::BadRequest(format!(
187 "Invalid BOS session operation '{}'",
188 params.bos_session_operation
189 ))
190 })?,
191 ),
192 template_name: params.bos_sessiontemplate_name.clone(),
193 limit: Some(limit_vec.join(",")),
194 stage: Some(false),
195 components: None,
196 include_disabled: Some(params.include_disabled),
197 status: None,
198 };
199
200 Ok((bos_session, limit_vec))
201}
202
203pub async fn create_bos_session(
209 infra: &InfraContext<'_>,
210 token: &str,
211 bos_session: BosSession,
212) -> Result<BosSession, Error> {
213 infra
214 .backend
215 .post_template_session(token, bos_session)
216 .await
217}