manta_server/service/
sat_file.rs

1//! SAT-file service wrappers.
2//!
3//! Thin forwarders from the HTTP handlers to the backend dispatcher,
4//! enforcing the CLAUDE.md boundary rule (handlers → service → backend).
5//!
6//! [`apply_session_template`] and [`validate_sat_file`] also consolidate
7//! the duplicate `get_group_name_available` fetch that the handlers
8//! previously performed twice (once inside `validate_user_group_vec_access`,
9//! once to build the `hsm_group_available_vec` argument): the service
10//! function fetches the group list once, validates it in-memory, and
11//! forwards it to the backend.
12
13use std::collections::HashMap;
14
15use manta_backend_dispatcher::error::Error;
16use manta_backend_dispatcher::interfaces::apply_sat_file::{
17  ApplyConfigurationParams, ApplyImageCreateSessionParams,
18  ApplyImageStampParams, ApplySessionTemplateParams, SatTrait,
19  ValidateSatFileParams,
20};
21use manta_backend_dispatcher::types::bos::{
22  session::BosSession, session_template::BosSessionTemplate,
23};
24use manta_backend_dispatcher::types::cfs::cfs_configuration_response::CfsConfigurationResponse;
25use manta_backend_dispatcher::types::cfs::session::CfsSessionGetResponse;
26use manta_backend_dispatcher::types::ims::Image;
27
28use crate::server::common::app_context::InfraContext;
29use crate::service::authorization;
30
31/// Apply a single SAT `configurations[]` entry.
32///
33/// CFS configurations are not HSM-group-scoped so no caller-access
34/// check is performed here. The backend's own RBAC layer enforces
35/// CSM-level authorization.
36#[allow(clippy::too_many_arguments)]
37pub async fn apply_configuration(
38  infra: &InfraContext<'_>,
39  token: &str,
40  vault_base_url: &str,
41  k8s_api_url: &str,
42  gitea_token: &str,
43  configuration: serde_json::Value,
44  dry_run: bool,
45  overwrite: bool,
46) -> Result<CfsConfigurationResponse, Error> {
47  infra
48    .backend
49    .apply_configuration(ApplyConfigurationParams {
50      shasta_token: token,
51      vault_base_url,
52      site_name: infra.site_name,
53      k8s_api_url,
54      gitea_base_url: infra.gitea_base_url,
55      gitea_token,
56      configuration,
57      dry_run,
58      overwrite,
59    })
60    .await
61}
62
63/// Translate one SAT `images[]` entry into a CFS session and create it.
64///
65/// Returns the created [`CfsSessionGetResponse`] without waiting for the
66/// session to complete (the CLI drives monitor + stamp steps itself).
67/// Caller-access validation for the image's target groups must be done
68/// BEFORE calling this function (see
69/// [`crate::service::authorization::validate_user_group_vec_access`]).
70#[allow(clippy::too_many_arguments)]
71pub async fn create_image_cfs_session(
72  infra: &InfraContext<'_>,
73  token: &str,
74  vault_base_url: &str,
75  k8s_api_url: &str,
76  image: serde_json::Value,
77  ref_lookup: HashMap<String, String>,
78  ansible_verbosity: Option<u8>,
79  ansible_passthrough: Option<&str>,
80  dry_run: bool,
81) -> Result<CfsSessionGetResponse, Error> {
82  infra
83    .backend
84    .apply_sat_image_create_session(ApplyImageCreateSessionParams {
85      shasta_token: token,
86      vault_base_url,
87      site_name: infra.site_name,
88      k8s_api_url,
89      image,
90      ref_lookup,
91      ansible_verbosity,
92      ansible_passthrough,
93      dry_run,
94    })
95    .await
96}
97
98/// Stamp `manta.image_session.*` provenance metadata onto the IMS image
99/// produced by a (terminal-complete) CFS session.
100///
101/// Session-access validation and result-image existence checks must be
102/// done BEFORE calling this; see
103/// [`crate::service::session::validate_session_access`] and
104/// [`crate::service::session::require_result_image`].
105pub async fn stamp_image_from_session(
106  infra: &InfraContext<'_>,
107  token: &str,
108  cfs_session_name: &str,
109) -> Result<Image, Error> {
110  infra
111    .backend
112    .apply_sat_image_stamp_from_session(ApplyImageStampParams {
113      shasta_token: token,
114      cfs_session_name,
115    })
116    .await
117}
118
119/// Apply a single SAT `session_templates[]` entry.
120///
121/// Fetches the caller's accessible group list once; for non-admin callers
122/// validates that every group in `target_groups` is accessible, then
123/// passes the full list to the backend as `hsm_group_available_vec`.
124/// This consolidates the two `get_group_name_available` calls that the
125/// handler previously performed (one inside `validate_user_group_vec_access`,
126/// one to build the backend param) into a single backend round-trip.
127pub async fn apply_session_template(
128  infra: &InfraContext<'_>,
129  token: &str,
130  session_template: serde_json::Value,
131  ref_lookup: HashMap<String, String>,
132  target_groups: &[String],
133  reboot: bool,
134  dry_run: bool,
135) -> Result<(BosSessionTemplate, Option<BosSession>), Error> {
136  let hsm_group_available_vec =
137    authorization::fetch_group_names_and_validate_access(
138      infra,
139      token,
140      target_groups,
141    )
142    .await?;
143  infra
144    .backend
145    .apply_session_template(ApplySessionTemplateParams {
146      shasta_token: token,
147      session_template,
148      ref_lookup,
149      hsm_group_available_vec: &hsm_group_available_vec,
150      reboot,
151      dry_run,
152    })
153    .await
154}
155
156/// Pre-flight validate a SAT file against live CSM state without mutating
157/// anything.
158///
159/// Fetches the caller's accessible group list once; for non-admin callers
160/// validates that every group in `target_groups` is accessible, then
161/// passes the full list to the backend. Same single-fetch consolidation
162/// as [`apply_session_template`].
163pub async fn validate_sat_file(
164  infra: &InfraContext<'_>,
165  token: &str,
166  sat_file: serde_json::Value,
167  target_groups: &[String],
168  vault_base_url: &str,
169  k8s_api_url: &str,
170) -> Result<(), Error> {
171  let hsm_group_available_vec =
172    authorization::fetch_group_names_and_validate_access(
173      infra,
174      token,
175      target_groups,
176    )
177    .await?;
178  infra
179    .backend
180    .validate_sat_file(ValidateSatFileParams {
181      shasta_token: token,
182      vault_base_url,
183      site_name: infra.site_name,
184      k8s_api_url,
185      sat_file,
186      hsm_group_available_vec: &hsm_group_available_vec,
187    })
188    .await
189}