From 46c565cc89bda0260a079e907ef0326e440846e7 Mon Sep 17 00:00:00 2001 From: Quentin Gliech Date: Fri, 1 Mar 2024 10:46:45 +0100 Subject: [PATCH] Move schemars to workspace dependencies Also enables the `preserve_order` feature, hence the big schema output diff. --- Cargo.lock | 1 + Cargo.toml | 5 + crates/config/Cargo.toml | 2 +- crates/iana/Cargo.toml | 2 +- crates/jose/Cargo.toml | 2 +- crates/policy/Cargo.toml | 2 +- docs/config.schema.json | 3070 ++++++++--------- .../schema/authorization_grant_input.json | 12 +- policies/schema/register_input.json | 18 +- 9 files changed, 1560 insertions(+), 1554 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2076fe51..630e1ff0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5054,6 +5054,7 @@ checksum = "45a28f4c49489add4ce10783f7911893516f15afe45d015608d41faca6bc4d29" dependencies = [ "chrono", "dyn-clone", + "indexmap 1.9.3", "schemars_derive", "serde", "serde_json", diff --git a/Cargo.toml b/Cargo.toml index bbd83029..e5f70682 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,6 +86,11 @@ version = "1.0.12" [workspace.dependencies.rand] version = "0.8.5" +# JSON Schema generation +[workspace.dependencies.schemars] +version = "0.8.16" +features = ["url", "chrono", "preserve_order"] + # Serialization and deserialization [workspace.dependencies.serde] version = "1.0.196" diff --git a/crates/config/Cargo.toml b/crates/config/Cargo.toml index bd1dde4e..f00c781d 100644 --- a/crates/config/Cargo.toml +++ b/crates/config/Cargo.toml @@ -23,7 +23,7 @@ camino = { workspace = true, features = ["serde1"] } chrono.workspace = true figment = { version = "0.10.14", features = ["env", "yaml", "test"] } ipnetwork = { version = "0.20.0", features = ["serde", "schemars"] } -schemars = { version = "0.8.16", features = ["url", "chrono"] } +schemars.workspace = true ulid.workspace = true url.workspace = true diff --git a/crates/iana/Cargo.toml b/crates/iana/Cargo.toml index 6efb6031..b8b2f797 100644 --- a/crates/iana/Cargo.toml +++ b/crates/iana/Cargo.toml @@ -13,7 +13,7 @@ workspace = true [dependencies] serde = { workspace = true, optional = true } -schemars = { version = "0.8.16", default-features = false, optional = true } +schemars = { workspace = true, optional = true } [features] default = ["serde", "schemars"] diff --git a/crates/jose/Cargo.toml b/crates/jose/Cargo.toml index e2bb9d8d..4e196011 100644 --- a/crates/jose/Cargo.toml +++ b/crates/jose/Cargo.toml @@ -24,7 +24,7 @@ p256 = { version = "0.13.2", features = ["ecdsa"] } p384 = { version = "0.13.0", features = ["ecdsa"] } rand.workspace = true rsa = "0.9.6" -schemars = "0.8.16" +schemars.workspace = true sec1 = "0.7.3" serde.workspace = true serde_json.workspace = true diff --git a/crates/policy/Cargo.toml b/crates/policy/Cargo.toml index 32a257e9..2f5872df 100644 --- a/crates/policy/Cargo.toml +++ b/crates/policy/Cargo.toml @@ -16,7 +16,7 @@ anyhow.workspace = true opa-wasm = { git = "https://github.com/matrix-org/rust-opa-wasm.git" } serde.workspace = true serde_json.workspace = true -schemars = {version = "0.8.16", optional = true } +schemars = { workspace = true, optional = true } thiserror.workspace = true tokio = { version = "1.35.1", features = ["io-util", "rt"] } tracing.workspace = true diff --git a/docs/config.schema.json b/docs/config.schema.json index 8a493318..6bd9e013 100644 --- a/docs/config.schema.json +++ b/docs/config.schema.json @@ -8,21 +8,6 @@ "secrets" ], "properties": { - "branding": { - "description": "Configuration section for tweaking the branding of the service", - "default": { - "service_name": null, - "policy_uri": null, - "tos_uri": null, - "imprint": null, - "logo_uri": null - }, - "allOf": [ - { - "$ref": "#/definitions/BrandingConfig" - } - ] - }, "clients": { "description": "List of OAuth 2.0/OIDC clients config", "default": [], @@ -31,47 +16,6 @@ "$ref": "#/definitions/ClientConfig" } }, - "database": { - "description": "Database connection configuration", - "default": { - "uri": "postgresql://", - "max_connections": 10, - "min_connections": 0, - "connect_timeout": 30, - "idle_timeout": 600, - "max_lifetime": 1800 - }, - "allOf": [ - { - "$ref": "#/definitions/DatabaseConfig" - } - ] - }, - "email": { - "description": "Configuration related to sending emails", - "default": { - "from": "\"Authentication Service\" ", - "reply_to": "\"Authentication Service\" ", - "transport": "blackhole" - }, - "allOf": [ - { - "$ref": "#/definitions/EmailConfig" - } - ] - }, - "experimental": { - "description": "Experimental configuration options", - "default": { - "access_token_ttl": 300, - "compat_token_ttl": 300 - }, - "allOf": [ - { - "$ref": "#/definitions/ExperimentalConfig" - } - ] - }, "http": { "description": "Configuration of the HTTP server", "default": { @@ -140,53 +84,19 @@ } ] }, - "matrix": { - "description": "Configuration related to the homeserver", - "allOf": [ - { - "$ref": "#/definitions/MatrixConfig" - } - ] - }, - "passwords": { - "description": "Configuration related to user passwords", + "database": { + "description": "Database connection configuration", "default": { - "enabled": true, - "schemes": [ - { - "version": 1, - "algorithm": "argon2id" - } - ] + "uri": "postgresql://", + "max_connections": 10, + "min_connections": 0, + "connect_timeout": 30, + "idle_timeout": 600, + "max_lifetime": 1800 }, "allOf": [ { - "$ref": "#/definitions/PasswordsConfig" - } - ] - }, - "policy": { - "description": "Configuration related to the OPA policies", - "default": { - "wasm_module": "./policies/policy.wasm", - "client_registration_entrypoint": "client_registration/violation", - "register_entrypoint": "register/violation", - "authorization_grant_entrypoint": "authorization_grant/violation", - "password_entrypoint": "password/violation", - "email_entrypoint": "email/violation", - "data": null - }, - "allOf": [ - { - "$ref": "#/definitions/PolicyConfig" - } - ] - }, - "secrets": { - "description": "Application secrets", - "allOf": [ - { - "$ref": "#/definitions/SecretsConfig" + "$ref": "#/definitions/DatabaseConfig" } ] }, @@ -223,6 +133,69 @@ } ] }, + "email": { + "description": "Configuration related to sending emails", + "default": { + "from": "\"Authentication Service\" ", + "reply_to": "\"Authentication Service\" ", + "transport": "blackhole" + }, + "allOf": [ + { + "$ref": "#/definitions/EmailConfig" + } + ] + }, + "secrets": { + "description": "Application secrets", + "allOf": [ + { + "$ref": "#/definitions/SecretsConfig" + } + ] + }, + "passwords": { + "description": "Configuration related to user passwords", + "default": { + "enabled": true, + "schemes": [ + { + "version": 1, + "algorithm": "argon2id" + } + ] + }, + "allOf": [ + { + "$ref": "#/definitions/PasswordsConfig" + } + ] + }, + "matrix": { + "description": "Configuration related to the homeserver", + "allOf": [ + { + "$ref": "#/definitions/MatrixConfig" + } + ] + }, + "policy": { + "description": "Configuration related to the OPA policies", + "default": { + "wasm_module": "./policies/policy.wasm", + "client_registration_entrypoint": "client_registration/violation", + "register_entrypoint": "register/violation", + "authorization_grant_entrypoint": "authorization_grant/violation", + "password_entrypoint": "password/violation", + "email_entrypoint": "email/violation", + "data": null + }, + "allOf": [ + { + "$ref": "#/definitions/PolicyConfig" + } + ] + }, "upstream_oauth2": { "description": "Configuration related to upstream OAuth providers", "default": { @@ -233,170 +206,36 @@ "$ref": "#/definitions/UpstreamOAuth2Config" } ] - } - }, - "definitions": { - "BindConfig": { - "description": "Configuration of a single listener", - "anyOf": [ + }, + "branding": { + "description": "Configuration section for tweaking the branding of the service", + "default": { + "service_name": null, + "policy_uri": null, + "tos_uri": null, + "imprint": null, + "logo_uri": null + }, + "allOf": [ { - "description": "Listen on the specified host and port", - "type": "object", - "required": [ - "port" - ], - "properties": { - "host": { - "description": "Host on which to listen.\n\nDefaults to listening on all addresses", - "type": "string" - }, - "port": { - "description": "Port on which to listen.", - "type": "integer", - "format": "uint16", - "minimum": 0.0 - } - } - }, - { - "description": "Listen on the specified address", - "type": "object", - "required": [ - "address" - ], - "properties": { - "address": { - "description": "Host and port on which to listen", - "examples": [ - "[::1]:8080", - "[::]:8080", - "127.0.0.1:8080", - "0.0.0.0:8080" - ], - "type": "string" - } - } - }, - { - "description": "Listen on a UNIX domain socket", - "type": "object", - "required": [ - "socket" - ], - "properties": { - "socket": { - "description": "Path to the socket", - "type": "string" - } - } - }, - { - "description": "Accept connections on file descriptors passed by the parent process.\n\nThis is useful for grabbing sockets passed by systemd.\n\nSee ", - "type": "object", - "properties": { - "fd": { - "description": "Index of the file descriptor. Note that this is offseted by 3 because of the standard input/output sockets, so setting here a value of `0` will grab the file descriptor `3`", - "default": 0, - "type": "integer", - "format": "uint", - "minimum": 0.0 - }, - "kind": { - "description": "Whether the socket is a TCP socket or a UNIX domain socket. Defaults to TCP.", - "default": "tcp", - "allOf": [ - { - "$ref": "#/definitions/UnixOrTcp" - } - ] - } - } + "$ref": "#/definitions/BrandingConfig" } ] }, - "BrandingConfig": { - "description": "Configuration section for tweaking the branding of the service", - "type": "object", - "properties": { - "imprint": { - "description": "Legal imprint, displayed in the footer in the footer of web pages and emails.", - "type": "string" - }, - "logo_uri": { - "description": "Logo displayed in some web pages.", - "type": "string", - "format": "uri" - }, - "policy_uri": { - "description": "Link to a privacy policy, displayed in the footer of web pages and emails. It is also advertised to clients through the `op_policy_uri` OIDC provider metadata.", - "type": "string", - "format": "uri" - }, - "service_name": { - "description": "A human-readable name. Defaults to the server's address.", - "type": "string" - }, - "tos_uri": { - "description": "Link to a terms of service document, displayed in the footer of web pages and emails. It is also advertised to clients through the `op_tos_uri` OIDC provider metadata.", - "type": "string", - "format": "uri" + "experimental": { + "description": "Experimental configuration options", + "default": { + "access_token_ttl": 300, + "compat_token_ttl": 300 + }, + "allOf": [ + { + "$ref": "#/definitions/ExperimentalConfig" } - } - }, - "ClaimsImports": { - "description": "How claims should be imported", - "type": "object", - "properties": { - "displayname": { - "description": "Import the displayname of the user.", - "default": { - "action": "ignore", - "template": null - }, - "allOf": [ - { - "$ref": "#/definitions/DisplaynameImportPreference" - } - ] - }, - "email": { - "description": "Import the email address of the user based on the `email` and `email_verified` claims", - "default": { - "action": "ignore", - "template": null, - "set_email_verification": "import" - }, - "allOf": [ - { - "$ref": "#/definitions/EmailImportPreference" - } - ] - }, - "localpart": { - "description": "Import the localpart of the MXID", - "default": { - "action": "ignore", - "template": null - }, - "allOf": [ - { - "$ref": "#/definitions/LocalpartImportPreference" - } - ] - }, - "subject": { - "description": "How to determine the subject of the user", - "default": { - "template": null - }, - "allOf": [ - { - "$ref": "#/definitions/SubjectImportPreference" - } - ] - } - } - }, + ] + } + }, + "definitions": { "ClientConfig": { "description": "An OAuth 2.0 client configuration", "type": "object", @@ -539,551 +378,137 @@ } } }, - "DatabaseConfig": { - "description": "Database connection configuration", + "JsonWebKeySet_for_JsonWebKeyPublicParameters": { "type": "object", - "anyOf": [ + "required": [ + "keys" + ], + "properties": { + "keys": { + "type": "array", + "items": { + "$ref": "#/definitions/JsonWebKey_for_JsonWebKeyPublicParameters" + } + } + } + }, + "JsonWebKey_for_JsonWebKeyPublicParameters": { + "type": "object", + "oneOf": [ { - "description": "Connect via a full URI", "type": "object", + "required": [ + "e", + "kty", + "n" + ], "properties": { - "uri": { - "description": "Connection URI", - "default": "postgresql://", + "kty": { "type": "string", - "format": "uri" + "enum": [ + "RSA" + ] + }, + "n": { + "type": "string" + }, + "e": { + "type": "string" } } }, { - "description": "Connect via a map of options", "type": "object", + "required": [ + "crv", + "kty", + "x", + "y" + ], "properties": { - "database": { - "description": "The database name", - "default": null, - "type": "string" - }, - "host": { - "description": "Name of host to connect to", - "default": null, + "kty": { "type": "string", - "format": "hostname" + "enum": [ + "EC" + ] }, - "password": { - "description": "Password to be used if the server demands password authentication", - "default": null, + "crv": { + "$ref": "#/definitions/JsonWebKeyEcEllipticCurve" + }, + "x": { "type": "string" }, - "port": { - "description": "Port number to connect at the server host", - "default": null, - "type": "integer", - "maximum": 65535.0, - "minimum": 1.0 - }, - "socket": { - "description": "Directory containing the UNIX socket to connect to", - "default": null, + "y": { "type": "string" + } + } + }, + { + "type": "object", + "required": [ + "crv", + "kty", + "x" + ], + "properties": { + "kty": { + "type": "string", + "enum": [ + "OKP" + ] }, - "username": { - "description": "PostgreSQL user name to connect as", - "default": null, + "crv": { + "$ref": "#/definitions/JsonWebKeyOkpEllipticCurve" + }, + "x": { "type": "string" } } } ], "properties": { - "connect_timeout": { - "description": "Set the amount of time to attempt connecting to the database", - "default": 30, - "type": "integer", - "format": "uint64", - "minimum": 0.0 + "use": { + "$ref": "#/definitions/JsonWebKeyUse" }, - "idle_timeout": { - "description": "Set a maximum idle duration for individual connections", - "default": 600, - "type": "integer", - "format": "uint64", - "minimum": 0.0 + "key_ops": { + "type": "array", + "items": { + "$ref": "#/definitions/JsonWebKeyOperation" + } }, - "max_connections": { - "description": "Set the maximum number of connections the pool should maintain", - "default": 10, - "type": "integer", - "format": "uint32", - "minimum": 1.0 + "alg": { + "$ref": "#/definitions/JsonWebSignatureAlg" }, - "max_lifetime": { - "description": "Set the maximum lifetime of individual connections", - "default": 1800, - "type": "integer", - "format": "uint64", - "minimum": 0.0 + "kid": { + "type": "string" }, - "min_connections": { - "description": "Set the minimum number of connections the pool should maintain", - "default": 0, - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - "DiscoveryMode": { - "description": "How to discover the provider's configuration", - "oneOf": [ - { - "description": "Use OIDC discovery with strict metadata verification", - "type": "string", - "enum": [ - "oidc" - ] + "x5u": { + "type": "string" }, - { - "description": "Use OIDC discovery with relaxed metadata verification", - "type": "string", - "enum": [ - "insecure" - ] + "x5c": { + "type": "array", + "items": { + "type": "string" + } }, - { - "description": "Use a static configuration", - "type": "string", - "enum": [ - "disabled" - ] - } - ] - }, - "DisplaynameImportPreference": { - "description": "What should be done for the displayname attribute", - "type": "object", - "properties": { - "action": { - "description": "How to handle the attribute", - "default": "ignore", - "allOf": [ - { - "$ref": "#/definitions/ImportAction" - } - ] + "x5t": { + "type": "string" }, - "template": { - "description": "The Jinja2 template to use for the displayname attribute\n\nIf not provided, the default template is `{{ user.name }}`", - "default": null, + "x5t#S256": { "type": "string" } } }, - "EmailConfig": { - "description": "Configuration related to sending emails", - "type": "object", - "oneOf": [ - { - "description": "Don't send emails anywhere", - "type": "object", - "required": [ - "transport" - ], - "properties": { - "transport": { - "type": "string", - "enum": [ - "blackhole" - ] - } - } - }, - { - "description": "Send emails via an SMTP relay", - "type": "object", - "required": [ - "hostname", - "mode", - "transport" - ], - "properties": { - "hostname": { - "description": "Hostname to connect to", - "type": "string", - "format": "hostname" - }, - "mode": { - "description": "Connection mode to the relay", - "allOf": [ - { - "$ref": "#/definitions/EmailSmtpMode" - } - ] - }, - "password": { - "description": "Password for use to authenticate when connecting to the SMTP server", - "type": "string" - }, - "port": { - "description": "Port to connect to. Default is 25 for plain, 465 for TLS and 587 for StartTLS", - "type": "integer", - "format": "uint16", - "minimum": 1.0 - }, - "transport": { - "type": "string", - "enum": [ - "smtp" - ] - }, - "username": { - "description": "Username for use to authenticate when connecting to the SMTP server", - "type": "string" - } - } - }, - { - "description": "Send emails by calling sendmail", - "type": "object", - "required": [ - "transport" - ], - "properties": { - "command": { - "description": "Command to execute", - "default": "sendmail", - "type": "string" - }, - "transport": { - "type": "string", - "enum": [ - "sendmail" - ] - } - } - }, - { - "description": "Send emails via the AWS SESv2 API", - "deprecated": true, - "type": "object", - "required": [ - "transport" - ], - "properties": { - "transport": { - "type": "string", - "enum": [ - "aws_ses" - ] - } - } - } - ], - "properties": { - "from": { - "description": "Email address to use as From when sending emails", - "default": "\"Authentication Service\" ", - "type": "string", - "format": "email" - }, - "reply_to": { - "description": "Email address to use as Reply-To when sending emails", - "default": "\"Authentication Service\" ", - "type": "string", - "format": "email" - } - } - }, - "EmailImportPreference": { - "description": "What should be done with the email attribute", - "type": "object", - "properties": { - "action": { - "description": "How to handle the claim", - "default": "ignore", - "allOf": [ - { - "$ref": "#/definitions/ImportAction" - } - ] - }, - "set_email_verification": { - "description": "Should the email address be marked as verified", - "default": "import", - "allOf": [ - { - "$ref": "#/definitions/SetEmailVerification" - } - ] - }, - "template": { - "description": "The Jinja2 template to use for the email address attribute\n\nIf not provided, the default template is `{{ user.email }}`", - "default": null, - "type": "string" - } - } - }, - "EmailSmtpMode": { - "description": "Encryption mode to use", - "oneOf": [ - { - "description": "Plain text", - "type": "string", - "enum": [ - "plain" - ] - }, - { - "description": "StartTLS (starts as plain text then upgrade to TLS)", - "type": "string", - "enum": [ - "starttls" - ] - }, - { - "description": "TLS", - "type": "string", - "enum": [ - "tls" - ] - } - ] - }, - "ExperimentalConfig": { - "description": "Configuration sections for experimental options\n\nDo not change these options unless you know what you are doing.", - "type": "object", - "properties": { - "access_token_ttl": { - "description": "Time-to-live of access tokens in seconds. Defaults to 5 minutes.", - "default": 300, - "type": "integer", - "format": "uint64", - "maximum": 86400.0, - "minimum": 60.0 - }, - "compat_token_ttl": { - "description": "Time-to-live of compatibility access tokens in seconds. Defaults to 5 minutes.", - "default": 300, - "type": "integer", - "format": "uint64", - "maximum": 86400.0, - "minimum": 60.0 - } - } - }, - "HashingScheme": { - "description": "A hashing algorithm", - "type": "object", - "oneOf": [ - { - "description": "bcrypt", - "type": "object", - "required": [ - "algorithm" - ], - "properties": { - "algorithm": { - "type": "string", - "enum": [ - "bcrypt" - ] - }, - "cost": { - "description": "Hashing cost", - "default": 12, - "type": "integer", - "format": "uint32", - "minimum": 0.0 - } - } - }, - { - "description": "argon2id", - "type": "object", - "required": [ - "algorithm" - ], - "properties": { - "algorithm": { - "type": "string", - "enum": [ - "argon2id" - ] - } - } - }, - { - "description": "PBKDF2", - "type": "object", - "required": [ - "algorithm" - ], - "properties": { - "algorithm": { - "type": "string", - "enum": [ - "pbkdf2" - ] - } - } - } - ], - "required": [ - "version" - ], - "properties": { - "version": { - "type": "integer", - "format": "uint16", - "minimum": 0.0 - } - } - }, - "HttpConfig": { - "description": "Configuration related to the web server", - "type": "object", - "required": [ - "public_base" - ], - "properties": { - "issuer": { - "description": "OIDC issuer URL. Defaults to `public_base` if not set.", - "type": "string", - "format": "uri" - }, - "listeners": { - "description": "List of listeners to run", - "default": [], - "type": "array", - "items": { - "$ref": "#/definitions/ListenerConfig" - } - }, - "public_base": { - "description": "Public URL base from where the authentication service is reachable", - "type": "string", - "format": "uri" - }, - "trusted_proxies": { - "description": "List of trusted reverse proxies that can set the `X-Forwarded-For` header", - "default": [ - "192.128.0.0/16", - "172.16.0.0/12", - "10.0.0.0/10", - "127.0.0.1/8", - "fd00::/8", - "::1/128" - ], - "type": "array", - "items": { - "$ref": "#/definitions/IpNetwork" - } - } - } - }, - "ImportAction": { - "description": "How to handle a claim", - "oneOf": [ - { - "description": "Ignore the claim", - "type": "string", - "enum": [ - "ignore" - ] - }, - { - "description": "Suggest the claim value, but allow the user to change it", - "type": "string", - "enum": [ - "suggest" - ] - }, - { - "description": "Force the claim value, but don't fail if it is missing", - "type": "string", - "enum": [ - "force" - ] - }, - { - "description": "Force the claim value, and fail if it is missing", - "type": "string", - "enum": [ - "require" - ] - } - ] - }, - "IpNetwork": { - "oneOf": [ - { - "title": "v4", - "allOf": [ - { - "$ref": "#/definitions/Ipv4Network" - } - ] - }, - { - "title": "v6", - "allOf": [ - { - "$ref": "#/definitions/Ipv6Network" - } - ] - } - ], - "x-rust-type": "ipnetwork::IpNetwork" - }, - "Ipv4Network": { - "type": "string", - "pattern": "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\/(3[0-2]|[0-2]?[0-9])$", - "x-rust-type": "ipnetwork::Ipv4Network" - }, - "Ipv6Network": { - "type": "string", - "pattern": "^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\")[/](12[0-8]|1[0-1][0-9]|[0-9]?[0-9])$", - "x-rust-type": "ipnetwork::Ipv6Network" - }, - "JsonWebKeyEcEllipticCurve": { - "description": "JSON Web Key EC Elliptic Curve", + "JsonWebKeyUse": { + "description": "JSON Web Key Use", "anyOf": [ { - "description": "P-256 Curve", - "const": "P-256" + "description": "Digital Signature or MAC", + "const": "sig" }, { - "description": "P-384 Curve", - "const": "P-384" - }, - { - "description": "P-521 Curve", - "const": "P-521" - }, - { - "description": "SECG secp256k1 curve", - "const": "secp256k1" - } - ] - }, - "JsonWebKeyOkpEllipticCurve": { - "description": "JSON Web Key OKP Elliptic Curve", - "anyOf": [ - { - "description": "Ed25519 signature algorithm key pairs", - "const": "Ed25519" - }, - { - "description": "Ed448 signature algorithm key pairs", - "const": "Ed448" - }, - { - "description": "X25519 function key pairs", - "const": "X25519" - }, - { - "description": "X448 function key pairs", - "const": "X448" + "description": "Encryption", + "const": "enc" } ] }, @@ -1124,140 +549,6 @@ } ] }, - "JsonWebKeySet_for_JsonWebKeyPublicParameters": { - "type": "object", - "required": [ - "keys" - ], - "properties": { - "keys": { - "type": "array", - "items": { - "$ref": "#/definitions/JsonWebKey_for_JsonWebKeyPublicParameters" - } - } - } - }, - "JsonWebKeyUse": { - "description": "JSON Web Key Use", - "anyOf": [ - { - "description": "Digital Signature or MAC", - "const": "sig" - }, - { - "description": "Encryption", - "const": "enc" - } - ] - }, - "JsonWebKey_for_JsonWebKeyPublicParameters": { - "type": "object", - "oneOf": [ - { - "type": "object", - "required": [ - "e", - "kty", - "n" - ], - "properties": { - "e": { - "type": "string" - }, - "kty": { - "type": "string", - "enum": [ - "RSA" - ] - }, - "n": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "crv", - "kty", - "x", - "y" - ], - "properties": { - "crv": { - "$ref": "#/definitions/JsonWebKeyEcEllipticCurve" - }, - "kty": { - "type": "string", - "enum": [ - "EC" - ] - }, - "x": { - "type": "string" - }, - "y": { - "type": "string" - } - } - }, - { - "type": "object", - "required": [ - "crv", - "kty", - "x" - ], - "properties": { - "crv": { - "$ref": "#/definitions/JsonWebKeyOkpEllipticCurve" - }, - "kty": { - "type": "string", - "enum": [ - "OKP" - ] - }, - "x": { - "type": "string" - } - } - } - ], - "properties": { - "alg": { - "$ref": "#/definitions/JsonWebSignatureAlg" - }, - "key_ops": { - "type": "array", - "items": { - "$ref": "#/definitions/JsonWebKeyOperation" - } - }, - "kid": { - "type": "string" - }, - "use": { - "$ref": "#/definitions/JsonWebKeyUse" - }, - "x5c": { - "type": "array", - "items": { - "type": "string" - } - }, - "x5t": { - "type": "string" - }, - "x5t#S256": { - "type": "string" - }, - "x5u": { - "type": "string" - } - } - }, "JsonWebSignatureAlg": { "description": "JSON Web Signature \"alg\" parameter", "anyOf": [ @@ -1323,40 +614,87 @@ } ] }, - "KeyConfig": { - "type": "object", - "oneOf": [ + "JsonWebKeyEcEllipticCurve": { + "description": "JSON Web Key EC Elliptic Curve", + "anyOf": [ { - "type": "object", - "required": [ - "password" - ], - "properties": { - "password": { - "type": "string" - } - }, - "additionalProperties": false + "description": "P-256 Curve", + "const": "P-256" }, { - "type": "object", - "required": [ - "password_file" - ], - "properties": { - "password_file": { - "type": "string" - } - }, - "additionalProperties": false + "description": "P-384 Curve", + "const": "P-384" + }, + { + "description": "P-521 Curve", + "const": "P-521" + }, + { + "description": "SECG secp256k1 curve", + "const": "secp256k1" } - ], + ] + }, + "JsonWebKeyOkpEllipticCurve": { + "description": "JSON Web Key OKP Elliptic Curve", + "anyOf": [ + { + "description": "Ed25519 signature algorithm key pairs", + "const": "Ed25519" + }, + { + "description": "Ed448 signature algorithm key pairs", + "const": "Ed448" + }, + { + "description": "X25519 function key pairs", + "const": "X25519" + }, + { + "description": "X448 function key pairs", + "const": "X448" + } + ] + }, + "HttpConfig": { + "description": "Configuration related to the web server", + "type": "object", "required": [ - "kid" + "public_base" ], "properties": { - "kid": { - "type": "string" + "listeners": { + "description": "List of listeners to run", + "default": [], + "type": "array", + "items": { + "$ref": "#/definitions/ListenerConfig" + } + }, + "trusted_proxies": { + "description": "List of trusted reverse proxies that can set the `X-Forwarded-For` header", + "default": [ + "192.128.0.0/16", + "172.16.0.0/12", + "10.0.0.0/10", + "127.0.0.1/8", + "fd00::/8", + "::1/128" + ], + "type": "array", + "items": { + "$ref": "#/definitions/IpNetwork" + } + }, + "public_base": { + "description": "Public URL base from where the authentication service is reachable", + "type": "string", + "format": "uri" + }, + "issuer": { + "description": "OIDC issuer URL. Defaults to `public_base` if not set.", + "type": "string", + "format": "uri" } } }, @@ -1368,26 +706,10 @@ "resources" ], "properties": { - "binds": { - "description": "List of sockets to bind", - "type": "array", - "items": { - "$ref": "#/definitions/BindConfig" - } - }, "name": { "description": "A unique name for this listener which will be shown in traces and in metrics labels", "type": "string" }, - "prefix": { - "description": "HTTP prefix to mount the resources on", - "type": "string" - }, - "proxy_protocol": { - "description": "Accept HAProxy's Proxy Protocol V1", - "default": false, - "type": "boolean" - }, "resources": { "description": "List of resources to mount", "type": "array", @@ -1395,6 +717,22 @@ "$ref": "#/definitions/Resource" } }, + "prefix": { + "description": "HTTP prefix to mount the resources on", + "type": "string" + }, + "binds": { + "description": "List of sockets to bind", + "type": "array", + "items": { + "$ref": "#/definitions/BindConfig" + } + }, + "proxy_protocol": { + "description": "Accept HAProxy's Proxy Protocol V1", + "default": false, + "type": "boolean" + }, "tls": { "description": "If set, makes the listener use TLS with the provided certificate and key", "allOf": [ @@ -1405,444 +743,6 @@ } } }, - "LocalpartImportPreference": { - "description": "What should be done for the localpart attribute", - "type": "object", - "properties": { - "action": { - "description": "How to handle the attribute", - "default": "ignore", - "allOf": [ - { - "$ref": "#/definitions/ImportAction" - } - ] - }, - "template": { - "description": "The Jinja2 template to use for the localpart attribute\n\nIf not provided, the default template is `{{ user.preferred_username }}`", - "default": null, - "type": "string" - } - } - }, - "MatrixConfig": { - "description": "Configuration related to the Matrix homeserver", - "type": "object", - "required": [ - "secret" - ], - "properties": { - "endpoint": { - "description": "The base URL of the homeserver's client API", - "default": "http://localhost:8008/", - "type": "string", - "format": "uri" - }, - "homeserver": { - "description": "The server name of the homeserver.", - "default": "localhost:8008", - "type": "string" - }, - "secret": { - "description": "Shared secret to use for calls to the admin API", - "type": "string" - } - } - }, - "MetricsConfig": { - "description": "Configuration related to exporting metrics", - "type": "object", - "oneOf": [ - { - "description": "Don't export metrics", - "type": "object", - "required": [ - "exporter" - ], - "properties": { - "exporter": { - "type": "string", - "enum": [ - "none" - ] - } - } - }, - { - "description": "Export metrics to stdout. Only useful for debugging", - "type": "object", - "required": [ - "exporter" - ], - "properties": { - "exporter": { - "type": "string", - "enum": [ - "stdout" - ] - } - } - }, - { - "description": "Export metrics to an OpenTelemetry protocol compatible endpoint", - "type": "object", - "required": [ - "exporter" - ], - "properties": { - "endpoint": { - "description": "OTLP compatible endpoint", - "examples": [ - "https://localhost:4317" - ], - "type": "string", - "format": "uri" - }, - "exporter": { - "type": "string", - "enum": [ - "otlp" - ] - } - } - }, - { - "description": "Export metrics via Prometheus. An HTTP listener with the `prometheus` resource must be setup to expose the Promethes metrics.", - "type": "object", - "required": [ - "exporter" - ], - "properties": { - "exporter": { - "type": "string", - "enum": [ - "prometheus" - ] - } - } - } - ] - }, - "PasswordsConfig": { - "description": "User password hashing config", - "type": "object", - "properties": { - "enabled": { - "description": "Whether password-based authentication is enabled", - "default": true, - "type": "boolean" - }, - "schemes": { - "default": [ - { - "version": 1, - "algorithm": "argon2id" - } - ], - "type": "array", - "items": { - "$ref": "#/definitions/HashingScheme" - } - } - } - }, - "PkceMethod": { - "description": "Whether to use proof key for code exchange (PKCE) when requesting and exchanging the token.", - "oneOf": [ - { - "description": "Use PKCE if the provider supports it\n\nDefaults to no PKCE if provider discovery is disabled", - "type": "string", - "enum": [ - "auto" - ] - }, - { - "description": "Always use PKCE with the S256 challenge method", - "type": "string", - "enum": [ - "always" - ] - }, - { - "description": "Never use PKCE", - "type": "string", - "enum": [ - "never" - ] - } - ] - }, - "PolicyConfig": { - "description": "Application secrets", - "type": "object", - "properties": { - "authorization_grant_entrypoint": { - "description": "Entrypoint to use when evaluating authorization grants", - "default": "authorization_grant/violation", - "type": "string" - }, - "client_registration_entrypoint": { - "description": "Entrypoint to use when evaluating client registrations", - "default": "client_registration/violation", - "type": "string" - }, - "data": { - "description": "Arbitrary data to pass to the policy", - "default": null - }, - "email_entrypoint": { - "description": "Entrypoint to use when adding an email address", - "default": "email/violation", - "type": "string" - }, - "password_entrypoint": { - "description": "Entrypoint to use when changing password", - "default": "password/violation", - "type": "string" - }, - "register_entrypoint": { - "description": "Entrypoint to use when evaluating user registrations", - "default": "register/violation", - "type": "string" - }, - "wasm_module": { - "description": "Path to the WASM module", - "default": "./policies/policy.wasm", - "type": "string" - } - } - }, - "Propagator": { - "description": "Propagation format for incoming and outgoing requests", - "oneOf": [ - { - "description": "Propagate according to the W3C Trace Context specification", - "type": "string", - "enum": [ - "tracecontext" - ] - }, - { - "description": "Propagate according to the W3C Baggage specification", - "type": "string", - "enum": [ - "baggage" - ] - }, - { - "description": "Propagate trace context with Jaeger compatible headers", - "type": "string", - "enum": [ - "jaeger" - ] - }, - { - "description": "Propagate trace context with Zipkin compatible headers (single `b3` header variant)", - "type": "string", - "enum": [ - "b3" - ] - }, - { - "description": "Propagate trace context with Zipkin compatible headers (multiple `x-b3-*` headers variant)", - "type": "string", - "enum": [ - "b3multi" - ] - } - ] - }, - "Provider": { - "description": "Authentication methods used against the OAuth 2.0 provider", - "type": "object", - "oneOf": [ - { - "description": "`none`: No authentication", - "type": "object", - "required": [ - "token_endpoint_auth_method" - ], - "properties": { - "token_endpoint_auth_method": { - "type": "string", - "enum": [ - "none" - ] - } - } - }, - { - "description": "`client_secret_basic`: `client_id` and `client_secret` used as basic authorization credentials", - "type": "object", - "required": [ - "client_secret", - "token_endpoint_auth_method" - ], - "properties": { - "client_secret": { - "type": "string" - }, - "token_endpoint_auth_method": { - "type": "string", - "enum": [ - "client_secret_basic" - ] - } - } - }, - { - "description": "`client_secret_post`: `client_id` and `client_secret` sent in the request body", - "type": "object", - "required": [ - "client_secret", - "token_endpoint_auth_method" - ], - "properties": { - "client_secret": { - "type": "string" - }, - "token_endpoint_auth_method": { - "type": "string", - "enum": [ - "client_secret_post" - ] - } - } - }, - { - "description": "`client_secret_basic`: a `client_assertion` sent in the request body and signed using the `client_secret`", - "type": "object", - "required": [ - "client_secret", - "token_endpoint_auth_method" - ], - "properties": { - "client_secret": { - "type": "string" - }, - "token_endpoint_auth_method": { - "type": "string", - "enum": [ - "client_secret_jwt" - ] - }, - "token_endpoint_auth_signing_alg": { - "$ref": "#/definitions/JsonWebSignatureAlg" - } - } - }, - { - "description": "`client_secret_basic`: a `client_assertion` sent in the request body and signed by an asymmetric key", - "type": "object", - "required": [ - "token_endpoint_auth_method" - ], - "properties": { - "token_endpoint_auth_method": { - "type": "string", - "enum": [ - "private_key_jwt" - ] - }, - "token_endpoint_auth_signing_alg": { - "$ref": "#/definitions/JsonWebSignatureAlg" - } - } - } - ], - "required": [ - "client_id", - "id", - "issuer", - "scope" - ], - "properties": { - "authorization_endpoint": { - "description": "The URL to use for the provider's authorization endpoint\n\nDefaults to the `authorization_endpoint` provided through discovery", - "type": "string", - "format": "uri" - }, - "brand_name": { - "description": "A brand identifier used to customise the UI, e.g. `apple`, `google`, `github`, etc.\n\nValues supported by the default template are:\n\n- `apple` - `google` - `facebook` - `github` - `gitlab` - `twitter`", - "type": "string" - }, - "claims_imports": { - "description": "How claims should be imported from the `id_token` provided by the provider", - "default": { - "subject": { - "template": null - }, - "localpart": { - "action": "ignore", - "template": null - }, - "displayname": { - "action": "ignore", - "template": null - }, - "email": { - "action": "ignore", - "template": null, - "set_email_verification": "import" - } - }, - "allOf": [ - { - "$ref": "#/definitions/ClaimsImports" - } - ] - }, - "client_id": { - "description": "The client ID to use when authenticating with the provider", - "type": "string" - }, - "discovery_mode": { - "description": "How to discover the provider's configuration\n\nDefaults to use OIDC discovery with strict metadata verification", - "default": "oidc", - "allOf": [ - { - "$ref": "#/definitions/DiscoveryMode" - } - ] - }, - "human_name": { - "description": "A human-readable name for the provider, that will be shown to users", - "type": "string" - }, - "id": { - "description": "A ULID as per https://github.com/ulid/spec", - "type": "string", - "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$" - }, - "issuer": { - "description": "The OIDC issuer URL", - "type": "string" - }, - "jwks_uri": { - "description": "The URL to use for getting the provider's public keys\n\nDefaults to the `jwks_uri` provided through discovery", - "type": "string", - "format": "uri" - }, - "pkce_method": { - "description": "Whether to use proof key for code exchange (PKCE) when requesting and exchanging the token.\n\nDefaults to `auto`, which uses PKCE if the provider supports it.", - "default": "auto", - "allOf": [ - { - "$ref": "#/definitions/PkceMethod" - } - ] - }, - "scope": { - "description": "The scopes to request from the provider", - "type": "string" - }, - "token_endpoint": { - "description": "The URL to use for the provider's token endpoint\n\nDefaults to the `token_endpoint` provided through discovery", - "type": "string", - "format": "uri" - } - } - }, "Resource": { "description": "HTTP resources to mount", "oneOf": [ @@ -2009,143 +909,102 @@ } ] }, - "SecretsConfig": { - "description": "Application secrets", - "type": "object", - "required": [ - "encryption" - ], - "properties": { - "encryption": { - "description": "Encryption key for secure cookies", - "examples": [ - "0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff" + "BindConfig": { + "description": "Configuration of a single listener", + "anyOf": [ + { + "description": "Listen on the specified host and port", + "type": "object", + "required": [ + "port" ], - "type": "string", - "pattern": "[0-9a-fA-F]{64}" - }, - "keys": { - "description": "List of private keys to use for signing and encrypting payloads", - "default": [], - "type": "array", - "items": { - "$ref": "#/definitions/KeyConfig" + "properties": { + "host": { + "description": "Host on which to listen.\n\nDefaults to listening on all addresses", + "type": "string" + }, + "port": { + "description": "Port on which to listen.", + "type": "integer", + "format": "uint16", + "minimum": 0.0 + } } - } - } - }, - "SentryConfig": { - "description": "Configuration related to the Sentry integration", - "type": "object", - "properties": { - "dsn": { - "description": "Sentry DSN", - "default": null, - "examples": [ - "https://public@host:port/1" + }, + { + "description": "Listen on the specified address", + "type": "object", + "required": [ + "address" ], - "type": "string", - "format": "uri" - } - } - }, - "SetEmailVerification": { - "description": "Should the email address be marked as verified", - "oneOf": [ - { - "description": "Mark the email address as verified", - "type": "string", - "enum": [ - "always" - ] + "properties": { + "address": { + "description": "Host and port on which to listen", + "examples": [ + "[::1]:8080", + "[::]:8080", + "127.0.0.1:8080", + "0.0.0.0:8080" + ], + "type": "string" + } + } }, { - "description": "Don't mark the email address as verified", - "type": "string", - "enum": [ - "never" - ] + "description": "Listen on a UNIX domain socket", + "type": "object", + "required": [ + "socket" + ], + "properties": { + "socket": { + "description": "Path to the socket", + "type": "string" + } + } }, { - "description": "Mark the email address as verified if the upstream provider says it is through the `email_verified` claim", - "type": "string", - "enum": [ - "import" - ] + "description": "Accept connections on file descriptors passed by the parent process.\n\nThis is useful for grabbing sockets passed by systemd.\n\nSee ", + "type": "object", + "properties": { + "fd": { + "description": "Index of the file descriptor. Note that this is offseted by 3 because of the standard input/output sockets, so setting here a value of `0` will grab the file descriptor `3`", + "default": 0, + "type": "integer", + "format": "uint", + "minimum": 0.0 + }, + "kind": { + "description": "Whether the socket is a TCP socket or a UNIX domain socket. Defaults to TCP.", + "default": "tcp", + "allOf": [ + { + "$ref": "#/definitions/UnixOrTcp" + } + ] + } + } } ] }, - "SubjectImportPreference": { - "description": "What should be done for the subject attribute", - "type": "object", - "properties": { - "template": { - "description": "The Jinja2 template to use for the subject attribute\n\nIf not provided, the default template is `{{ user.sub }}`", - "default": null, - "type": "string" - } - } - }, - "TelemetryConfig": { - "description": "Configuration related to sending monitoring data", - "type": "object", - "properties": { - "metrics": { - "description": "Configuration related to exporting metrics", - "default": { - "exporter": "none" - }, - "allOf": [ - { - "$ref": "#/definitions/MetricsConfig" - } + "UnixOrTcp": { + "description": "Kind of socket", + "oneOf": [ + { + "description": "UNIX domain socket", + "type": "string", + "enum": [ + "unix" ] }, - "sentry": { - "description": "Configuration related to the Sentry integration", - "default": { - "dsn": null - }, - "allOf": [ - { - "$ref": "#/definitions/SentryConfig" - } - ] - }, - "tracing": { - "description": "Configuration related to exporting traces", - "default": { - "exporter": "none", - "propagators": [] - }, - "allOf": [ - { - "$ref": "#/definitions/TracingConfig" - } + { + "description": "TCP socket", + "type": "string", + "enum": [ + "tcp" ] } - } - }, - "TemplatesConfig": { - "description": "Configuration related to templates", - "type": "object", - "properties": { - "assets_manifest": { - "description": "Path to the assets manifest", - "default": "./frontend/dist/manifest.json", - "type": "string" - }, - "path": { - "description": "Path to the folder which holds the templates", - "default": "./templates/", - "type": "string" - }, - "translations_path": { - "description": "Path to the translations", - "default": "./translations/", - "type": "string" - } - } + ] }, "TlsConfig": { "description": "Configuration related to TLS on a listener", @@ -2177,6 +1036,171 @@ } ] }, + "IpNetwork": { + "oneOf": [ + { + "title": "v4", + "allOf": [ + { + "$ref": "#/definitions/Ipv4Network" + } + ] + }, + { + "title": "v6", + "allOf": [ + { + "$ref": "#/definitions/Ipv6Network" + } + ] + } + ], + "x-rust-type": "ipnetwork::IpNetwork" + }, + "Ipv4Network": { + "type": "string", + "pattern": "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\/(3[0-2]|[0-2]?[0-9])$", + "x-rust-type": "ipnetwork::Ipv4Network" + }, + "Ipv6Network": { + "type": "string", + "pattern": "^(([0-9a-fA-F]{1,4}:){7,7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:)|fe80:(:[0-9a-fA-F]{0,4}){0,4}%[0-9a-zA-Z]{1,}|::(ffff(:0{1,4}){0,1}:){0,1}((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])|([0-9a-fA-F]{1,4}:){1,4}:((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\")[/](12[0-8]|1[0-1][0-9]|[0-9]?[0-9])$", + "x-rust-type": "ipnetwork::Ipv6Network" + }, + "DatabaseConfig": { + "description": "Database connection configuration", + "type": "object", + "anyOf": [ + { + "description": "Connect via a full URI", + "type": "object", + "properties": { + "uri": { + "description": "Connection URI", + "default": "postgresql://", + "type": "string", + "format": "uri" + } + } + }, + { + "description": "Connect via a map of options", + "type": "object", + "properties": { + "host": { + "description": "Name of host to connect to", + "default": null, + "type": "string", + "format": "hostname" + }, + "port": { + "description": "Port number to connect at the server host", + "default": null, + "type": "integer", + "maximum": 65535.0, + "minimum": 1.0 + }, + "socket": { + "description": "Directory containing the UNIX socket to connect to", + "default": null, + "type": "string" + }, + "username": { + "description": "PostgreSQL user name to connect as", + "default": null, + "type": "string" + }, + "password": { + "description": "Password to be used if the server demands password authentication", + "default": null, + "type": "string" + }, + "database": { + "description": "The database name", + "default": null, + "type": "string" + } + } + } + ], + "properties": { + "max_connections": { + "description": "Set the maximum number of connections the pool should maintain", + "default": 10, + "type": "integer", + "format": "uint32", + "minimum": 1.0 + }, + "min_connections": { + "description": "Set the minimum number of connections the pool should maintain", + "default": 0, + "type": "integer", + "format": "uint32", + "minimum": 0.0 + }, + "connect_timeout": { + "description": "Set the amount of time to attempt connecting to the database", + "default": 30, + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "idle_timeout": { + "description": "Set a maximum idle duration for individual connections", + "default": 600, + "type": "integer", + "format": "uint64", + "minimum": 0.0 + }, + "max_lifetime": { + "description": "Set the maximum lifetime of individual connections", + "default": 1800, + "type": "integer", + "format": "uint64", + "minimum": 0.0 + } + } + }, + "TelemetryConfig": { + "description": "Configuration related to sending monitoring data", + "type": "object", + "properties": { + "tracing": { + "description": "Configuration related to exporting traces", + "default": { + "exporter": "none", + "propagators": [] + }, + "allOf": [ + { + "$ref": "#/definitions/TracingConfig" + } + ] + }, + "metrics": { + "description": "Configuration related to exporting metrics", + "default": { + "exporter": "none" + }, + "allOf": [ + { + "$ref": "#/definitions/MetricsConfig" + } + ] + }, + "sentry": { + "description": "Configuration related to the Sentry integration", + "default": { + "dsn": null + }, + "allOf": [ + { + "$ref": "#/definitions/SentryConfig" + } + ] + } + } + }, "TracingConfig": { "description": "Configuration related to exporting traces", "type": "object", @@ -2220,6 +1244,12 @@ "exporter" ], "properties": { + "exporter": { + "type": "string", + "enum": [ + "otlp" + ] + }, "endpoint": { "description": "OTLP compatible endpoint", "examples": [ @@ -2227,12 +1257,6 @@ ], "type": "string", "format": "uri" - }, - "exporter": { - "type": "string", - "enum": [ - "otlp" - ] } }, "additionalProperties": false @@ -2249,23 +1273,23 @@ "protocol" ], "properties": { - "endpoint": { - "description": "Full URL of the Jaeger HTTP endpoint\n\nDefaults to `http://localhost:14268/api/traces`", - "type": "string" - }, - "password": { - "description": "Password to be used for HTTP basic authentication", - "type": "string" - }, "protocol": { "type": "string", "enum": [ "http/thrift.binary" ] }, + "endpoint": { + "description": "Full URL of the Jaeger HTTP endpoint\n\nDefaults to `http://localhost:14268/api/traces`", + "type": "string" + }, "username": { "description": "Username to be used for HTTP basic authentication", "type": "string" + }, + "password": { + "description": "Password to be used for HTTP basic authentication", + "type": "string" } } }, @@ -2278,6 +1302,12 @@ "protocol" ], "properties": { + "protocol": { + "type": "string", + "enum": [ + "udp/thrift.compact" + ] + }, "agent_host": { "description": "Hostname of the Jaeger agent\n\nDefaults to `localhost`", "type": "string" @@ -2287,12 +1317,6 @@ "type": "integer", "format": "uint16", "minimum": 0.0 - }, - "protocol": { - "type": "string", - "enum": [ - "udp/thrift.compact" - ] } } } @@ -2317,6 +1341,12 @@ "exporter" ], "properties": { + "exporter": { + "type": "string", + "enum": [ + "zipkin" + ] + }, "collector_endpoint": { "description": "Zipkin collector endpoint", "examples": [ @@ -2324,12 +1354,6 @@ ], "type": "string", "format": "uri" - }, - "exporter": { - "type": "string", - "enum": [ - "zipkin" - ] } }, "additionalProperties": false @@ -2348,25 +1372,514 @@ } } }, - "UnixOrTcp": { - "description": "Kind of socket", + "Propagator": { + "description": "Propagation format for incoming and outgoing requests", "oneOf": [ { - "description": "UNIX domain socket", + "description": "Propagate according to the W3C Trace Context specification", "type": "string", "enum": [ - "unix" + "tracecontext" ] }, { - "description": "TCP socket", + "description": "Propagate according to the W3C Baggage specification", "type": "string", "enum": [ - "tcp" + "baggage" + ] + }, + { + "description": "Propagate trace context with Jaeger compatible headers", + "type": "string", + "enum": [ + "jaeger" + ] + }, + { + "description": "Propagate trace context with Zipkin compatible headers (single `b3` header variant)", + "type": "string", + "enum": [ + "b3" + ] + }, + { + "description": "Propagate trace context with Zipkin compatible headers (multiple `x-b3-*` headers variant)", + "type": "string", + "enum": [ + "b3multi" ] } ] }, + "MetricsConfig": { + "description": "Configuration related to exporting metrics", + "type": "object", + "oneOf": [ + { + "description": "Don't export metrics", + "type": "object", + "required": [ + "exporter" + ], + "properties": { + "exporter": { + "type": "string", + "enum": [ + "none" + ] + } + } + }, + { + "description": "Export metrics to stdout. Only useful for debugging", + "type": "object", + "required": [ + "exporter" + ], + "properties": { + "exporter": { + "type": "string", + "enum": [ + "stdout" + ] + } + } + }, + { + "description": "Export metrics to an OpenTelemetry protocol compatible endpoint", + "type": "object", + "required": [ + "exporter" + ], + "properties": { + "exporter": { + "type": "string", + "enum": [ + "otlp" + ] + }, + "endpoint": { + "description": "OTLP compatible endpoint", + "examples": [ + "https://localhost:4317" + ], + "type": "string", + "format": "uri" + } + } + }, + { + "description": "Export metrics via Prometheus. An HTTP listener with the `prometheus` resource must be setup to expose the Promethes metrics.", + "type": "object", + "required": [ + "exporter" + ], + "properties": { + "exporter": { + "type": "string", + "enum": [ + "prometheus" + ] + } + } + } + ] + }, + "SentryConfig": { + "description": "Configuration related to the Sentry integration", + "type": "object", + "properties": { + "dsn": { + "description": "Sentry DSN", + "default": null, + "examples": [ + "https://public@host:port/1" + ], + "type": "string", + "format": "uri" + } + } + }, + "TemplatesConfig": { + "description": "Configuration related to templates", + "type": "object", + "properties": { + "path": { + "description": "Path to the folder which holds the templates", + "default": "./templates/", + "type": "string" + }, + "assets_manifest": { + "description": "Path to the assets manifest", + "default": "./frontend/dist/manifest.json", + "type": "string" + }, + "translations_path": { + "description": "Path to the translations", + "default": "./translations/", + "type": "string" + } + } + }, + "EmailConfig": { + "description": "Configuration related to sending emails", + "type": "object", + "oneOf": [ + { + "description": "Don't send emails anywhere", + "type": "object", + "required": [ + "transport" + ], + "properties": { + "transport": { + "type": "string", + "enum": [ + "blackhole" + ] + } + } + }, + { + "description": "Send emails via an SMTP relay", + "type": "object", + "required": [ + "hostname", + "mode", + "transport" + ], + "properties": { + "transport": { + "type": "string", + "enum": [ + "smtp" + ] + }, + "mode": { + "description": "Connection mode to the relay", + "allOf": [ + { + "$ref": "#/definitions/EmailSmtpMode" + } + ] + }, + "hostname": { + "description": "Hostname to connect to", + "type": "string", + "format": "hostname" + }, + "port": { + "description": "Port to connect to. Default is 25 for plain, 465 for TLS and 587 for StartTLS", + "type": "integer", + "format": "uint16", + "minimum": 1.0 + }, + "username": { + "description": "Username for use to authenticate when connecting to the SMTP server", + "type": "string" + }, + "password": { + "description": "Password for use to authenticate when connecting to the SMTP server", + "type": "string" + } + } + }, + { + "description": "Send emails by calling sendmail", + "type": "object", + "required": [ + "transport" + ], + "properties": { + "transport": { + "type": "string", + "enum": [ + "sendmail" + ] + }, + "command": { + "description": "Command to execute", + "default": "sendmail", + "type": "string" + } + } + }, + { + "description": "Send emails via the AWS SESv2 API", + "deprecated": true, + "type": "object", + "required": [ + "transport" + ], + "properties": { + "transport": { + "type": "string", + "enum": [ + "aws_ses" + ] + } + } + } + ], + "properties": { + "from": { + "description": "Email address to use as From when sending emails", + "default": "\"Authentication Service\" ", + "type": "string", + "format": "email" + }, + "reply_to": { + "description": "Email address to use as Reply-To when sending emails", + "default": "\"Authentication Service\" ", + "type": "string", + "format": "email" + } + } + }, + "EmailSmtpMode": { + "description": "Encryption mode to use", + "oneOf": [ + { + "description": "Plain text", + "type": "string", + "enum": [ + "plain" + ] + }, + { + "description": "StartTLS (starts as plain text then upgrade to TLS)", + "type": "string", + "enum": [ + "starttls" + ] + }, + { + "description": "TLS", + "type": "string", + "enum": [ + "tls" + ] + } + ] + }, + "SecretsConfig": { + "description": "Application secrets", + "type": "object", + "required": [ + "encryption" + ], + "properties": { + "encryption": { + "description": "Encryption key for secure cookies", + "examples": [ + "0000111122223333444455556666777788889999aaaabbbbccccddddeeeeffff" + ], + "type": "string", + "pattern": "[0-9a-fA-F]{64}" + }, + "keys": { + "description": "List of private keys to use for signing and encrypting payloads", + "default": [], + "type": "array", + "items": { + "$ref": "#/definitions/KeyConfig" + } + } + } + }, + "KeyConfig": { + "type": "object", + "oneOf": [ + { + "type": "object", + "required": [ + "password" + ], + "properties": { + "password": { + "type": "string" + } + }, + "additionalProperties": false + }, + { + "type": "object", + "required": [ + "password_file" + ], + "properties": { + "password_file": { + "type": "string" + } + }, + "additionalProperties": false + } + ], + "required": [ + "kid" + ], + "properties": { + "kid": { + "type": "string" + } + } + }, + "PasswordsConfig": { + "description": "User password hashing config", + "type": "object", + "properties": { + "enabled": { + "description": "Whether password-based authentication is enabled", + "default": true, + "type": "boolean" + }, + "schemes": { + "default": [ + { + "version": 1, + "algorithm": "argon2id" + } + ], + "type": "array", + "items": { + "$ref": "#/definitions/HashingScheme" + } + } + } + }, + "HashingScheme": { + "description": "A hashing algorithm", + "type": "object", + "oneOf": [ + { + "description": "bcrypt", + "type": "object", + "required": [ + "algorithm" + ], + "properties": { + "algorithm": { + "type": "string", + "enum": [ + "bcrypt" + ] + }, + "cost": { + "description": "Hashing cost", + "default": 12, + "type": "integer", + "format": "uint32", + "minimum": 0.0 + } + } + }, + { + "description": "argon2id", + "type": "object", + "required": [ + "algorithm" + ], + "properties": { + "algorithm": { + "type": "string", + "enum": [ + "argon2id" + ] + } + } + }, + { + "description": "PBKDF2", + "type": "object", + "required": [ + "algorithm" + ], + "properties": { + "algorithm": { + "type": "string", + "enum": [ + "pbkdf2" + ] + } + } + } + ], + "required": [ + "version" + ], + "properties": { + "version": { + "type": "integer", + "format": "uint16", + "minimum": 0.0 + } + } + }, + "MatrixConfig": { + "description": "Configuration related to the Matrix homeserver", + "type": "object", + "required": [ + "secret" + ], + "properties": { + "homeserver": { + "description": "The server name of the homeserver.", + "default": "localhost:8008", + "type": "string" + }, + "secret": { + "description": "Shared secret to use for calls to the admin API", + "type": "string" + }, + "endpoint": { + "description": "The base URL of the homeserver's client API", + "default": "http://localhost:8008/", + "type": "string", + "format": "uri" + } + } + }, + "PolicyConfig": { + "description": "Application secrets", + "type": "object", + "properties": { + "wasm_module": { + "description": "Path to the WASM module", + "default": "./policies/policy.wasm", + "type": "string" + }, + "client_registration_entrypoint": { + "description": "Entrypoint to use when evaluating client registrations", + "default": "client_registration/violation", + "type": "string" + }, + "register_entrypoint": { + "description": "Entrypoint to use when evaluating user registrations", + "default": "register/violation", + "type": "string" + }, + "authorization_grant_entrypoint": { + "description": "Entrypoint to use when evaluating authorization grants", + "default": "authorization_grant/violation", + "type": "string" + }, + "password_entrypoint": { + "description": "Entrypoint to use when changing password", + "default": "password/violation", + "type": "string" + }, + "email_entrypoint": { + "description": "Entrypoint to use when adding an email address", + "default": "email/violation", + "type": "string" + }, + "data": { + "description": "Arbitrary data to pass to the policy", + "default": null + } + } + }, "UpstreamOAuth2Config": { "description": "Upstream OAuth 2.0 providers configuration", "type": "object", @@ -2382,6 +1895,493 @@ } } } + }, + "Provider": { + "description": "Authentication methods used against the OAuth 2.0 provider", + "type": "object", + "oneOf": [ + { + "description": "`none`: No authentication", + "type": "object", + "required": [ + "token_endpoint_auth_method" + ], + "properties": { + "token_endpoint_auth_method": { + "type": "string", + "enum": [ + "none" + ] + } + } + }, + { + "description": "`client_secret_basic`: `client_id` and `client_secret` used as basic authorization credentials", + "type": "object", + "required": [ + "client_secret", + "token_endpoint_auth_method" + ], + "properties": { + "token_endpoint_auth_method": { + "type": "string", + "enum": [ + "client_secret_basic" + ] + }, + "client_secret": { + "type": "string" + } + } + }, + { + "description": "`client_secret_post`: `client_id` and `client_secret` sent in the request body", + "type": "object", + "required": [ + "client_secret", + "token_endpoint_auth_method" + ], + "properties": { + "token_endpoint_auth_method": { + "type": "string", + "enum": [ + "client_secret_post" + ] + }, + "client_secret": { + "type": "string" + } + } + }, + { + "description": "`client_secret_basic`: a `client_assertion` sent in the request body and signed using the `client_secret`", + "type": "object", + "required": [ + "client_secret", + "token_endpoint_auth_method" + ], + "properties": { + "token_endpoint_auth_method": { + "type": "string", + "enum": [ + "client_secret_jwt" + ] + }, + "client_secret": { + "type": "string" + }, + "token_endpoint_auth_signing_alg": { + "$ref": "#/definitions/JsonWebSignatureAlg" + } + } + }, + { + "description": "`client_secret_basic`: a `client_assertion` sent in the request body and signed by an asymmetric key", + "type": "object", + "required": [ + "token_endpoint_auth_method" + ], + "properties": { + "token_endpoint_auth_method": { + "type": "string", + "enum": [ + "private_key_jwt" + ] + }, + "token_endpoint_auth_signing_alg": { + "$ref": "#/definitions/JsonWebSignatureAlg" + } + } + } + ], + "required": [ + "client_id", + "id", + "issuer", + "scope" + ], + "properties": { + "id": { + "description": "A ULID as per https://github.com/ulid/spec", + "type": "string", + "pattern": "^[0123456789ABCDEFGHJKMNPQRSTVWXYZ]{26}$" + }, + "issuer": { + "description": "The OIDC issuer URL", + "type": "string" + }, + "human_name": { + "description": "A human-readable name for the provider, that will be shown to users", + "type": "string" + }, + "brand_name": { + "description": "A brand identifier used to customise the UI, e.g. `apple`, `google`, `github`, etc.\n\nValues supported by the default template are:\n\n- `apple` - `google` - `facebook` - `github` - `gitlab` - `twitter`", + "type": "string" + }, + "client_id": { + "description": "The client ID to use when authenticating with the provider", + "type": "string" + }, + "scope": { + "description": "The scopes to request from the provider", + "type": "string" + }, + "discovery_mode": { + "description": "How to discover the provider's configuration\n\nDefaults to use OIDC discovery with strict metadata verification", + "default": "oidc", + "allOf": [ + { + "$ref": "#/definitions/DiscoveryMode" + } + ] + }, + "pkce_method": { + "description": "Whether to use proof key for code exchange (PKCE) when requesting and exchanging the token.\n\nDefaults to `auto`, which uses PKCE if the provider supports it.", + "default": "auto", + "allOf": [ + { + "$ref": "#/definitions/PkceMethod" + } + ] + }, + "authorization_endpoint": { + "description": "The URL to use for the provider's authorization endpoint\n\nDefaults to the `authorization_endpoint` provided through discovery", + "type": "string", + "format": "uri" + }, + "token_endpoint": { + "description": "The URL to use for the provider's token endpoint\n\nDefaults to the `token_endpoint` provided through discovery", + "type": "string", + "format": "uri" + }, + "jwks_uri": { + "description": "The URL to use for getting the provider's public keys\n\nDefaults to the `jwks_uri` provided through discovery", + "type": "string", + "format": "uri" + }, + "claims_imports": { + "description": "How claims should be imported from the `id_token` provided by the provider", + "default": { + "subject": { + "template": null + }, + "localpart": { + "action": "ignore", + "template": null + }, + "displayname": { + "action": "ignore", + "template": null + }, + "email": { + "action": "ignore", + "template": null, + "set_email_verification": "import" + } + }, + "allOf": [ + { + "$ref": "#/definitions/ClaimsImports" + } + ] + } + } + }, + "DiscoveryMode": { + "description": "How to discover the provider's configuration", + "oneOf": [ + { + "description": "Use OIDC discovery with strict metadata verification", + "type": "string", + "enum": [ + "oidc" + ] + }, + { + "description": "Use OIDC discovery with relaxed metadata verification", + "type": "string", + "enum": [ + "insecure" + ] + }, + { + "description": "Use a static configuration", + "type": "string", + "enum": [ + "disabled" + ] + } + ] + }, + "PkceMethod": { + "description": "Whether to use proof key for code exchange (PKCE) when requesting and exchanging the token.", + "oneOf": [ + { + "description": "Use PKCE if the provider supports it\n\nDefaults to no PKCE if provider discovery is disabled", + "type": "string", + "enum": [ + "auto" + ] + }, + { + "description": "Always use PKCE with the S256 challenge method", + "type": "string", + "enum": [ + "always" + ] + }, + { + "description": "Never use PKCE", + "type": "string", + "enum": [ + "never" + ] + } + ] + }, + "ClaimsImports": { + "description": "How claims should be imported", + "type": "object", + "properties": { + "subject": { + "description": "How to determine the subject of the user", + "default": { + "template": null + }, + "allOf": [ + { + "$ref": "#/definitions/SubjectImportPreference" + } + ] + }, + "localpart": { + "description": "Import the localpart of the MXID", + "default": { + "action": "ignore", + "template": null + }, + "allOf": [ + { + "$ref": "#/definitions/LocalpartImportPreference" + } + ] + }, + "displayname": { + "description": "Import the displayname of the user.", + "default": { + "action": "ignore", + "template": null + }, + "allOf": [ + { + "$ref": "#/definitions/DisplaynameImportPreference" + } + ] + }, + "email": { + "description": "Import the email address of the user based on the `email` and `email_verified` claims", + "default": { + "action": "ignore", + "template": null, + "set_email_verification": "import" + }, + "allOf": [ + { + "$ref": "#/definitions/EmailImportPreference" + } + ] + } + } + }, + "SubjectImportPreference": { + "description": "What should be done for the subject attribute", + "type": "object", + "properties": { + "template": { + "description": "The Jinja2 template to use for the subject attribute\n\nIf not provided, the default template is `{{ user.sub }}`", + "default": null, + "type": "string" + } + } + }, + "LocalpartImportPreference": { + "description": "What should be done for the localpart attribute", + "type": "object", + "properties": { + "action": { + "description": "How to handle the attribute", + "default": "ignore", + "allOf": [ + { + "$ref": "#/definitions/ImportAction" + } + ] + }, + "template": { + "description": "The Jinja2 template to use for the localpart attribute\n\nIf not provided, the default template is `{{ user.preferred_username }}`", + "default": null, + "type": "string" + } + } + }, + "ImportAction": { + "description": "How to handle a claim", + "oneOf": [ + { + "description": "Ignore the claim", + "type": "string", + "enum": [ + "ignore" + ] + }, + { + "description": "Suggest the claim value, but allow the user to change it", + "type": "string", + "enum": [ + "suggest" + ] + }, + { + "description": "Force the claim value, but don't fail if it is missing", + "type": "string", + "enum": [ + "force" + ] + }, + { + "description": "Force the claim value, and fail if it is missing", + "type": "string", + "enum": [ + "require" + ] + } + ] + }, + "DisplaynameImportPreference": { + "description": "What should be done for the displayname attribute", + "type": "object", + "properties": { + "action": { + "description": "How to handle the attribute", + "default": "ignore", + "allOf": [ + { + "$ref": "#/definitions/ImportAction" + } + ] + }, + "template": { + "description": "The Jinja2 template to use for the displayname attribute\n\nIf not provided, the default template is `{{ user.name }}`", + "default": null, + "type": "string" + } + } + }, + "EmailImportPreference": { + "description": "What should be done with the email attribute", + "type": "object", + "properties": { + "action": { + "description": "How to handle the claim", + "default": "ignore", + "allOf": [ + { + "$ref": "#/definitions/ImportAction" + } + ] + }, + "template": { + "description": "The Jinja2 template to use for the email address attribute\n\nIf not provided, the default template is `{{ user.email }}`", + "default": null, + "type": "string" + }, + "set_email_verification": { + "description": "Should the email address be marked as verified", + "default": "import", + "allOf": [ + { + "$ref": "#/definitions/SetEmailVerification" + } + ] + } + } + }, + "SetEmailVerification": { + "description": "Should the email address be marked as verified", + "oneOf": [ + { + "description": "Mark the email address as verified", + "type": "string", + "enum": [ + "always" + ] + }, + { + "description": "Don't mark the email address as verified", + "type": "string", + "enum": [ + "never" + ] + }, + { + "description": "Mark the email address as verified if the upstream provider says it is through the `email_verified` claim", + "type": "string", + "enum": [ + "import" + ] + } + ] + }, + "BrandingConfig": { + "description": "Configuration section for tweaking the branding of the service", + "type": "object", + "properties": { + "service_name": { + "description": "A human-readable name. Defaults to the server's address.", + "type": "string" + }, + "policy_uri": { + "description": "Link to a privacy policy, displayed in the footer of web pages and emails. It is also advertised to clients through the `op_policy_uri` OIDC provider metadata.", + "type": "string", + "format": "uri" + }, + "tos_uri": { + "description": "Link to a terms of service document, displayed in the footer of web pages and emails. It is also advertised to clients through the `op_tos_uri` OIDC provider metadata.", + "type": "string", + "format": "uri" + }, + "imprint": { + "description": "Legal imprint, displayed in the footer in the footer of web pages and emails.", + "type": "string" + }, + "logo_uri": { + "description": "Logo displayed in some web pages.", + "type": "string", + "format": "uri" + } + } + }, + "ExperimentalConfig": { + "description": "Configuration sections for experimental options\n\nDo not change these options unless you know what you are doing.", + "type": "object", + "properties": { + "access_token_ttl": { + "description": "Time-to-live of access tokens in seconds. Defaults to 5 minutes.", + "default": 300, + "type": "integer", + "format": "uint64", + "maximum": 86400.0, + "minimum": 60.0 + }, + "compat_token_ttl": { + "description": "Time-to-live of compatibility access tokens in seconds. Defaults to 5 minutes.", + "default": 300, + "type": "integer", + "format": "uint64", + "maximum": 86400.0, + "minimum": 60.0 + } + } } } } \ No newline at end of file diff --git a/policies/schema/authorization_grant_input.json b/policies/schema/authorization_grant_input.json index 21c880c4..9b2f7740 100644 --- a/policies/schema/authorization_grant_input.json +++ b/policies/schema/authorization_grant_input.json @@ -9,19 +9,19 @@ "scope" ], "properties": { + "user": { + "type": "object", + "additionalProperties": true + }, "client": { "type": "object", "additionalProperties": true }, - "grant_type": { - "$ref": "#/definitions/GrantType" - }, "scope": { "type": "string" }, - "user": { - "type": "object", - "additionalProperties": true + "grant_type": { + "$ref": "#/definitions/GrantType" } }, "definitions": { diff --git a/policies/schema/register_input.json b/policies/schema/register_input.json index db0c137a..455accfc 100644 --- a/policies/schema/register_input.json +++ b/policies/schema/register_input.json @@ -12,12 +12,6 @@ "username" ], "properties": { - "email": { - "type": "string" - }, - "password": { - "type": "string" - }, "registration_method": { "type": "string", "enum": [ @@ -26,6 +20,12 @@ }, "username": { "type": "string" + }, + "password": { + "type": "string" + }, + "email": { + "type": "string" } } }, @@ -36,9 +36,6 @@ "username" ], "properties": { - "email": { - "type": "string" - }, "registration_method": { "type": "string", "enum": [ @@ -47,6 +44,9 @@ }, "username": { "type": "string" + }, + "email": { + "type": "string" } } }