Skip to main content

kipuka_dogtag/
cmc.rs

1//! Full CMC (Certificate Management over CMS) operations.
2//!
3//! Provides passthrough submission of CMC requests to Dogtag's CMC Full
4//! enrollment endpoint. This supports kipuka's `/fullcmc` EST endpoint
5//! (RFC 7030 S4.3) by proxying CMC messages directly to the CA.
6
7use tracing::debug;
8
9use crate::client::DogtagClient;
10use crate::{DogtagError, DogtagResult};
11
12/// CMC-specific client operations.
13///
14/// Thin wrapper indicating CMC-related functionality. The actual HTTP
15/// client is shared via [`DogtagClient`].
16pub struct CmcClient;
17
18impl DogtagClient {
19    /// Submit a Full CMC request to Dogtag.
20    ///
21    /// Sends `POST /ca/ee/ca/profileSubmitCMCFull` with the raw CMC
22    /// request bytes (DER-encoded CMS/PKCS#7). Returns the CMC response
23    /// bytes for direct relay to the EST client.
24    ///
25    /// This is a pure passthrough: kipuka's `/fullcmc` endpoint receives
26    /// a CMC request from the EST client and forwards it to Dogtag without
27    /// interpretation. The response is similarly relayed back.
28    ///
29    /// # Content Types
30    ///
31    /// - Request: `application/pkcs7-mime` (CMC request, DER)
32    /// - Response: `application/pkcs7-mime` (CMC response, DER)
33    pub async fn submit_cmc_request(&self, cmc_der: &[u8]) -> DogtagResult<Vec<u8>> {
34        debug!(
35            size = cmc_der.len(),
36            "Submitting Full CMC request to Dogtag"
37        );
38
39        let resp = self
40            .post_bytes(
41                "/ca/ee/ca/profileSubmitCMCFull",
42                cmc_der.to_vec(),
43                "application/pkcs7-mime",
44            )
45            .await?;
46
47        let status = resp.status();
48        if !status.is_success() {
49            let body = resp.text().await.unwrap_or_default();
50            return Err(DogtagError::ApiError {
51                status: status.as_u16(),
52                body,
53            });
54        }
55
56        resp.bytes()
57            .await
58            .map(|b| b.to_vec())
59            .map_err(|e| DogtagError::ParseError(format!("Failed to read CMC response: {e}")))
60    }
61}