confium_deployment/identity/
actor.rs1use crate::identity::attributes::SignerAttributes;
4use crate::identity::token::HardwareToken;
5use chrono::{DateTime, Utc};
6use serde::{Deserialize, Serialize};
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
10#[serde(rename_all = "snake_case")]
11pub enum ActorType {
12 Manufacturer,
14 TestingLab,
16 IssuingAuthorityOfficer,
18 BimlDirector,
20 QuorumCoordinator,
22 Verifier,
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
28#[serde(tag = "kind", rename_all = "snake_case")]
29pub enum SigningKeyHandle {
30 Software {
32 key_id: String,
34 algorithm: String,
36 },
37 Hardware {
39 key_id: String,
41 algorithm: String,
43 token: HardwareToken,
45 },
46}
47
48#[derive(Debug, Clone, Serialize, Deserialize)]
50#[serde(tag = "kind", rename_all = "snake_case")]
51pub enum EncryptionKeyHandle {
52 Software {
54 key_id: String,
56 algorithm: String,
58 },
59 Hardware {
61 key_id: String,
63 algorithm: String,
65 token: HardwareToken,
67 },
68}
69
70#[derive(Debug, Clone, Serialize, Deserialize)]
72pub struct ActorIdentity {
73 pub actor_id: String,
75 pub actor_type: ActorType,
77 pub quorum_id: Option<String>,
79 pub signing_key: SigningKeyHandle,
81 pub encryption_key: Option<EncryptionKeyHandle>,
83 pub certificate_chain_der: Vec<Vec<u8>>,
85 pub hardware_token: Option<HardwareToken>,
87 pub attributes: SignerAttributes,
89 pub registered_at: DateTime<Utc>,
91 pub expires_at: Option<DateTime<Utc>>,
93}
94
95impl ActorIdentity {
96 pub fn builder() -> ActorIdentityBuilder {
98 ActorIdentityBuilder::default()
99 }
100}
101
102#[derive(Debug, Default, Clone)]
104pub struct ActorIdentityBuilder {
105 actor_id: Option<String>,
106 actor_type: Option<ActorType>,
107 quorum_id: Option<String>,
108 signing_key: Option<SigningKeyHandle>,
109 encryption_key: Option<EncryptionKeyHandle>,
110 certificate_chain_der: Vec<Vec<u8>>,
111 hardware_token: Option<HardwareToken>,
112 attributes: SignerAttributes,
113 expires_at: Option<DateTime<Utc>>,
114}
115
116impl ActorIdentityBuilder {
117 pub fn actor_id(mut self, id: impl Into<String>) -> Self {
119 self.actor_id = Some(id.into());
120 self
121 }
122 pub fn actor_type(mut self, t: ActorType) -> Self {
124 self.actor_type = Some(t);
125 self
126 }
127 pub fn quorum_id(mut self, id: impl Into<String>) -> Self {
129 self.quorum_id = Some(id.into());
130 self
131 }
132 pub fn signing_key(mut self, key: SigningKeyHandle) -> Self {
134 self.signing_key = Some(key);
135 self
136 }
137 pub fn encryption_key(mut self, key: EncryptionKeyHandle) -> Self {
139 self.encryption_key = Some(key);
140 self
141 }
142 pub fn certificate_chain(mut self, chain: Vec<Vec<u8>>) -> Self {
144 self.certificate_chain_der = chain;
145 self
146 }
147 pub fn hardware_token(mut self, token: HardwareToken) -> Self {
149 self.hardware_token = Some(token);
150 self
151 }
152 pub fn attributes(mut self, attrs: SignerAttributes) -> Self {
154 self.attributes = attrs;
155 self
156 }
157 pub fn expires_at(mut self, when: DateTime<Utc>) -> Self {
159 self.expires_at = Some(when);
160 self
161 }
162
163 pub fn build(self) -> Result<ActorIdentity, IdentityError> {
165 Ok(ActorIdentity {
166 actor_id: self
167 .actor_id
168 .ok_or(IdentityError::MissingField("actor_id"))?,
169 actor_type: self
170 .actor_type
171 .ok_or(IdentityError::MissingField("actor_type"))?,
172 quorum_id: self.quorum_id,
173 signing_key: self
174 .signing_key
175 .ok_or(IdentityError::MissingField("signing_key"))?,
176 encryption_key: self.encryption_key,
177 certificate_chain_der: self.certificate_chain_der,
178 hardware_token: self.hardware_token,
179 attributes: self.attributes,
180 registered_at: Utc::now(),
181 expires_at: self.expires_at,
182 })
183 }
184}
185
186#[derive(Debug, thiserror::Error)]
188pub enum IdentityError {
189 #[error("missing required field: {0}")]
191 MissingField(&'static str),
192 #[error("actor not found: {0}")]
194 NotFound(String),
195 #[error("actor already exists: {0}")]
197 AlreadyExists(String),
198 #[error("serialization error: {0}")]
200 Serde(#[from] serde_json::Error),
201}
202
203#[cfg(test)]
204mod tests {
205 use super::*;
206
207 #[test]
208 fn builder_produces_identity() {
209 let id = ActorIdentity::builder()
210 .actor_id("biml-director-1")
211 .actor_type(ActorType::BimlDirector)
212 .signing_key(SigningKeyHandle::Software {
213 key_id: "k1".into(),
214 algorithm: "Ed25519".into(),
215 })
216 .build()
217 .expect("build");
218 assert_eq!(id.actor_id, "biml-director-1");
219 assert_eq!(id.actor_type, ActorType::BimlDirector);
220 }
221
222 #[test]
223 fn builder_fails_without_required_fields() {
224 let result = ActorIdentity::builder().build();
225 assert!(result.is_err());
226 }
227}