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::server::common::authorization::{
14 get_groups_names_available, validate_target_hsm_members,
15};
16use crate::server::common::node_ops::validate_xname_format;
17pub use manta_shared::shared::params::template::{
18 ApplyTemplateParams, GetTemplateParams,
19};
20
21pub async fn get_templates(
23 infra: &InfraContext<'_>,
24 token: &str,
25 params: &GetTemplateParams,
26) -> Result<Vec<BosSessionTemplate>, Error> {
27 let target_hsm_group_vec = get_groups_names_available(
28 infra.backend,
29 token,
30 params.hsm_group.as_deref(),
31 params.settings_hsm_group_name.as_deref(),
32 )
33 .await?;
34
35 let hsm_member_vec = infra
36 .backend
37 .get_member_vec_from_group_name_vec(token, &target_hsm_group_vec)
38 .await?;
39
40 let limit_ref = params.limit.as_ref();
41
42 tracing::info!(
43 "Get BOS sessiontemplates for HSM groups: {:?}",
44 target_hsm_group_vec
45 );
46
47 let mut bos_sessiontemplate_vec = infra
48 .backend
49 .get_and_filter_templates(
50 token,
51 infra.shasta_base_url,
52 infra.shasta_root_cert,
53 &target_hsm_group_vec,
54 &hsm_member_vec,
55 params.name.as_deref(),
56 limit_ref,
57 )
58 .await?;
59
60 bos_sessiontemplate_vec.sort_by(|a, b| a.name.cmp(&b.name));
61
62 Ok(bos_sessiontemplate_vec)
63}
64
65pub async fn validate_and_prepare_template_session(
70 infra: &InfraContext<'_>,
71 token: &str,
72 params: &ApplyTemplateParams,
73) -> Result<(BosSession, Vec<String>), Error> {
74 let backend = infra.backend;
75
76 let bos_sessiontemplate_vec = backend
78 .get_and_filter_templates(
79 token,
80 infra.shasta_base_url,
81 infra.shasta_root_cert,
82 &[],
83 &[],
84 Some(¶ms.bos_sessiontemplate_name),
85 None,
86 )
87 .await?;
88
89 let bos_sessiontemplate = if bos_sessiontemplate_vec.is_empty() {
90 return Err(Error::NotFound(format!(
91 "No BOS sessiontemplate '{}' found",
92 params.bos_sessiontemplate_name
93 )));
94 } else {
95 bos_sessiontemplate_vec.first().ok_or_else(|| {
96 Error::NotFound("BOS sessiontemplate list unexpectedly empty".to_string())
97 })?
98 };
99
100 tracing::info!(
102 "Validate user has access to HSM group in BOS sessiontemplate"
103 );
104 let target_hsm_vec = bos_sessiontemplate.get_target_hsm();
105 let target_xname_vec: Vec<String> = if !target_hsm_vec.is_empty() {
106 backend
107 .get_member_vec_from_group_name_vec(token, &target_hsm_vec)
108 .await
109 .unwrap_or_default()
110 } else {
111 bos_sessiontemplate.get_target_xname()
112 };
113
114 validate_target_hsm_members(backend, token, &target_xname_vec).await?;
115
116 tracing::info!("Validate user has access to xnames in BOS sessiontemplate");
118 let limit_vec: Vec<String> =
119 params.limit.split(',').map(str::to_string).collect();
120
121 let mut xnames_to_validate_access_vec = Vec::new();
122
123 for limit_value in &limit_vec {
124 tracing::info!("Check if limit value '{}', is an xname", limit_value);
125 if validate_xname_format(limit_value) {
126 tracing::info!("limit value '{}' is an xname", limit_value);
127 xnames_to_validate_access_vec.push(limit_value.to_string());
128 } else {
129 let hsm_members_vec_rslt = backend
130 .get_member_vec_from_group_name_vec(
131 token,
132 std::slice::from_ref(limit_value),
133 )
134 .await;
135
136 if let Ok(mut hsm_members_vec) = hsm_members_vec_rslt {
137 tracing::info!(
138 "Check if limit value '{}', is an HSM group name",
139 limit_value
140 );
141 xnames_to_validate_access_vec.append(&mut hsm_members_vec);
142 } else {
143 return Err(Error::BadRequest(format!(
144 "Value '{limit_value}' in 'limit' argument does not match \
145 an xname or a HSM group name."
146 )));
147 }
148 }
149 }
150
151 tracing::info!("Validate list of xnames translated from 'limit argument'");
152 validate_target_hsm_members(backend, token, &xnames_to_validate_access_vec)
153 .await?;
154
155 tracing::info!("Access to '{}' granted. Continue.", params.limit);
156
157 let bos_session = BosSession {
159 name: params.bos_session_name.clone(),
160 tenant: None,
161 operation: Some(
162 Operation::from_str(¶ms.bos_session_operation).map_err(|_| {
163 Error::BadRequest(format!(
164 "Invalid BOS session operation '{}'",
165 params.bos_session_operation
166 ))
167 })?,
168 ),
169 template_name: params.bos_sessiontemplate_name.clone(),
170 limit: Some(limit_vec.join(",")),
171 stage: Some(false),
172 components: None,
173 include_disabled: Some(params.include_disabled),
174 status: None,
175 };
176
177 Ok((bos_session, limit_vec))
178}
179
180pub async fn create_bos_session(
182 infra: &InfraContext<'_>,
183 token: &str,
184 bos_session: BosSession,
185) -> Result<BosSession, Error> {
186 infra
187 .backend
188 .post_template_session(
189 token,
190 infra.shasta_base_url,
191 infra.shasta_root_cert,
192 bos_session,
193 )
194 .await
195}