Skip to main content

canic_core/dto/
auth.rs

1use crate::dto::{prelude::*, rpc::RootRequestMetadata};
2
3//
4// DelegationAudience
5//
6
7#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
8pub enum DelegationAudience {
9    Canister(Principal),
10    CanicSubnet(Principal),
11    Project(String),
12}
13
14//
15// DelegatedRoleGrant
16//
17
18#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
19pub struct DelegatedRoleGrant {
20    pub target: CanisterRole,
21    pub scopes: Vec<String>,
22}
23
24//
25// RootProof
26//
27
28#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
29pub enum RootProof {
30    IcCanisterSignatureV1(IcCanisterSignatureProofV1),
31}
32
33//
34// IssuerProof
35//
36
37#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
38pub enum IssuerProof {
39    IcCanisterSignatureV1(IcCanisterSignatureProofV1),
40}
41
42//
43// IcCanisterSignatureProofV1
44//
45
46#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
47pub struct IcCanisterSignatureProofV1 {
48    pub signature_cbor: Vec<u8>,
49    pub public_key_der: Vec<u8>,
50}
51
52//
53// IssuerProofAlgorithm
54//
55
56#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
57pub enum IssuerProofAlgorithm {
58    IcCanisterSignatureV1,
59}
60
61//
62// IssuerProofBinding
63//
64
65#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
66pub enum IssuerProofBinding {
67    IcCanisterSignatureV1 { seed_hash: [u8; 32] },
68}
69
70//
71// DelegationCert
72//
73
74#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
75pub struct DelegationCert {
76    pub root_pid: Principal,
77    pub issuer_pid: Principal,
78    pub issuer_proof_alg: IssuerProofAlgorithm,
79    pub issuer_proof_binding_hash: [u8; 32],
80    pub issuer_proof_binding: IssuerProofBinding,
81    pub issuer_signer_generation: Option<u64>,
82    pub issued_at_ns: u64,
83    pub not_before_ns: u64,
84    pub expires_at_ns: u64,
85    pub max_token_ttl_ns: u64,
86    pub aud: DelegationAudience,
87    pub grants: Vec<DelegatedRoleGrant>,
88}
89
90//
91// DelegationProof
92//
93
94#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
95pub struct DelegationProof {
96    pub cert: DelegationCert,
97    pub root_proof: RootProof,
98}
99
100//
101// ActiveDelegationProof
102//
103
104#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
105pub struct ActiveDelegationProof {
106    pub proof: DelegationProof,
107    pub cert_hash: [u8; 32],
108    pub not_before_ns: u64,
109    pub expires_at_ns: u64,
110    pub refresh_after_ns: u64,
111    pub installed_at_ns: u64,
112    pub installed_by: Principal,
113}
114
115//
116// InstallActiveDelegationProofRequest
117//
118
119#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
120pub struct InstallActiveDelegationProofRequest {
121    pub proof: DelegationProof,
122}
123
124//
125// InstallActiveDelegationProofResponse
126//
127
128#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
129pub struct InstallActiveDelegationProofResponse {
130    pub active_proof: ActiveDelegationProof,
131}
132
133//
134// DelegatedTokenClaims
135//
136
137#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
138pub struct DelegatedTokenClaims {
139    pub subject: Principal,
140    pub issuer_pid: Principal,
141    pub cert_hash: [u8; 32],
142    pub issued_at_ns: u64,
143    pub expires_at_ns: u64,
144    pub aud: DelegationAudience,
145    pub grants: Vec<DelegatedRoleGrant>,
146    pub nonce: [u8; 16],
147    #[serde(default)]
148    pub ext: Option<Vec<u8>>,
149}
150
151//
152// DelegatedToken
153//
154
155#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
156pub struct DelegatedToken {
157    pub claims: DelegatedTokenClaims,
158    pub proof: DelegationProof,
159    pub issuer_proof: IssuerProof,
160}
161
162//
163// AuthRequestMetadata
164//
165
166#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
167pub struct AuthRequestMetadata {
168    pub request_id: [u8; 32],
169    pub ttl_ns: u64,
170}
171
172//
173// DelegationProofIssueRequest
174//
175
176#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
177pub struct DelegationProofIssueRequest {
178    #[serde(default)]
179    pub metadata: Option<AuthRequestMetadata>,
180    pub issuer_pid: Principal,
181    pub aud: DelegationAudience,
182    pub grants: Vec<DelegatedRoleGrant>,
183    pub cert_ttl_ns: u64,
184}
185
186//
187// DelegationProofPrepareResponse
188//
189
190#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
191pub struct DelegationProofPrepareResponse {
192    pub cert: DelegationCert,
193    pub cert_hash: [u8; 32],
194    pub retrieval_expires_at_ns: u64,
195}
196
197//
198// DelegationProofGetRequest
199//
200
201#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
202pub struct DelegationProofGetRequest {
203    pub cert_hash: [u8; 32],
204}
205
206//
207// DelegatedTokenPrepareRequest
208//
209
210#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
211pub struct DelegatedTokenPrepareRequest {
212    #[serde(default)]
213    pub metadata: Option<AuthRequestMetadata>,
214    pub subject: Principal,
215    pub aud: DelegationAudience,
216    pub grants: Vec<DelegatedRoleGrant>,
217    pub ttl_ns: u64,
218    #[serde(default)]
219    pub ext: Option<Vec<u8>>,
220}
221
222//
223// DelegatedTokenPrepareResponse
224//
225
226#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
227pub struct DelegatedTokenPrepareResponse {
228    pub claims: DelegatedTokenClaims,
229    pub claims_hash: [u8; 32],
230    pub retrieval_expires_at_ns: u64,
231}
232
233//
234// DelegatedTokenGetRequest
235//
236
237#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
238pub struct DelegatedTokenGetRequest {
239    pub claims_hash: [u8; 32],
240}
241
242//
243// RoleAttestationRequest
244//
245
246#[derive(CandidType, Clone, Debug, Deserialize)]
247pub struct RoleAttestationRequest {
248    pub subject: Principal,
249    pub role: CanisterRole,
250    #[serde(default)]
251    pub subnet_id: Option<Principal>,
252    pub audience: Principal,
253    pub ttl_ns: u64,
254    pub epoch: u64,
255    #[serde(default)]
256    pub metadata: Option<RootRequestMetadata>,
257}
258
259//
260// RoleAttestation
261//
262
263#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
264pub struct RoleAttestation {
265    pub subject: Principal,
266    pub role: CanisterRole,
267    #[serde(default)]
268    pub subnet_id: Option<Principal>,
269    pub audience: Principal,
270    pub issued_at_ns: u64,
271    pub expires_at_ns: u64,
272    pub epoch: u64,
273}
274
275//
276// RoleAttestationPrepareResponse
277//
278
279#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
280pub struct RoleAttestationPrepareResponse {
281    pub payload: RoleAttestation,
282    pub payload_hash: [u8; 32],
283    pub retrieval_expires_at_ns: u64,
284}
285
286//
287// RoleAttestationGetRequest
288//
289
290#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
291pub struct RoleAttestationGetRequest {
292    pub payload_hash: [u8; 32],
293}
294
295//
296// SignedRoleAttestation
297//
298
299#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
300pub struct SignedRoleAttestation {
301    pub payload: RoleAttestation,
302    pub root_proof: RootProof,
303}
304
305#[cfg(test)]
306mod tests {
307    #[test]
308    fn auth_dtos_remain_passive_boundary_types() {
309        let source = include_str!("auth.rs");
310        let production_source = source
311            .split("#[cfg(test)]")
312            .next()
313            .expect("production source exists");
314
315        for marker in [
316            "impl DelegatedToken",
317            "impl DelegatedTokenClaims",
318            "impl RoleAttestation",
319            "impl SignedRoleAttestation",
320            "fn verify",
321            "fn sign",
322            "fn resolve",
323            "fn replay",
324            "fn consume",
325            "fn policy",
326            "fn validate",
327        ] {
328            assert!(
329                !production_source.contains(marker),
330                "auth DTOs must stay passive; found marker `{marker}`"
331            );
332        }
333    }
334}