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    pub nonce: [u8; 16],
219    #[serde(default)]
220    pub ext: Option<Vec<u8>>,
221}
222
223//
224// DelegatedTokenPrepareResponse
225//
226
227#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
228pub struct DelegatedTokenPrepareResponse {
229    pub claims: DelegatedTokenClaims,
230    pub claims_hash: [u8; 32],
231    pub retrieval_expires_at_ns: u64,
232}
233
234//
235// DelegatedTokenGetRequest
236//
237
238#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
239pub struct DelegatedTokenGetRequest {
240    pub claims_hash: [u8; 32],
241}
242
243//
244// RoleAttestationRequest
245//
246
247#[derive(CandidType, Clone, Debug, Deserialize)]
248pub struct RoleAttestationRequest {
249    pub subject: Principal,
250    pub role: CanisterRole,
251    #[serde(default)]
252    pub subnet_id: Option<Principal>,
253    pub audience: Principal,
254    pub ttl_ns: u64,
255    pub epoch: u64,
256    #[serde(default)]
257    pub metadata: Option<RootRequestMetadata>,
258}
259
260//
261// RoleAttestation
262//
263
264#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
265pub struct RoleAttestation {
266    pub subject: Principal,
267    pub role: CanisterRole,
268    #[serde(default)]
269    pub subnet_id: Option<Principal>,
270    pub audience: Principal,
271    pub issued_at_ns: u64,
272    pub expires_at_ns: u64,
273    pub epoch: u64,
274}
275
276//
277// RoleAttestationPrepareResponse
278//
279
280#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
281pub struct RoleAttestationPrepareResponse {
282    pub payload: RoleAttestation,
283    pub payload_hash: [u8; 32],
284    pub retrieval_expires_at_ns: u64,
285}
286
287//
288// RoleAttestationGetRequest
289//
290
291#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
292pub struct RoleAttestationGetRequest {
293    pub payload_hash: [u8; 32],
294}
295
296//
297// SignedRoleAttestation
298//
299
300#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
301pub struct SignedRoleAttestation {
302    pub payload: RoleAttestation,
303    pub root_proof: RootProof,
304}
305
306#[cfg(test)]
307mod tests {
308    #[test]
309    fn auth_dtos_remain_passive_boundary_types() {
310        let source = include_str!("auth.rs");
311        let production_source = source
312            .split("#[cfg(test)]")
313            .next()
314            .expect("production source exists");
315
316        for marker in [
317            "impl DelegatedToken",
318            "impl DelegatedTokenClaims",
319            "impl RoleAttestation",
320            "impl SignedRoleAttestation",
321            "fn verify",
322            "fn sign",
323            "fn resolve",
324            "fn replay",
325            "fn consume",
326            "fn policy",
327            "fn validate",
328        ] {
329            assert!(
330                !production_source.contains(marker),
331                "auth DTOs must stay passive; found marker `{marker}`"
332            );
333        }
334    }
335}