use mime::APPLICATION_JSON;
use nameth::NamedEnumValues as _;
use nameth::nameth;
use openssl::pkey::HasPublic;
use openssl::pkey::PKeyRef;
use reqwest::StatusCode;
use trz_gateway_common::api::tunnel::GetCertificateRequest;
use trz_gateway_common::x509::PemAsStringError;
use trz_gateway_common::x509::PemString as _;
use super::AuthCode;
use super::config::ClientConfig;
use super::config::SniOverrideError;
use super::config::set_sni_override;
use super::config::url;
use crate::http_client::HttpClient;
use crate::http_client::HttpRequestError;
pub(crate) async fn get_certifiate(
client_config: &impl ClientConfig,
http_client: HttpClient,
auth_code: AuthCode,
key: &PKeyRef<impl HasPublic>,
) -> Result<String, GetCertificateError> {
let public_key = key.public_key_to_pem().pem_string()?;
let mut url = url(client_config, "/remote/certificate")?;
set_sni_override(&mut url, client_config.sni_override())?;
let body = serde_json::to_string(&GetCertificateRequest {
auth_code,
public_key,
name: client_config.client_name(),
})?;
let response = http_client
.get(url, APPLICATION_JSON.as_ref(), body)
.await?;
let status = response.status;
let body = response.body;
if !status.is_success() {
return Err(GetCertificateError::HttpStatus { status, body });
}
Ok(body)
}
#[nameth]
#[derive(thiserror::Error, Debug)]
pub enum GetCertificateError {
#[error("[{n}] {0}", n = self.name())]
SniOverride(#[from] SniOverrideError),
#[error("[{n}] {0}", n = self.name())]
PublicKeyToPem(#[from] PemAsStringError),
#[error("[{n}] {0}", n = self.name())]
RequestSerialization(#[from] serde_json::Error),
#[error("[{n}] {0}", n = self.name())]
HttpRequest(#[from] HttpRequestError),
#[error("[{n}] Gateway returned {status}: {body}", n = self.name())]
HttpStatus { status: StatusCode, body: String },
}