authly_client/
connection.rs

1//! Code related to the connection to Authly.
2
3use std::{borrow::Cow, sync::Arc};
4
5use authly_common::{id::ServiceId, proto::service::authly_service_client::AuthlyServiceClient};
6use tonic::transport::Endpoint;
7
8use crate::{
9    builder::{ConnectionParamsBuilder, Inference},
10    error,
11    identity::Identity,
12    Error,
13};
14
15/// The parameters used to establish a connection to Authly.
16#[derive(Clone)]
17pub struct ConnectionParams {
18    pub(crate) inference: Inference,
19    pub(crate) url: Cow<'static, str>,
20    pub(crate) authly_local_ca: Vec<u8>,
21    pub(crate) identity: Identity,
22    pub(crate) entity_id: ServiceId,
23    pub(crate) jwt_decoding_key: jsonwebtoken::DecodingKey,
24}
25
26impl ConnectionParams {
27    /// Gets the current Authly root CA.
28    pub fn ca_pem(&self) -> &[u8] {
29        &self.authly_local_ca
30    }
31
32    /// Gets the entity to be used for a connection.
33    pub fn identity(&self) -> &Identity {
34        &self.identity
35    }
36}
37
38pub(crate) struct Connection {
39    pub authly_service: AuthlyServiceClient<tonic::transport::Channel>,
40    pub params: Arc<ConnectionParams>,
41}
42
43#[derive(Clone)]
44pub(crate) enum ReconfigureStrategy {
45    ReInfer { url: Cow<'static, str> },
46    Params(Arc<ConnectionParams>),
47}
48
49impl ReconfigureStrategy {
50    pub(crate) async fn new_connection_params(&self) -> Result<Arc<ConnectionParams>, Error> {
51        match self {
52            Self::ReInfer { url } => {
53                let mut params_builder = ConnectionParamsBuilder::new(url.clone());
54                params_builder.infer().await?;
55                Ok(params_builder.try_into_connection_params()?)
56            }
57            Self::Params(params) => Ok(params.clone()),
58        }
59    }
60}
61
62pub(crate) async fn make_connection(params: Arc<ConnectionParams>) -> Result<Connection, Error> {
63    let tls_config = tonic::transport::ClientTlsConfig::new()
64        .ca_certificate(tonic::transport::Certificate::from_pem(
65            &params.authly_local_ca,
66        ))
67        .identity(tonic::transport::Identity::from_pem(
68            params.identity.cert_pem.clone(),
69            params.identity.key_pem.clone(),
70        ));
71
72    let endpoint = match &params.url {
73        Cow::Borrowed(url) => Endpoint::from_static(url),
74        Cow::Owned(url) => Endpoint::from_shared(url.clone()).map_err(error::network)?,
75    }
76    .tls_config(tls_config)
77    .map_err(error::network)?;
78
79    let authly_service =
80        AuthlyServiceClient::new(endpoint.connect().await.map_err(error::unclassified)?);
81
82    Ok(Connection {
83        authly_service,
84        params,
85    })
86}