Skip to content

Commit 8e1eb8f

Browse files
authored
feat(rust/signed-doc): New CatalystId admin functionality for SignatureKid validation rule (#607)
* update `SignatureKidRule` rule * wip * bump version * fix
1 parent 1779383 commit 8e1eb8f

25 files changed

+168
-156
lines changed

rust/signed_doc/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "catalyst-signed-doc"
3-
version = "0.0.9"
3+
version = "0.0.10"
44
edition.workspace = true
55
authors.workspace = true
66
homepage.workspace = true
@@ -11,7 +11,7 @@ license.workspace = true
1111
workspace = true
1212

1313
[dependencies]
14-
catalyst-types = { version = "0.0.9", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "catalyst-types/v0.0.9" }
14+
catalyst-types = { version = "0.0.10", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "catalyst-types/v0.0.10" }
1515
cbork-utils = { version = "0.0.2", git = "https://github.com/input-output-hk/catalyst-libs.git", tag = "cbork-utils-v0.0.2" }
1616

1717
catalyst-signed-doc-macro = { version = "0.0.1", path = "../catalyst-signed-doc-macro" }

rust/signed_doc/src/validator/rules/signature_kid.rs

Lines changed: 38 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,28 @@
22
33
use std::collections::HashSet;
44

5-
use catalyst_signed_doc_spec::signers::roles::{AdminRole, Roles, UserRole};
5+
use catalyst_signed_doc_spec::signers::roles::{Roles, UserRole};
66
use catalyst_types::catalyst_id::role_index::RoleId;
77

88
use crate::CatalystSignedDocument;
99

1010
/// COSE signature `kid` (Catalyst Id) role validation
1111
#[derive(Debug)]
1212
pub(crate) struct SignatureKidRule {
13-
/// expected `RoleId` values for the `kid` field
13+
/// expected `RoleId` values for the `kid` field.
14+
/// if empty, document must be signed by admin kid
1415
allowed_roles: HashSet<RoleId>,
1516
}
1617

1718
impl SignatureKidRule {
1819
/// Generating `SignatureKidRule` from specs
1920
pub(crate) fn new(spec: &Roles) -> anyhow::Result<Self> {
21+
anyhow::ensure!(
22+
spec.user.is_empty() != spec.admin.is_empty(),
23+
"If 'admin' is not empty 'user' roles cannot been specified'.
24+
And vice versa, if 'user' is not empty 'admin' roles cannot been specified'"
25+
);
26+
2027
let allowed_roles: HashSet<_> = spec
2128
.user
2229
.iter()
@@ -27,26 +34,8 @@ impl SignatureKidRule {
2734
UserRole::Representative => RoleId::DelegatedRepresentative,
2835
}
2936
})
30-
.chain(spec.admin.iter().map(|v| {
31-
match v {
32-
AdminRole::RootCA => RoleId::RootCA,
33-
AdminRole::BrandCA => RoleId::BrandCA,
34-
AdminRole::CampaignCA => RoleId::CampaignCA,
35-
AdminRole::CategoryCA => RoleId::CategoryCA,
36-
AdminRole::RootAdmin => RoleId::RootAdmin,
37-
AdminRole::BrandAdmin => RoleId::BrandAdmin,
38-
AdminRole::CampaignAdmin => RoleId::CampaignAdmin,
39-
AdminRole::CategoryAdmin => RoleId::CategoryAdmin,
40-
AdminRole::Moderator => RoleId::Moderator,
41-
}
42-
}))
4337
.collect();
4438

45-
anyhow::ensure!(
46-
!allowed_roles.is_empty(),
47-
"A list of allowed roles cannot be empty"
48-
);
49-
5039
Ok(Self { allowed_roles })
5140
}
5241

@@ -57,20 +46,36 @@ impl SignatureKidRule {
5746
doc: &CatalystSignedDocument,
5847
) -> anyhow::Result<bool> {
5948
let contains_exp_role = doc.authors().iter().enumerate().all(|(i, kid)| {
60-
let (role_index, _) = kid.role_and_rotation();
61-
let res = self.allowed_roles.contains(&role_index);
62-
if !res {
63-
doc.report().invalid_value(
64-
"kid",
65-
role_index.to_string().as_str(),
66-
format!("{:?}", self.allowed_roles).as_str(),
67-
format!(
68-
"Invalid Catalyst Signed Document signature at position [{i}] `kid` Catalyst Role value"
69-
)
70-
.as_str(),
71-
);
49+
if self.allowed_roles.is_empty() {
50+
let res = kid.is_admin();
51+
if !res {
52+
doc.report().invalid_value(
53+
"kid",
54+
&kid.to_string(),
55+
"Catalyst id must be in admin URI type.",
56+
format!(
57+
"Invalid Catalyst Signed Document signature at position [{i}] `kid` Catalyst Role value"
58+
)
59+
.as_str(),
60+
);
61+
}
62+
res
63+
} else {
64+
let (role_index, _) = kid.role_and_rotation();
65+
let res = self.allowed_roles.contains(&role_index);
66+
if !res {
67+
doc.report().invalid_value(
68+
"kid",
69+
role_index.to_string().as_str(),
70+
format!("{:?}", self.allowed_roles).as_str(),
71+
format!(
72+
"Invalid Catalyst Signed Document signature at position [{i}] `kid` Catalyst Role value"
73+
)
74+
.as_str(),
75+
);
76+
}
77+
res
7278
}
73-
res
7479
});
7580
if !contains_exp_role {
7681
return Ok(false);

rust/signed_doc/tests/brand_parameters.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@ mod common;
2525
|provider| {
2626
let template = brand_parameters_form_template_doc(provider).inspect(|v| provider.add_document(None, v).unwrap())?;
2727
let id = UuidV7::new();
28-
let (sk, kid) = create_dummy_key_pair(RoleId::Role0)
29-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
28+
let (sk, kid) = create_dummy_key_pair(Some(RoleId::Role0));
29+
provider.add_sk(kid.clone(), sk.clone());
3030
Builder::new()
3131
.with_json_metadata(serde_json::json!({
3232
"content-type": ContentType::Json,
@@ -51,8 +51,8 @@ mod common;
5151
|provider| {
5252
let template = brand_parameters_form_template_doc(provider).inspect(|v| provider.add_document(None, v).unwrap())?;
5353
let id = UuidV7::new();
54-
let (sk, kid) = create_dummy_key_pair(RoleId::BrandAdmin)
55-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
54+
let (sk, kid) = create_dummy_key_pair(None);
55+
provider.add_sk(kid.clone(), sk.clone());
5656
Builder::new()
5757
.with_json_metadata(serde_json::json!({
5858
"content-type": ContentType::Json,
@@ -77,8 +77,8 @@ mod common;
7777
|provider| {
7878
let template = brand_parameters_form_template_doc(provider).inspect(|v| provider.add_document(None, v).unwrap())?;
7979
let id = UuidV7::new();
80-
let (sk, kid) = create_dummy_key_pair(RoleId::BrandAdmin)
81-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
80+
let (sk, kid) = create_dummy_key_pair(None);
81+
provider.add_sk(kid.clone(), sk.clone());
8282
Builder::new()
8383
.with_json_metadata(serde_json::json!({
8484
"content-type": ContentType::Json,
@@ -102,8 +102,8 @@ mod common;
102102
#[test_case(
103103
|provider| {
104104
let id = UuidV7::new();
105-
let (sk, kid) = create_dummy_key_pair(RoleId::BrandAdmin)
106-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
105+
let (sk, kid) = create_dummy_key_pair(None);
106+
provider.add_sk(kid.clone(), sk.clone());
107107
Builder::new()
108108
.with_json_metadata(serde_json::json!({
109109
"content-type": ContentType::Json,

rust/signed_doc/tests/brand_parameters_form_template.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ mod common;
2121
#[test_case(
2222
|provider| {
2323
let id = UuidV7::new();
24-
let (sk, kid) = create_dummy_key_pair(RoleId::Role0)
25-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
24+
let (sk, kid) = create_dummy_key_pair(Some(RoleId::Role0));
25+
provider.add_sk(kid.clone(), sk.clone());
2626
Builder::new()
2727
.with_json_metadata(serde_json::json!({
2828
"content-type": ContentType::SchemaJson,
@@ -42,8 +42,8 @@ mod common;
4242
#[test_case(
4343
|provider| {
4444
let id = UuidV7::new();
45-
let (sk, kid) = create_dummy_key_pair(RoleId::BrandAdmin)
46-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
45+
let (sk, kid) = create_dummy_key_pair(None);
46+
provider.add_sk(kid.clone(), sk.clone());
4747
Builder::new()
4848
.with_json_metadata(serde_json::json!({
4949
"content-type": ContentType::SchemaJson,
@@ -63,8 +63,8 @@ mod common;
6363
#[test_case(
6464
|provider| {
6565
let id = UuidV7::new();
66-
let (sk, kid) = create_dummy_key_pair(RoleId::BrandAdmin)
67-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
66+
let (sk, kid) = create_dummy_key_pair(None);
67+
provider.add_sk(kid.clone(), sk.clone());
6868
Builder::new()
6969
.with_json_metadata(serde_json::json!({
7070
"content-type": ContentType::SchemaJson,

rust/signed_doc/tests/campaign_parameters.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ mod common;
3030
let parameters = brand_parameters_doc(&template, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
3131
let template = campaign_parameters_form_template_doc(&parameters, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
3232
let id = UuidV7::new();
33-
let (sk, kid) = create_dummy_key_pair(RoleId::Role0)
34-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
33+
let (sk, kid) = create_dummy_key_pair(Some(RoleId::Role0));
34+
provider.add_sk(kid.clone(), sk.clone());
3535
Builder::new()
3636
.with_json_metadata(serde_json::json!({
3737
"content-type": ContentType::Json,
@@ -62,8 +62,8 @@ mod common;
6262
let parameters = brand_parameters_doc(&template, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
6363
let template = campaign_parameters_form_template_doc(&parameters, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
6464
let id = UuidV7::new();
65-
let (sk, kid) = create_dummy_key_pair(RoleId::BrandAdmin)
66-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
65+
let (sk, kid) = create_dummy_key_pair(None);
66+
provider.add_sk(kid.clone(), sk.clone());
6767
Builder::new()
6868
.with_json_metadata(serde_json::json!({
6969
"content-type": ContentType::Json,
@@ -94,8 +94,8 @@ mod common;
9494
let parameters = brand_parameters_doc(&template, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
9595
let template = campaign_parameters_form_template_doc(&parameters, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
9696
let id = UuidV7::new();
97-
let (sk, kid) = create_dummy_key_pair(RoleId::BrandAdmin)
98-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
97+
let (sk, kid) = create_dummy_key_pair(None);
98+
provider.add_sk(kid.clone(), sk.clone());
9999
Builder::new()
100100
.with_json_metadata(serde_json::json!({
101101
"content-type": ContentType::Json,
@@ -124,8 +124,8 @@ mod common;
124124
let template = brand_parameters_form_template_doc(provider).inspect(|v| provider.add_document(None, v).unwrap())?;
125125
let parameters = brand_parameters_doc(&template, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
126126
let id = UuidV7::new();
127-
let (sk, kid) = create_dummy_key_pair(RoleId::BrandAdmin)
128-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
127+
let (sk, kid) = create_dummy_key_pair(None);
128+
provider.add_sk(kid.clone(), sk.clone());
129129
Builder::new()
130130
.with_json_metadata(serde_json::json!({
131131
"content-type": ContentType::Json,
@@ -152,8 +152,8 @@ mod common;
152152
let parameters = brand_parameters_doc(&template, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
153153
let template = campaign_parameters_form_template_doc(&parameters, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
154154
let id = UuidV7::new();
155-
let (sk, kid) = create_dummy_key_pair(RoleId::BrandAdmin)
156-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
155+
let (sk, kid) = create_dummy_key_pair(None);
156+
provider.add_sk(kid.clone(), sk.clone());
157157
Builder::new()
158158
.with_json_metadata(serde_json::json!({
159159
"content-type": ContentType::Json,

rust/signed_doc/tests/campaign_parameters_form_template.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ mod common;
2828
let template = brand_parameters_form_template_doc(provider).inspect(|v| provider.add_document(None, v).unwrap())?;
2929
let parameters = brand_parameters_doc(&template, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
3030
let id = UuidV7::new();
31-
let (sk, kid) = create_dummy_key_pair(RoleId::Role0)
32-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
31+
let (sk, kid) = create_dummy_key_pair(Some(RoleId::Role0));
32+
provider.add_sk(kid.clone(), sk.clone());
3333
Builder::new()
3434
.with_json_metadata(serde_json::json!({
3535
"content-type": ContentType::SchemaJson,
@@ -55,8 +55,8 @@ mod common;
5555
let template = brand_parameters_form_template_doc(provider).inspect(|v| provider.add_document(None, v).unwrap())?;
5656
let parameters = brand_parameters_doc(&template, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
5757
let id = UuidV7::new();
58-
let (sk, kid) = create_dummy_key_pair(RoleId::BrandAdmin)
59-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
58+
let (sk, kid) = create_dummy_key_pair(None);
59+
provider.add_sk(kid.clone(), sk.clone());
6060
Builder::new()
6161
.with_json_metadata(serde_json::json!({
6262
"content-type": ContentType::SchemaJson,
@@ -82,8 +82,8 @@ mod common;
8282
let template = brand_parameters_form_template_doc(provider).inspect(|v| provider.add_document(None, v).unwrap())?;
8383
let parameters = brand_parameters_doc(&template, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
8484
let id = UuidV7::new();
85-
let (sk, kid) = create_dummy_key_pair(RoleId::BrandAdmin)
86-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
85+
let (sk, kid) = create_dummy_key_pair(None);
86+
provider.add_sk(kid.clone(), sk.clone());
8787
Builder::new()
8888
.with_json_metadata(serde_json::json!({
8989
"content-type": ContentType::SchemaJson,
@@ -106,8 +106,8 @@ mod common;
106106
#[test_case(
107107
|provider| {
108108
let id = UuidV7::new();
109-
let (sk, kid) = create_dummy_key_pair(RoleId::BrandAdmin)
110-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
109+
let (sk, kid) = create_dummy_key_pair(None);
110+
provider.add_sk(kid.clone(), sk.clone());
111111
Builder::new()
112112
.with_json_metadata(serde_json::json!({
113113
"content-type": ContentType::SchemaJson,

rust/signed_doc/tests/category_parameters.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ mod common;
3535
let parameters = campaign_parameters_doc(&template, &parameters, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
3636
let template = category_parameters_form_template_doc(&parameters, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
3737
let id = UuidV7::new();
38-
let (sk, kid) = create_dummy_key_pair(RoleId::Role0)
39-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
38+
let (sk, kid) = create_dummy_key_pair(Some(RoleId::Role0));
39+
provider.add_sk(kid.clone(), sk.clone());
4040
Builder::new()
4141
.with_json_metadata(serde_json::json!({
4242
"content-type": ContentType::Json,
@@ -69,8 +69,8 @@ mod common;
6969
let parameters = campaign_parameters_doc(&template, &parameters, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
7070
let template = category_parameters_form_template_doc(&parameters, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
7171
let id = UuidV7::new();
72-
let (sk, kid) = create_dummy_key_pair(RoleId::BrandAdmin)
73-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
72+
let (sk, kid) = create_dummy_key_pair(None);
73+
provider.add_sk(kid.clone(), sk.clone());
7474
Builder::new()
7575
.with_json_metadata(serde_json::json!({
7676
"content-type": ContentType::Json,
@@ -103,8 +103,8 @@ mod common;
103103
let parameters = campaign_parameters_doc(&template, &parameters, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
104104
let template = category_parameters_form_template_doc(&parameters, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
105105
let id = UuidV7::new();
106-
let (sk, kid) = create_dummy_key_pair(RoleId::BrandAdmin)
107-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
106+
let (sk, kid) = create_dummy_key_pair(None);
107+
provider.add_sk(kid.clone(), sk.clone());
108108
Builder::new()
109109
.with_json_metadata(serde_json::json!({
110110
"content-type": ContentType::Json,
@@ -135,8 +135,8 @@ mod common;
135135
let template = campaign_parameters_form_template_doc(&parameters, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
136136
let parameters = campaign_parameters_doc(&template, &parameters, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
137137
let id = UuidV7::new();
138-
let (sk, kid) = create_dummy_key_pair(RoleId::BrandAdmin)
139-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
138+
let (sk, kid) = create_dummy_key_pair(None);
139+
provider.add_sk(kid.clone(), sk.clone());
140140
Builder::new()
141141
.with_json_metadata(serde_json::json!({
142142
"content-type": ContentType::Json,
@@ -165,8 +165,8 @@ mod common;
165165
let parameters = campaign_parameters_doc(&template, &parameters, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
166166
let template = category_parameters_form_template_doc(&parameters, provider).inspect(|v| provider.add_document(None, v).unwrap())?;
167167
let id = UuidV7::new();
168-
let (sk, kid) = create_dummy_key_pair(RoleId::BrandAdmin)
169-
.inspect(|(sk, kid)| provider.add_sk(kid.clone(), sk.clone()))?;
168+
let (sk, kid) = create_dummy_key_pair(None);
169+
provider.add_sk(kid.clone(), sk.clone());
170170
Builder::new()
171171
.with_json_metadata(serde_json::json!({
172172
"content-type": ContentType::Json,

0 commit comments

Comments
 (0)