generated from tkuhrt/os-template
-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Abdulbois <[email protected]> Signed-off-by: Abdulbois <[email protected]>
- Loading branch information
Showing
8 changed files
with
302 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,3 +12,4 @@ Cargo.lock | |
|
||
# MSVC Windows builds of rustc generate these, which store debugging information | ||
*.pdb | ||
.idea/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
[package] | ||
name = "sd-jwt-generate" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | ||
|
||
[dependencies] | ||
clap = { version = "4.4.10", features = ["derive"] } | ||
serde = { version = "1.0.193", features = ["derive"] } | ||
serde_yaml = "0.9.27" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
use clap::Parser; | ||
use serde::Serialize; | ||
|
||
#[derive(Parser)] | ||
pub struct Cli { | ||
/// The type to generate | ||
#[arg(short, value_enum, default_value_t = GenerateType::Example)] | ||
pub type_: GenerateType, | ||
/// The paths to the directories where specifications.yaml file is located | ||
#[arg(short, value_delimiter = ' ', num_args = 0.., require_equals = false)] | ||
pub paths: Vec<std::path::PathBuf>, | ||
} | ||
|
||
|
||
#[derive(clap::ValueEnum, Clone, Debug, Serialize)] | ||
#[serde(rename_all = "kebab-case")] | ||
pub enum GenerateType { | ||
Example, | ||
TestCase, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
mod cli; | ||
mod types; | ||
|
||
use std::path::PathBuf; | ||
use clap::Parser; | ||
use crate::cli::{Cli, GenerateType}; | ||
use crate::types::settings::Settings; | ||
|
||
const SPECIFICATION_FILE_NAME: &str = "specification.yml"; | ||
const SETTINGS_FILE_NAME: &str = "settings.yml"; | ||
|
||
fn main() { | ||
let args = Cli::parse(); | ||
|
||
println!("type_: {:?}, paths: {:?}", args.type_.clone(), args.paths); | ||
|
||
let basedir = std::env::current_dir().expect("Unable to get current directory"); | ||
let settings_file = basedir.join(SETTINGS_FILE_NAME); | ||
|
||
if !settings_file.exists() { | ||
eprintln!("Settings file '{:?}' does not exist.", settings_file); | ||
std::process::exit(1); | ||
} | ||
|
||
let glob: Vec<PathBuf>; | ||
if args.paths.is_empty() { | ||
glob = basedir | ||
.read_dir() | ||
.expect("Unable to read directory") | ||
.filter_map(|entry| { | ||
if let Ok(entry) = entry { | ||
let path = entry.path(); | ||
if path.is_dir() && path.join(SPECIFICATION_FILE_NAME).exists() { | ||
return Some(path.join(SPECIFICATION_FILE_NAME)); | ||
} | ||
} | ||
None | ||
}) | ||
.collect(); | ||
} else { | ||
glob = args.paths.iter() | ||
.map(|d| basedir.join(d).join(SPECIFICATION_FILE_NAME)) | ||
.collect(); | ||
} | ||
println!("settings.yaml - {:?}", settings_file); | ||
println!("specification.yaml files - {:?}", glob); | ||
|
||
|
||
let settings = load_yaml_settings(&settings_file); | ||
println!("{:#?}", settings); | ||
|
||
|
||
for case_path in glob { | ||
println!("Generating data for '{:?}'", case_path); | ||
generate_test_case_data(&settings, &case_path, args.type_.clone()); | ||
} | ||
} | ||
|
||
fn generate_test_case_data(settings: &Settings, test_case: &PathBuf, type_: GenerateType) { | ||
todo!() | ||
} | ||
|
||
fn load_yaml_settings(file: &PathBuf) -> Settings { | ||
let contents = std::fs::read_to_string(file) | ||
.expect("Failed to read settings file"); | ||
|
||
let settings: Settings = serde_yaml::from_str(&contents) | ||
.expect("Failed to parse YAML"); | ||
|
||
settings | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
pub mod settings; | ||
pub mod specification; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
use serde::{Deserialize, Serialize}; | ||
|
||
#[derive(Serialize, Deserialize, PartialEq, Debug)] | ||
pub struct KeySettings { | ||
pub key_size: i32, | ||
pub kty: String, | ||
pub issuer_key: Key, | ||
pub holder_key: Key, | ||
} | ||
|
||
#[derive(Serialize, Deserialize, PartialEq, Debug)] | ||
pub struct Key { | ||
pub kty: String, | ||
pub d: String, | ||
pub crv: String, | ||
pub x: String, | ||
pub y: String, | ||
} | ||
|
||
#[derive(Serialize, Deserialize, PartialEq, Debug)] | ||
pub struct Identifiers { | ||
pub issuer: String, | ||
pub verifier: String, | ||
} | ||
|
||
#[derive(Serialize, Deserialize, PartialEq, Debug)] | ||
pub struct Settings { | ||
pub identifiers: Identifiers, | ||
pub key_settings: KeySettings, | ||
pub key_binding_nonce: String, | ||
pub expiry_seconds: Option<u64>, | ||
pub random_seed: Option<u64>, | ||
pub iat: Option<u64>, | ||
pub exp: Option<u64>, | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use crate::types::settings::Settings; | ||
|
||
#[test] | ||
fn test_test_settings() { | ||
let yaml_str = r#" | ||
identifiers: | ||
issuer: "https://example.com/issuer" | ||
verifier: "https://example.com/verifier" | ||
key_settings: | ||
key_size: 256 | ||
kty: "EC" | ||
issuer_key: | ||
kty: "EC" | ||
d: "Ur2bNKuBPOrAaxsRnbSH6hIhmNTxSGXshDSUD1a1y7g" | ||
crv: "P-256" | ||
x: "b28d4MwZMjw8-00CG4xfnn9SLMVMM19SlqZpVb_uNtQ" | ||
y: "Xv5zWwuoaTgdS6hV43yI6gBwTnjukmFQQnJ_kCxzqk8" | ||
holder_key: | ||
kty: "EC" | ||
d: "5K5SCos8zf9zRemGGUl6yfok-_NiiryNZsvANWMhF-I" | ||
crv: "P-256" | ||
x: "TCAER19Zvu3OHF4j4W4vfSVoHIP1ILilDls7vCeGemc" | ||
y: "ZxjiWWbZMQGHVWKVQ4hbSIirsVfuecCE6t4jT9F2HZQ" | ||
key_binding_nonce: "1234567890" | ||
expiry_seconds: 86400000 | ||
random_seed: 0 | ||
iat: 1683000000 | ||
exp: 1883000000 | ||
"#; | ||
|
||
let settings: Settings = serde_yaml::from_str(yaml_str).unwrap(); | ||
println!("{:#?}", settings); | ||
assert_eq!(settings.identifiers.issuer, "https://example.com/issuer"); | ||
} | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
use serde::{Deserialize, Deserializer, Serialize}; | ||
use serde_yaml::value::TaggedValue; | ||
use serde_yaml::Value; | ||
use std::collections::HashMap; | ||
use std::hash::{Hash, Hasher}; | ||
use std::io; | ||
use std::io::Read; | ||
use serde::de::Error; | ||
|
||
const SD_TAG: &str = "!sd"; | ||
|
||
#[derive(Serialize, Deserialize, PartialEq, Debug, Clone)] | ||
#[serde(rename_all = "kebab-case")] | ||
pub struct Claims(HashMap<ClaimName, Value>); | ||
|
||
#[derive(Serialize, Deserialize, Debug, Clone)] | ||
#[serde(untagged)] | ||
pub enum ClaimName { | ||
Str(String), | ||
Tag(TaggedValue), | ||
} | ||
|
||
impl PartialEq for ClaimName { | ||
fn eq(&self, other: &Self) -> bool { | ||
match (self, other) { | ||
(ClaimName::Str(a), ClaimName::Str(b)) => a == b, | ||
(ClaimName::Tag(a), ClaimName::Tag(b)) => b.eq(a), | ||
_ => false, | ||
} | ||
} | ||
} | ||
|
||
impl Eq for ClaimName {} | ||
|
||
impl Hash for ClaimName { | ||
fn hash<H: Hasher>(&self, state: &mut H) { | ||
match self { | ||
ClaimName::Str(string) => string.hash(state), | ||
ClaimName::Tag(tag) => tag.hash(state), | ||
} | ||
} | ||
} | ||
|
||
#[derive(Debug, Deserialize)] | ||
pub struct Specification { | ||
pub user_claims: UserClaims, | ||
pub holder_disclosed_claims: Claims, | ||
} | ||
|
||
impl From<&str> for Specification { | ||
fn from(value: &str) -> Self { | ||
serde_yaml::from_str(value).expect("Failed to parse YAML") | ||
} | ||
} | ||
|
||
#[derive(Serialize, PartialEq, Debug)] | ||
pub struct UserClaims { | ||
pub sub: String, | ||
#[serde(flatten)] | ||
pub claims: Claims, | ||
} | ||
|
||
impl<'de> Deserialize<'de> for UserClaims { | ||
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> | ||
where | ||
D: Deserializer<'de>, | ||
{ | ||
let mut value: HashMap<Value, Value> = Deserialize::deserialize(deserializer)?; | ||
let sub = &Value::from("sub".to_string()); | ||
|
||
if let Some(Value::String(sub)) = value.remove(sub) { | ||
let mut claims: Claims = Claims(HashMap::new()); | ||
|
||
for (k, v) in value { | ||
match k { | ||
Value::String(s) => { | ||
claims.0.insert(ClaimName::Str(s), v); | ||
} | ||
Value::Tagged(tag) => { | ||
if tag.tag.to_string() == SD_TAG { | ||
claims.0.insert(ClaimName::Tag(*tag), v); | ||
} else { | ||
return Err(Error::custom("Unsupported tag in claim-name, only !sd tag is supported")); | ||
} | ||
} | ||
_ => { | ||
return Err(Error::custom("Unsupported type for claim-name, it can be only string or tagged")); | ||
} | ||
} | ||
} | ||
|
||
return Ok(UserClaims { sub, claims }); | ||
} | ||
|
||
Err(Error::custom("Unsupported structure for user-claims")) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use crate::types::specification::Specification; | ||
|
||
#[test] | ||
fn test_specification() { | ||
let yaml_str = r#" | ||
user_claims: | ||
sub: 6c5c0a49-b589-431d-bae7-219122a9ec2c | ||
name: Bois | ||
!sd address: | ||
street_address: Schulstr. 12 | ||
!sd street_address1: Schulstr. 12 | ||
holder_disclosed_claims: {} | ||
"#; | ||
|
||
let example = Specification::from(yaml_str); | ||
println!("{:#?}", example); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters