• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

maxlambrecht / rust-spiffe / 20683117309

03 Jan 2026 09:23PM UTC coverage: 80.131% (-6.1%) from 86.238%
20683117309

push

github

web-flow
refactor(spiffe): feature-gate X.509/JWT, restructure modules, and polish APIs (#223)

Signed-off-by: Max Lambrecht <maxlambrecht@gmail.com>

548 of 654 new or added lines in 12 files covered. (83.79%)

309 existing lines in 9 files now uncovered.

3424 of 4273 relevant lines covered (80.13%)

473.7 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/spiffe/src/workload_api/error.rs
1
//! Error types for Workload API operations.
2

3
use thiserror::Error;
4

5
use crate::transport::EndpointError;
6
use crate::SpiffeIdError;
7
#[cfg(feature = "jwt")]
8
use crate::{JwtBundleError, JwtSvidError};
9
#[cfg(feature = "x509")]
10
use crate::{X509BundleError, X509SvidError};
11

12
#[cfg(any(
13
    feature = "workload-api",
14
    feature = "workload-api-x509",
15
    feature = "workload-api-jwt",
16
    feature = "workload-api-full"
17
))]
18
use crate::transport::TransportError;
19

20
/// Errors produced by Workload API operations.
21
#[derive(Debug, Error)]
22
#[non_exhaustive]
23
pub enum WorkloadApiError {
24
    /// `SPIFFE_ENDPOINT_SOCKET` is not set.
25
    #[error("missing SPIFFE endpoint socket path (SPIFFE_ENDPOINT_SOCKET)")]
26
    MissingEndpointSocket,
27

28
    /// The Workload API returned an empty response.
29
    ///
30
    /// This error can occur when:
31
    /// - The gRPC stream ends unexpectedly
32
    /// - No SVIDs are available for the requested identity
33
    /// - The Workload API is misconfigured or the workload is not registered
34
    ///
35
    /// **Common causes:**
36
    /// - Workload selectors don't match
37
    /// - SPIRE agent is not running
38
    /// - Network connectivity issues
39
    #[error("empty Workload API response")]
40
    EmptyResponse,
41

42
    /// Failed to parse the Workload API endpoint string.
43
    #[error("invalid workload api endpoint: {0}")]
44
    Endpoint(#[from] EndpointError),
45

46
    /// The Workload API denied issuing an identity for this workload (e.g. selectors do not match).
47
    ///
48
    /// This error occurs when the SPIRE agent cannot match the workload to any
49
    /// registration entry based on the workload's selectors.
50
    #[error("no identity issued")]
51
    NoIdentityIssued,
52

53
    /// The Workload API denied the request for other permission reasons.
54
    #[error("permission denied: {0}")]
55
    PermissionDenied(String),
56

57
    /// No JWT-SVID found with the requested hint.
58
    #[error("no JWT-SVID found with hint: {0}")]
59
    HintNotFound(String),
60

61
    /// Errors returned by the underlying transport.
62
    #[cfg(any(
63
        feature = "workload-api",
64
        feature = "workload-api-x509",
65
        feature = "workload-api-jwt",
66
        feature = "workload-api-full"
67
    ))]
68
    #[error(transparent)]
69
    Transport(#[from] TransportError),
70

71
    /// Failed to parse an X.509 SVID from the Workload API response.
72
    #[cfg(feature = "x509")]
73
    #[error("failed to parse X.509 SVID: {0}")]
74
    X509Svid(#[from] X509SvidError),
75

76
    /// Failed to parse a JWT-SVID from the Workload API response.
77
    #[cfg(feature = "jwt")]
78
    #[error("failed to parse JWT-SVID: {0}")]
79
    JwtSvid(#[from] JwtSvidError),
UNCOV
80

×
81
    /// Failed to parse an X.509 bundle from the Workload API response.
82
    #[cfg(feature = "x509")]
UNCOV
83
    #[error("failed to parse X.509 bundle: {0}")]
×
UNCOV
84
    X509Bundle(#[from] X509BundleError),
×
85

UNCOV
86
    /// Failed to parse a JWT bundle from the Workload API response.
×
NEW
87
    #[cfg(feature = "jwt")]
×
UNCOV
88
    #[error("failed to parse JWT bundle: {0}")]
×
89
    JwtBundle(#[from] JwtBundleError),
UNCOV
90

×
UNCOV
91
    /// Failed to parse a SPIFFE identifier from the Workload API response.
×
92
    #[error("failed to parse SPIFFE ID: {0}")]
UNCOV
93
    SpiffeId(#[from] SpiffeIdError),
×
UNCOV
94
}
×
95

96
#[cfg(any(
97
    feature = "workload-api",
98
    feature = "workload-api-x509",
NEW
99
    feature = "workload-api-jwt",
×
NEW
100
    feature = "workload-api-full"
×
NEW
101
))]
×
102
impl From<tonic::Status> for WorkloadApiError {
103
    fn from(status: tonic::Status) -> Self {
×
104
        use tonic::Code;
105

106
        if status.code() == Code::PermissionDenied {
×
107
            let msg = status.message();
×
108

109
            if msg.contains("no identity issued") {
×
110
                return Self::NoIdentityIssued;
×
111
            }
×
112

113
            return Self::PermissionDenied(msg.to_owned());
×
114
        }
×
115

116
        Self::Transport(TransportError::Status(status))
×
117
    }
×
118
}
119

120
#[cfg(any(
121
    feature = "workload-api",
122
    feature = "workload-api-x509",
123
    feature = "workload-api-jwt",
124
    feature = "workload-api-full"
125
))]
126
impl From<tonic::transport::Error> for WorkloadApiError {
127
    fn from(e: tonic::transport::Error) -> Self {
×
128
        Self::Transport(TransportError::Tonic(e))
×
129
    }
×
130
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc