diff --git a/.github/workflows/check.yaml b/.github/workflows/check.yaml index 6917f613..bd89692f 100644 --- a/.github/workflows/check.yaml +++ b/.github/workflows/check.yaml @@ -233,7 +233,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --offline + args: --offline --workspace coverage: @@ -284,7 +284,7 @@ jobs: uses: actions-rs/cargo@v1 with: command: test - args: --all-features --no-fail-fast + args: --all-features --no-fail-fast --workspace env: CARGO_INCREMENTAL: '0' RUSTFLAGS: '-Zinstrument-coverage' diff --git a/Cargo.lock b/Cargo.lock index 7535226f..c811f070 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -304,7 +304,10 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ + "lazy_static", "memchr", + "regex-automata", + "serde", ] [[package]] @@ -478,6 +481,12 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4c78c047431fee22c1a7bb92e00ad095a02a983affe4d8a72e2a2c62c1b94f3" +[[package]] +name = "convert_case" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + [[package]] name = "cookie" version = "0.16.0" @@ -617,6 +626,28 @@ dependencies = [ "subtle", ] +[[package]] +name = "csv" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +dependencies = [ + "bstr", + "csv-core", + "itoa 0.4.8", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", +] + [[package]] name = "darling" version = "0.13.1" @@ -1563,6 +1594,30 @@ dependencies = [ "warp", ] +[[package]] +name = "mas-iana" +version = "0.1.0" +dependencies = [ + "schemars", + "serde", +] + +[[package]] +name = "mas-iana-codegen" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "convert_case", + "csv", + "futures-util", + "reqwest", + "serde", + "tokio", + "tracing", + "tracing-subscriber", +] + [[package]] name = "mas-jose" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index d02b0e9b..20704f87 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,4 @@ [workspace] +default-members = ["crates/cli"] members = ["crates/*"] diff --git a/Dockerfile b/Dockerfile index 09562af6..53d39c34 100644 --- a/Dockerfile +++ b/Dockerfile @@ -120,6 +120,7 @@ COPY . . COPY --from=static-files /app/crates/static-files/public /app/crates/static-files/public ENV SQLX_OFFLINE=true RUN cargo test \ + --workspace \ --target $(/docker-arch-to-rust-target.sh "${TARGETPLATFORM}") ## Runtime stage, debug variant ## diff --git a/crates/iana-codegen/Cargo.toml b/crates/iana-codegen/Cargo.toml new file mode 100644 index 00000000..0d22fb65 --- /dev/null +++ b/crates/iana-codegen/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "mas-iana-codegen" +version = "0.1.0" +authors = ["Quentin Gliech "] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +anyhow = "1.0.51" +async-trait = "0.1.52" +convert_case = "0.4" +csv = "1.1" +futures-util = "0.3.19" +reqwest = { version = "0.11", features = ["blocking", "rustls-tls"], default-features = false } +serde = { version = "1", features = ["derive"] } +tokio = { version = "1.15.0", features = ["full"] } +tracing = "0.1.29" +tracing-subscriber = "0.3.5" diff --git a/crates/iana-codegen/src/jose.rs b/crates/iana-codegen/src/jose.rs new file mode 100644 index 00000000..8fd0d9f7 --- /dev/null +++ b/crates/iana-codegen/src/jose.rs @@ -0,0 +1,241 @@ +// Copyright 2022 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use serde::Deserialize; + +use crate::EnumEntry; + +#[derive(Debug, Deserialize, PartialEq, Eq)] +enum Usage { + #[serde(rename = "alg")] + Alg, + #[serde(rename = "enc")] + Enc, + #[serde(rename = "JWK")] + Jwk, +} + +#[derive(Debug, Deserialize)] +enum Requirements { + Required, + #[serde(rename = "Recommended+")] + RecommendedPlus, + Recommended, + #[serde(rename = "Recommended-")] + RecommendedMinus, + Optional, + Prohibited, +} + +#[allow(dead_code)] +#[derive(Debug, Deserialize)] +pub struct WebEncryptionSignatureAlgorithm { + #[serde(rename = "Algorithm Name")] + name: String, + #[serde(rename = "Algorithm Description")] + description: String, + #[serde(rename = "Algorithm Usage Location(s)")] + usage: Usage, + #[serde(rename = "JOSE Implementation Requirements")] + requirements: Requirements, + #[serde(rename = "Change Controller")] + change_controller: String, + #[serde(rename = "Reference")] + reference: String, + #[serde(rename = "Algorithm Analysis Document(s)")] + analysis: String, +} + +impl EnumEntry for WebEncryptionSignatureAlgorithm { + const URL: &'static str = + "https://www.iana.org/assignments/jose/web-signature-encryption-algorithms.csv"; + const SECTIONS: &'static [&'static str] = + &["JsonWebSignatureAlgorithm", "JsonWebEncryptionAlgorithm"]; + + fn key(&self) -> Option<&'static str> { + match self.usage { + Usage::Alg => Some("JsonWebSignatureAlgorithm"), + Usage::Enc => Some("JsonWebEncryptionAlgorithm"), + _ => None, + } + } + + fn name(&self) -> &str { + &self.name + } + + fn description(&self) -> Option<&str> { + Some(&self.description) + } +} + +#[allow(dead_code)] +#[derive(Debug, Deserialize)] +pub struct WebEncryptionCompressionAlgorithm { + #[serde(rename = "Compression Algorithm Value")] + value: String, + #[serde(rename = "Compression Algorithm Description")] + description: String, + #[serde(rename = "Change Controller")] + change_controller: String, + #[serde(rename = "Reference")] + reference: String, +} + +impl EnumEntry for WebEncryptionCompressionAlgorithm { + const URL: &'static str = + "https://www.iana.org/assignments/jose/web-encryption-compression-algorithms.csv"; + const SECTIONS: &'static [&'static str] = &["JsonWebEncryptionCompressionAlgorithm"]; + + fn key(&self) -> Option<&'static str> { + Some("JsonWebEncryptionCompressionAlgorithm") + } + + fn name(&self) -> &str { + &self.value + } + + fn description(&self) -> Option<&str> { + Some(&self.description) + } +} + +#[allow(dead_code)] +#[derive(Debug, Deserialize)] +pub struct WebKeyType { + #[serde(rename = "\"kty\" Parameter Value")] + value: String, + #[serde(rename = "Key Type Description")] + description: String, + #[serde(rename = "JOSE Implementation Requirements")] + requirements: Requirements, + #[serde(rename = "Change Controller")] + change_controller: String, + #[serde(rename = "Reference")] + reference: String, +} + +impl EnumEntry for WebKeyType { + const URL: &'static str = "https://www.iana.org/assignments/jose/web-key-types.csv"; + const SECTIONS: &'static [&'static str] = &["JsonWebKeyType"]; + + fn key(&self) -> Option<&'static str> { + Some("JsonWebKeyType") + } + + fn name(&self) -> &str { + &self.value + } + + fn description(&self) -> Option<&str> { + Some(&self.description) + } +} + +#[allow(dead_code)] +#[derive(Debug, Deserialize)] +pub struct WebKeyEllipticCurve { + #[serde(rename = "Curve Name")] + name: String, + #[serde(rename = "Curve Description")] + description: String, + #[serde(rename = "JOSE Implementation Requirements")] + requirements: Requirements, + #[serde(rename = "Change Controller")] + change_controller: String, + #[serde(rename = "Reference")] + reference: String, +} + +impl EnumEntry for WebKeyEllipticCurve { + const URL: &'static str = "https://www.iana.org/assignments/jose/web-key-elliptic-curve.csv"; + const SECTIONS: &'static [&'static str] = + &["JsonWebKeyEcEllipticCurve", "JsonWebKeyOkpEllipticCurve"]; + + fn key(&self) -> Option<&'static str> { + if self.name.starts_with("P-") || self.name == "secp256k1" { + Some("JsonWebKeyEcEllipticCurve") + } else { + Some("JsonWebKeyOkpEllipticCurve") + } + } + + fn name(&self) -> &str { + &self.name + } + + fn description(&self) -> Option<&str> { + Some(&self.description) + } +} + +#[allow(dead_code)] +#[derive(Debug, Deserialize)] +pub struct WebKeyUse { + #[serde(rename = "Use Member Value")] + value: String, + #[serde(rename = "Use Description")] + description: String, + #[serde(rename = "Change Controller")] + change_controller: String, + #[serde(rename = "Reference")] + reference: String, +} + +impl EnumEntry for WebKeyUse { + const URL: &'static str = "https://www.iana.org/assignments/jose/web-key-use.csv"; + const SECTIONS: &'static [&'static str] = &["JsonWebKeyUse"]; + + fn key(&self) -> Option<&'static str> { + Some("JsonWebKeyUse") + } + + fn name(&self) -> &str { + &self.value + } + + fn description(&self) -> Option<&str> { + Some(&self.description) + } +} + +#[allow(dead_code)] +#[derive(Debug, Deserialize)] +pub struct WebKeyOperation { + #[serde(rename = "Key Operation Value")] + name: String, + #[serde(rename = "Key Operation Description")] + description: String, + #[serde(rename = "Change Controller")] + change_controller: String, + #[serde(rename = "Reference")] + reference: String, +} + +impl EnumEntry for WebKeyOperation { + const URL: &'static str = "https://www.iana.org/assignments/jose/web-key-operations.csv"; + const SECTIONS: &'static [&'static str] = &["JsonWebKeyOperation"]; + + fn key(&self) -> Option<&'static str> { + Some("JsonWebKeyOperation") + } + + fn name(&self) -> &str { + &self.name + } + + fn description(&self) -> Option<&str> { + Some(&self.description) + } +} diff --git a/crates/iana-codegen/src/main.rs b/crates/iana-codegen/src/main.rs new file mode 100644 index 00000000..6955d066 --- /dev/null +++ b/crates/iana-codegen/src/main.rs @@ -0,0 +1,219 @@ +// Copyright 2022 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::{collections::HashMap, fmt::Display, path::PathBuf, sync::Arc}; + +use reqwest::Client; +use tokio::io::AsyncWriteExt; +use tracing::Level; + +pub mod jose; +pub mod oauth; +pub mod traits; + +#[derive(Debug)] +struct File { + client: Arc, + registry_name: &'static str, + registry_url: &'static str, + sections: Vec<&'static str>, + sources: Vec<&'static str>, + items: HashMap<&'static str, Vec>, +} + +fn resolve_path(relative: PathBuf) -> PathBuf { + let crate_root = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let workspace_root = crate_root.parent().unwrap().parent().unwrap(); + workspace_root.join(relative) +} + +impl File { + #[tracing::instrument(skip(client))] + fn new(registry_name: &'static str, registry_url: &'static str, client: Arc) -> Self { + tracing::info!("Generating file from IANA registry"); + Self { + client, + registry_name, + registry_url, + sources: Vec::new(), + sections: Vec::new(), + items: HashMap::new(), + } + } + + #[tracing::instrument(skip_all, fields(url))] + async fn load(mut self) -> anyhow::Result { + tracing::Span::current().record("url", &T::URL); + self.sections.extend_from_slice(T::SECTIONS); + self.sources.push(T::URL); + for (key, value) in T::fetch(&self.client).await? { + self.items.entry(key).or_default().push(value); + } + Ok(self) + } + + #[tracing::instrument(skip_all)] + async fn write(&self, path: PathBuf) -> anyhow::Result<()> { + let mut file = tokio::fs::OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open(path) + .await?; + + tracing::info!("Writing file"); + file.write_all(format!("{}", self).as_bytes()).await?; + + Ok(()) + } +} + +impl Display for File { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + writeln!( + f, + r#"// Copyright 2022 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Enums from the {:?} IANA registry +//! See <{}> +//! +//! Generated from:"#, + self.registry_name, self.registry_url, + )?; + + for source in &self.sources { + writeln!(f, "//! - <{}>", source)?; + } + + writeln!( + f, + r#" +// Do not edit this file manually + +use schemars::JsonSchema; +use serde::{{Deserialize, Serialize}}; +"# + )?; + + for key in &self.sections { + let list = if let Some(list) = self.items.get(key) { + list + } else { + continue; + }; + + writeln!( + f, + "#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)]" + )?; + write!(f, "pub enum {} {{", key)?; + for member in list { + writeln!(f)?; + if let Some(description) = &member.description { + writeln!(f, " /// {}", description)?; + } + writeln!(f, " #[serde(rename = \"{}\")]", member.value)?; + writeln!(f, " {},", member.enum_name)?; + } + writeln!(f, "}}")?; + writeln!(f)?; + } + + Ok(()) + } +} + +use self::{jose::*, oauth::*, traits::*}; + +#[tracing::instrument(skip(client))] +async fn generate_jose(client: &Arc, path: PathBuf) -> anyhow::Result<()> { + let path = resolve_path(path); + let client = client.clone(); + + let file = File::new( + "JSON Object Signing and Encryption", + "https://www.iana.org/assignments/jose/jose.xhtml", + client.clone(), + ) + .load::() + .await? + .load::() + .await? + .load::() + .await? + .load::() + .await? + .load::() + .await? + .load::() + .await?; + + file.write(path).await?; + + Ok(()) +} + +#[tracing::instrument(skip(client))] +async fn generate_oauth(client: &Arc, path: PathBuf) -> anyhow::Result<()> { + let path = resolve_path(path); + let client = client.clone(); + + let file = File::new( + "OAuth Parameters", + "https://www.iana.org/assignments/jose/jose.xhtml", + client.clone(), + ) + .load::() + .await? + .load::() + .await? + .load::() + .await? + .load::() + .await?; + + file.write(path).await?; + + Ok(()) +} + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + tracing_subscriber::fmt() + .with_max_level(Level::INFO) + .pretty() + .init(); + + let client = Client::builder().user_agent("iana-parser/0.0.1").build()?; + let client = Arc::new(client); + + let iana_crate_root = PathBuf::from("crates/iana/"); + + generate_jose(&client, iana_crate_root.join("src/jose.rs")).await?; + generate_oauth(&client, iana_crate_root.join("src/oauth.rs")).await?; + + Ok(()) +} diff --git a/crates/iana-codegen/src/oauth.rs b/crates/iana-codegen/src/oauth.rs new file mode 100644 index 00000000..13206ea6 --- /dev/null +++ b/crates/iana-codegen/src/oauth.rs @@ -0,0 +1,116 @@ +// Copyright 2022 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use serde::Deserialize; + +use crate::EnumEntry; + +#[allow(dead_code)] +#[derive(Debug, Deserialize)] +pub struct TokenTypeHint { + #[serde(rename = "Hint Value")] + name: String, + #[serde(rename = "Change Controller")] + change_controller: String, + #[serde(rename = "Reference")] + reference: String, +} + +impl EnumEntry for TokenTypeHint { + const URL: &'static str = + "https://www.iana.org/assignments/oauth-parameters/token-type-hint.csv"; + const SECTIONS: &'static [&'static str] = &["OAuthTokenTypeHint"]; + + fn key(&self) -> Option<&'static str> { + Some("OAuthTokenTypeHint") + } + + fn name(&self) -> &str { + &self.name + } +} + +#[allow(dead_code)] +#[derive(Debug, Deserialize)] +pub struct AuthorizationEndpointResponseType { + #[serde(rename = "Name")] + name: String, + #[serde(rename = "Change Controller")] + change_controller: String, + #[serde(rename = "Reference")] + reference: String, +} + +impl EnumEntry for AuthorizationEndpointResponseType { + const URL: &'static str = "https://www.iana.org/assignments/oauth-parameters/endpoint.csv"; + const SECTIONS: &'static [&'static str] = &["OAuthAuthorizationEndpointResponseType"]; + + fn key(&self) -> Option<&'static str> { + Some("OAuthAuthorizationEndpointResponseType") + } + + fn name(&self) -> &str { + &self.name + } +} + +#[allow(dead_code)] +#[derive(Debug, Deserialize)] +pub struct TokenEndpointAuthenticationMethod { + #[serde(rename = "Token Endpoint Authentication Method Name")] + name: String, + #[serde(rename = "Change Controller")] + change_controller: String, + #[serde(rename = "Reference")] + reference: String, +} + +impl EnumEntry for TokenEndpointAuthenticationMethod { + const URL: &'static str = + "https://www.iana.org/assignments/oauth-parameters/token-endpoint-auth-method.csv"; + const SECTIONS: &'static [&'static str] = &["OAuthTokenEndpointAuthenticationMethod"]; + + fn key(&self) -> Option<&'static str> { + Some("OAuthTokenEndpointAuthenticationMethod") + } + + fn name(&self) -> &str { + &self.name + } +} + +#[allow(dead_code)] +#[derive(Debug, Deserialize)] +pub struct PkceCodeChallengeMethod { + #[serde(rename = "Code Challenge Method Parameter Name")] + name: String, + #[serde(rename = "Change Controller")] + change_controller: String, + #[serde(rename = "Reference")] + reference: String, +} + +impl EnumEntry for PkceCodeChallengeMethod { + const URL: &'static str = + "https://www.iana.org/assignments/oauth-parameters/pkce-code-challenge-method.csv"; + const SECTIONS: &'static [&'static str] = &["PkceCodeChallengeMethod"]; + + fn key(&self) -> Option<&'static str> { + Some("PkceCodeChallengeMethod") + } + + fn name(&self) -> &str { + &self.name + } +} diff --git a/crates/iana-codegen/src/traits.rs b/crates/iana-codegen/src/traits.rs new file mode 100644 index 00000000..ddde5858 --- /dev/null +++ b/crates/iana-codegen/src/traits.rs @@ -0,0 +1,74 @@ +// Copyright 2022 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use anyhow::Context; +use async_trait::async_trait; +use convert_case::{Case, Casing}; +use reqwest::Client; +use serde::de::DeserializeOwned; + +#[derive(Debug)] +pub struct EnumMember { + pub value: String, + pub description: Option, + pub enum_name: String, +} + +#[async_trait] +pub trait EnumEntry: DeserializeOwned + Send + Sync { + const URL: &'static str; + const SECTIONS: &'static [&'static str]; + + fn key(&self) -> Option<&'static str>; + fn name(&self) -> &str; + fn description(&self) -> Option<&str> { + None + } + fn enum_name(&self) -> String { + self.name().replace('+', "_").to_case(Case::Pascal) + } + + async fn fetch(client: &Client) -> anyhow::Result> { + tracing::info!("Fetching CSV"); + let body = client + .get(Self::URL) + .send() + .await + .context(format!("can't the CSV at {}", Self::URL))? + .bytes() + .await + .context(format!("can't the CSV body at {}", Self::URL))?; + + let parsed: Result, _> = csv::Reader::from_reader(body.as_ref()) + .into_deserialize() + .filter_map(|item: Result| { + item.map(|item| { + item.key().map(|key| { + ( + key, + EnumMember { + value: item.name().to_string(), + description: item.description().map(ToString::to_string), + enum_name: item.enum_name(), + }, + ) + }) + }) + .transpose() + }) + .collect(); + + Ok(parsed.context(format!("can't parse the CSV at {}", Self::URL))?) + } +} diff --git a/crates/iana/Cargo.toml b/crates/iana/Cargo.toml new file mode 100644 index 00000000..69165869 --- /dev/null +++ b/crates/iana/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "mas-iana" +version = "0.1.0" +authors = ["Quentin Gliech "] +edition = "2021" +license = "Apache-2.0" + +[dependencies] +serde = "1.0.133" +schemars = { version = "0.8.8" } diff --git a/crates/iana/src/jose.rs b/crates/iana/src/jose.rs new file mode 100644 index 00000000..a5b46ea2 --- /dev/null +++ b/crates/iana/src/jose.rs @@ -0,0 +1,306 @@ +// Copyright 2022 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Enums from the "JSON Object Signing and Encryption" IANA registry +//! See +//! +//! Generated from: +//! - +//! - +//! - +//! - +//! - +//! - + +// Do not edit this file manually + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +pub enum JsonWebSignatureAlgorithm { + /// HMAC using SHA-256 + #[serde(rename = "HS256")] + Hs256, + + /// HMAC using SHA-384 + #[serde(rename = "HS384")] + Hs384, + + /// HMAC using SHA-512 + #[serde(rename = "HS512")] + Hs512, + + /// RSASSA-PKCS1-v1_5 using SHA-256 + #[serde(rename = "RS256")] + Rs256, + + /// RSASSA-PKCS1-v1_5 using SHA-384 + #[serde(rename = "RS384")] + Rs384, + + /// RSASSA-PKCS1-v1_5 using SHA-512 + #[serde(rename = "RS512")] + Rs512, + + /// ECDSA using P-256 and SHA-256 + #[serde(rename = "ES256")] + Es256, + + /// ECDSA using P-384 and SHA-384 + #[serde(rename = "ES384")] + Es384, + + /// ECDSA using P-521 and SHA-512 + #[serde(rename = "ES512")] + Es512, + + /// RSASSA-PSS using SHA-256 and MGF1 with SHA-256 + #[serde(rename = "PS256")] + Ps256, + + /// RSASSA-PSS using SHA-384 and MGF1 with SHA-384 + #[serde(rename = "PS384")] + Ps384, + + /// RSASSA-PSS using SHA-512 and MGF1 with SHA-512 + #[serde(rename = "PS512")] + Ps512, + + /// No digital signature or MAC performed + #[serde(rename = "none")] + None, + + /// RSAES-PKCS1-v1_5 + #[serde(rename = "RSA1_5")] + Rsa15, + + /// RSAES OAEP using default parameters + #[serde(rename = "RSA-OAEP")] + RsaOaep, + + /// RSAES OAEP using SHA-256 and MGF1 with SHA-256 + #[serde(rename = "RSA-OAEP-256")] + RsaOaep256, + + /// AES Key Wrap using 128-bit key + #[serde(rename = "A128KW")] + A128Kw, + + /// AES Key Wrap using 192-bit key + #[serde(rename = "A192KW")] + A192Kw, + + /// AES Key Wrap using 256-bit key + #[serde(rename = "A256KW")] + A256Kw, + + /// Direct use of a shared symmetric key + #[serde(rename = "dir")] + Dir, + + /// ECDH-ES using Concat KDF + #[serde(rename = "ECDH-ES")] + EcdhEs, + + /// ECDH-ES using Concat KDF and "A128KW" wrapping + #[serde(rename = "ECDH-ES+A128KW")] + EcdhEsA128Kw, + + /// ECDH-ES using Concat KDF and "A192KW" wrapping + #[serde(rename = "ECDH-ES+A192KW")] + EcdhEsA192Kw, + + /// ECDH-ES using Concat KDF and "A256KW" wrapping + #[serde(rename = "ECDH-ES+A256KW")] + EcdhEsA256Kw, + + /// Key wrapping with AES GCM using 128-bit key + #[serde(rename = "A128GCMKW")] + A128Gcmkw, + + /// Key wrapping with AES GCM using 192-bit key + #[serde(rename = "A192GCMKW")] + A192Gcmkw, + + /// Key wrapping with AES GCM using 256-bit key + #[serde(rename = "A256GCMKW")] + A256Gcmkw, + + /// PBES2 with HMAC SHA-256 and "A128KW" wrapping + #[serde(rename = "PBES2-HS256+A128KW")] + Pbes2Hs256A128Kw, + + /// PBES2 with HMAC SHA-384 and "A192KW" wrapping + #[serde(rename = "PBES2-HS384+A192KW")] + Pbes2Hs384A192Kw, + + /// PBES2 with HMAC SHA-512 and "A256KW" wrapping + #[serde(rename = "PBES2-HS512+A256KW")] + Pbes2Hs512A256Kw, + + /// EdDSA signature algorithms + #[serde(rename = "EdDSA")] + EdDsa, + + /// RSA-OAEP using SHA-384 and MGF1 with SHA-384 + #[serde(rename = "RSA-OAEP-384")] + RsaOaep384, + + /// RSA-OAEP using SHA-512 and MGF1 with SHA-512 + #[serde(rename = "RSA-OAEP-512")] + RsaOaep512, + + /// ECDSA using secp256k1 curve and SHA-256 + #[serde(rename = "ES256K")] + Es256K, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +pub enum JsonWebEncryptionAlgorithm { + /// AES_128_CBC_HMAC_SHA_256 authenticated encryption algorithm + #[serde(rename = "A128CBC-HS256")] + A128CbcHs256, + + /// AES_192_CBC_HMAC_SHA_384 authenticated encryption algorithm + #[serde(rename = "A192CBC-HS384")] + A192CbcHs384, + + /// AES_256_CBC_HMAC_SHA_512 authenticated encryption algorithm + #[serde(rename = "A256CBC-HS512")] + A256CbcHs512, + + /// AES GCM using 128-bit key + #[serde(rename = "A128GCM")] + A128Gcm, + + /// AES GCM using 192-bit key + #[serde(rename = "A192GCM")] + A192Gcm, + + /// AES GCM using 256-bit key + #[serde(rename = "A256GCM")] + A256Gcm, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +pub enum JsonWebEncryptionCompressionAlgorithm { + /// DEFLATE + #[serde(rename = "DEF")] + Def, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +pub enum JsonWebKeyType { + /// Elliptic Curve + #[serde(rename = "EC")] + Ec, + + /// RSA + #[serde(rename = "RSA")] + Rsa, + + /// Octet sequence + #[serde(rename = "oct")] + Oct, + + /// Octet string key pairs + #[serde(rename = "OKP")] + Okp, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +pub enum JsonWebKeyEcEllipticCurve { + /// P-256 Curve + #[serde(rename = "P-256")] + P256, + + /// P-384 Curve + #[serde(rename = "P-384")] + P384, + + /// P-521 Curve + #[serde(rename = "P-521")] + P521, + + /// SECG secp256k1 curve + #[serde(rename = "secp256k1")] + Secp256K1, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +pub enum JsonWebKeyOkpEllipticCurve { + /// Ed25519 signature algorithm key pairs + #[serde(rename = "Ed25519")] + Ed25519, + + /// Ed448 signature algorithm key pairs + #[serde(rename = "Ed448")] + Ed448, + + /// X25519 function key pairs + #[serde(rename = "X25519")] + X25519, + + /// X448 function key pairs + #[serde(rename = "X448")] + X448, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +pub enum JsonWebKeyUse { + /// Digital Signature or MAC + #[serde(rename = "sig")] + Sig, + + /// Encryption + #[serde(rename = "enc")] + Enc, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +pub enum JsonWebKeyOperation { + /// Compute digital signature or MAC + #[serde(rename = "sign")] + Sign, + + /// Verify digital signature or MAC + #[serde(rename = "verify")] + Verify, + + /// Encrypt content + #[serde(rename = "encrypt")] + Encrypt, + + /// Decrypt content and validate decryption, if applicable + #[serde(rename = "decrypt")] + Decrypt, + + /// Encrypt key + #[serde(rename = "wrapKey")] + WrapKey, + + /// Decrypt key and validate decryption, if applicable + #[serde(rename = "unwrapKey")] + UnwrapKey, + + /// Derive key + #[serde(rename = "deriveKey")] + DeriveKey, + + /// Derive bits not to be used as a key + #[serde(rename = "deriveBits")] + DeriveBits, +} + diff --git a/crates/iana/src/lib.rs b/crates/iana/src/lib.rs new file mode 100644 index 00000000..873d1d41 --- /dev/null +++ b/crates/iana/src/lib.rs @@ -0,0 +1,16 @@ +// Copyright 2022 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pub mod jose; +pub mod oauth; diff --git a/crates/iana/src/oauth.rs b/crates/iana/src/oauth.rs new file mode 100644 index 00000000..2f357e64 --- /dev/null +++ b/crates/iana/src/oauth.rs @@ -0,0 +1,100 @@ +// Copyright 2022 The Matrix.org Foundation C.I.C. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Enums from the "OAuth Parameters" IANA registry +//! See +//! +//! Generated from: +//! - +//! - +//! - +//! - + +// Do not edit this file manually + +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +pub enum OAuthTokenTypeHint { + #[serde(rename = "access_token")] + AccessToken, + + #[serde(rename = "refresh_token")] + RefreshToken, + + #[serde(rename = "pct")] + Pct, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +pub enum OAuthAuthorizationEndpointResponseType { + #[serde(rename = "code")] + Code, + + #[serde(rename = "code id_token")] + CodeIdToken, + + #[serde(rename = "code id_token token")] + CodeIdTokenToken, + + #[serde(rename = "code token")] + CodeToken, + + #[serde(rename = "id_token")] + IdToken, + + #[serde(rename = "id_token token")] + IdTokenToken, + + #[serde(rename = "none")] + None, + + #[serde(rename = "token")] + Token, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +pub enum OAuthTokenEndpointAuthenticationMethod { + #[serde(rename = "none")] + None, + + #[serde(rename = "client_secret_post")] + ClientSecretPost, + + #[serde(rename = "client_secret_basic")] + ClientSecretBasic, + + #[serde(rename = "client_secret_jwt")] + ClientSecretJwt, + + #[serde(rename = "private_key_jwt")] + PrivateKeyJwt, + + #[serde(rename = "tls_client_auth")] + TlsClientAuth, + + #[serde(rename = "self_signed_tls_client_auth")] + SelfSignedTlsClientAuth, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, JsonSchema)] +pub enum PkceCodeChallengeMethod { + #[serde(rename = "plain")] + Plain, + + #[serde(rename = "S256")] + S256, +} +