1use crate::dto::{prelude::*, rpc::RootRequestMetadata};
2
3#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
8pub enum DelegationAudience {
9 Canic,
10 Project(String),
11}
12
13#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
18pub struct DelegatedRoleGrant {
19 pub target: CanisterRole,
20 pub scopes: Vec<String>,
21}
22
23#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
28pub enum ShardKeyBinding {
29 IcThresholdEcdsaSecp256k1 {
30 key_name_hash: [u8; 32],
31 derivation_path_hash: [u8; 32],
32 },
33}
34
35#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
40pub enum ShardSignatureAlgorithm {
41 IcThresholdEcdsaSecp256k1,
42}
43
44#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
49pub enum RootProof {
50 IcCanisterSignatureV1(IcCanisterSignatureProofV1),
51}
52
53#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
58pub struct IcCanisterSignatureProofV1 {
59 pub signature_cbor: Vec<u8>,
60 pub public_key_der: Vec<u8>,
61}
62
63#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
68pub struct DelegationCert {
69 pub root_pid: Principal,
70 pub shard_pid: Principal,
71 pub shard_key_id: String,
72 pub shard_sig_alg: ShardSignatureAlgorithm,
73 pub shard_public_key_sec1: Vec<u8>,
74 pub shard_key_hash: [u8; 32],
75 pub shard_key_binding: ShardKeyBinding,
76 pub issued_at_ns: u64,
77 pub not_before_ns: u64,
78 pub expires_at_ns: u64,
79 pub max_token_ttl_ns: u64,
80 pub aud: DelegationAudience,
81 pub grants: Vec<DelegatedRoleGrant>,
82}
83
84#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
89pub struct DelegationProof {
90 pub cert: DelegationCert,
91 pub root_proof: RootProof,
92}
93
94#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
99pub struct DelegatedTokenClaims {
100 pub subject: Principal,
101 pub issuer_shard_pid: Principal,
102 pub cert_hash: [u8; 32],
103 pub issued_at_ns: u64,
104 pub expires_at_ns: u64,
105 pub aud: DelegationAudience,
106 pub grants: Vec<DelegatedRoleGrant>,
107 pub nonce: [u8; 16],
108}
109
110#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
115pub struct DelegatedToken {
116 pub claims: DelegatedTokenClaims,
117 pub proof: DelegationProof,
118 pub shard_sig: Vec<u8>,
119}
120
121#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)]
126pub struct AuthRequestMetadata {
127 pub request_id: [u8; 32],
128 pub ttl_ns: u64,
129}
130
131#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
136pub struct DelegationProofIssueRequest {
137 #[serde(default)]
138 pub metadata: Option<AuthRequestMetadata>,
139 pub shard_pid: Principal,
140 pub aud: DelegationAudience,
141 pub grants: Vec<DelegatedRoleGrant>,
142 pub cert_ttl_ns: u64,
143}
144
145#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
150pub struct DelegationProofPrepareResponse {
151 pub cert: DelegationCert,
152 pub cert_hash: [u8; 32],
153 pub retrieval_expires_at_ns: u64,
154}
155
156#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
161pub struct DelegationProofGetRequest {
162 pub cert_hash: [u8; 32],
163}
164
165#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
170pub struct DelegatedTokenIssueRequest {
171 #[serde(default)]
172 pub metadata: Option<AuthRequestMetadata>,
173 pub proof: DelegationProof,
174 pub subject: Principal,
175 pub aud: DelegationAudience,
176 pub grants: Vec<DelegatedRoleGrant>,
177 pub ttl_ns: u64,
178 pub nonce: [u8; 16],
179}
180
181#[derive(CandidType, Clone, Debug, Deserialize)]
186pub struct RoleAttestationRequest {
187 pub subject: Principal,
188 pub role: CanisterRole,
189 #[serde(default)]
190 pub subnet_id: Option<Principal>,
191 pub audience: Principal,
192 pub ttl_ns: u64,
193 pub epoch: u64,
194 #[serde(default)]
195 pub metadata: Option<RootRequestMetadata>,
196}
197
198#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
203pub struct RoleAttestation {
204 pub subject: Principal,
205 pub role: CanisterRole,
206 #[serde(default)]
207 pub subnet_id: Option<Principal>,
208 pub audience: Principal,
209 pub issued_at_ns: u64,
210 pub expires_at_ns: u64,
211 pub epoch: u64,
212}
213
214#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
219pub struct SignedRoleAttestation {
220 pub payload: RoleAttestation,
221 pub signature: Vec<u8>,
222 pub key_id: u32,
223}
224
225#[derive(CandidType, Clone, Debug, Deserialize)]
230pub struct InternalInvocationProofRequest {
231 pub subject: Principal,
232 pub role: CanisterRole,
233 #[serde(default)]
234 pub subnet_id: Option<Principal>,
235 pub audience: Principal,
236 pub audience_method: String,
237 pub ttl_ns: u64,
238 #[serde(default)]
239 pub metadata: Option<RootRequestMetadata>,
240}
241
242#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
247pub struct InternalInvocationProofPayloadV1 {
248 pub subject: Principal,
249 pub role: CanisterRole,
250 #[serde(default)]
251 pub subnet_id: Option<Principal>,
252 pub audience: Principal,
253 pub audience_method: String,
254 pub issued_at_ns: u64,
255 pub expires_at_ns: u64,
256 pub epoch: u64,
257}
258
259#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
264pub struct SignedInternalInvocationProofV1 {
265 pub payload: InternalInvocationProofPayloadV1,
266 pub signature: Vec<u8>,
267 pub key_id: u32,
268}
269
270#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
275pub struct CanicInternalCallHeaderV1 {
276 pub target_canister: Principal,
277 pub target_method: String,
278}
279
280#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
285pub struct CanicInternalCallEnvelopeV1 {
286 pub version: u16,
287 pub header: CanicInternalCallHeaderV1,
288 pub proof: SignedInternalInvocationProofV1,
289 pub args: Vec<u8>,
290}
291
292#[derive(CandidType, Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
297pub enum AttestationKeyStatus {
298 Current,
299 Previous,
300}
301
302#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
307pub struct AttestationKey {
308 pub key_id: u32,
309 pub public_key: Vec<u8>,
310 pub key_name: String,
311 pub key_hash: [u8; 32],
312 pub status: AttestationKeyStatus,
313 #[serde(default)]
314 pub valid_from: Option<u64>,
315 #[serde(default)]
316 pub valid_until: Option<u64>,
317}
318
319#[derive(CandidType, Clone, Debug, Deserialize, Eq, PartialEq)]
324pub struct AttestationKeySet {
325 pub root_pid: Principal,
326 pub generated_at: u64,
327 pub keys: Vec<AttestationKey>,
328}
329
330#[cfg(test)]
331mod tests {
332 #[test]
333 fn auth_dtos_remain_passive_boundary_types() {
334 let source = include_str!("auth.rs");
335 let production_source = source
336 .split("#[cfg(test)]")
337 .next()
338 .expect("production source exists");
339
340 for marker in [
341 "impl DelegatedToken",
342 "impl DelegatedTokenClaims",
343 "impl RoleAttestation",
344 "impl SignedRoleAttestation",
345 "impl InternalInvocationProofPayloadV1",
346 "impl SignedInternalInvocationProofV1",
347 "impl CanicInternalCallEnvelopeV1",
348 "fn verify",
349 "fn sign",
350 "fn resolve",
351 "fn replay",
352 "fn consume",
353 "fn policy",
354 "fn validate",
355 ] {
356 assert!(
357 !production_source.contains(marker),
358 "auth DTOs must stay passive; found marker `{marker}`"
359 );
360 }
361 }
362}