use thiserror::Error;
use crate::transport::EndpointError;
use crate::SpiffeIdError;
#[cfg(feature = "jwt")]
use crate::{JwtBundleError, JwtSvidError};
#[cfg(feature = "x509")]
use crate::{X509BundleError, X509SvidError};
#[cfg(any(
feature = "workload-api",
feature = "workload-api-x509",
feature = "workload-api-jwt",
feature = "workload-api-full"
))]
use crate::transport::TransportError;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum WorkloadApiError {
#[error("missing SPIFFE endpoint socket path (SPIFFE_ENDPOINT_SOCKET)")]
MissingEndpointSocket,
#[error("SPIFFE endpoint socket path is not a valid UTF-8 string: {}", .0.display())]
NotUnicodeEndpointSocket(std::ffi::OsString),
#[error("empty Workload API response")]
EmptyResponse,
#[error("invalid workload api endpoint: {0}")]
Endpoint(#[from] EndpointError),
#[error("no identity issued")]
NoIdentityIssued,
#[error("permission denied: {0}")]
PermissionDenied(String),
#[error("no JWT-SVID found with hint: {0}")]
HintNotFound(String),
#[cfg(any(
feature = "workload-api",
feature = "workload-api-x509",
feature = "workload-api-jwt",
feature = "workload-api-full"
))]
#[error(transparent)]
Transport(#[from] TransportError),
#[cfg(feature = "x509")]
#[error("failed to parse X.509 SVID: {0}")]
X509Svid(#[from] X509SvidError),
#[cfg(feature = "jwt")]
#[error("failed to parse JWT-SVID: {0}")]
JwtSvid(#[from] JwtSvidError),
#[cfg(feature = "x509")]
#[error("failed to parse X.509 bundle: {0}")]
X509Bundle(#[from] X509BundleError),
#[cfg(feature = "jwt")]
#[error("failed to parse JWT bundle: {0}")]
JwtBundle(#[from] JwtBundleError),
#[error("failed to parse SPIFFE ID: {0}")]
SpiffeId(#[from] SpiffeIdError),
}
#[cfg(any(
feature = "workload-api",
feature = "workload-api-x509",
feature = "workload-api-jwt",
feature = "workload-api-full"
))]
impl From<tonic::Status> for WorkloadApiError {
fn from(status: tonic::Status) -> Self {
use tonic::Code;
if status.code() == Code::PermissionDenied {
let msg = status.message();
if msg.contains("no identity issued") {
return Self::NoIdentityIssued;
}
return Self::PermissionDenied(msg.to_owned());
}
Self::Transport(TransportError::Status(status))
}
}
#[cfg(any(
feature = "workload-api",
feature = "workload-api-x509",
feature = "workload-api-jwt",
feature = "workload-api-full"
))]
impl From<tonic::transport::Error> for WorkloadApiError {
fn from(e: tonic::transport::Error) -> Self {
Self::Transport(TransportError::Tonic(e))
}
}