mirror of
https://github.com/warp-tech/warpgate.git
synced 2025-09-13 10:04:30 +08:00
parent
33803f1a30
commit
331af972bc
14 changed files with 597 additions and 39 deletions
26
.github/workflows/build.yml
vendored
26
.github/workflows/build.yml
vendored
|
@ -5,7 +5,7 @@ permissions:
|
||||||
on: [push, pull_request]
|
on: [push, pull_request]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
Build:
|
build:
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
include:
|
include:
|
||||||
|
@ -128,3 +128,27 @@ jobs:
|
||||||
generate_release_notes: true
|
generate_release_notes: true
|
||||||
files: dist/*
|
files: dist/*
|
||||||
token: ${{ secrets.GITHUB_TOKEN }}
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
config-schema:
|
||||||
|
name: Config schema check
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Setup
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install --no-install-recommends -y libssl-dev pkg-config
|
||||||
|
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Install tools
|
||||||
|
run: |
|
||||||
|
cargo install just
|
||||||
|
|
||||||
|
- name: Ensure there are no changes in config schema
|
||||||
|
run: |
|
||||||
|
mkdir warpgate-web/dist
|
||||||
|
just config-schema
|
||||||
|
git diff --exit-code config-schema.json
|
||||||
|
|
59
Cargo.lock
generated
59
Cargo.lock
generated
|
@ -3470,6 +3470,26 @@ dependencies = [
|
||||||
"bitflags 2.8.0",
|
"bitflags 2.8.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ref-cast"
|
||||||
|
version = "1.0.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4a0ae411dbe946a674d89546582cea4ba2bb8defac896622d6496f14c23ba5cf"
|
||||||
|
dependencies = [
|
||||||
|
"ref-cast-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ref-cast-impl"
|
||||||
|
version = "1.0.24"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1165225c21bff1f3bbce98f5a1f889949bc902d3575308cc7b0de30b4f6d27c7"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.98",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
version = "1.11.1"
|
version = "1.11.1"
|
||||||
|
@ -3972,6 +3992,31 @@ dependencies = [
|
||||||
"windows-sys 0.59.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "schemars"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f"
|
||||||
|
dependencies = [
|
||||||
|
"dyn-clone",
|
||||||
|
"ref-cast",
|
||||||
|
"schemars_derive",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "schemars_derive"
|
||||||
|
version = "0.9.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5016d94c77c6d32f0b8e08b781f7dc8a90c2007d4e77472cc2807bc10a8438fe"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"serde_derive_internals",
|
||||||
|
"syn 2.0.98",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
|
@ -4230,6 +4275,17 @@ dependencies = [
|
||||||
"syn 2.0.98",
|
"syn 2.0.98",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_derive_internals"
|
||||||
|
version = "0.29.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.98",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_json"
|
||||||
version = "1.0.138"
|
version = "1.0.138"
|
||||||
|
@ -5396,6 +5452,7 @@ dependencies = [
|
||||||
"notify",
|
"notify",
|
||||||
"rcgen",
|
"rcgen",
|
||||||
"rustls 0.23.22",
|
"rustls 0.23.22",
|
||||||
|
"schemars",
|
||||||
"sd-notify",
|
"sd-notify",
|
||||||
"sea-orm",
|
"sea-orm",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -5469,6 +5526,7 @@ dependencies = [
|
||||||
"rustls 0.23.22",
|
"rustls 0.23.22",
|
||||||
"rustls-native-certs",
|
"rustls-native-certs",
|
||||||
"rustls-pemfile 1.0.4",
|
"rustls-pemfile 1.0.4",
|
||||||
|
"schemars",
|
||||||
"sea-orm",
|
"sea-orm",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -5690,6 +5748,7 @@ dependencies = [
|
||||||
"jsonwebtoken",
|
"jsonwebtoken",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"openidconnect",
|
"openidconnect",
|
||||||
|
"schemars",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"thiserror 1.0.69",
|
"thiserror 1.0.69",
|
||||||
|
|
|
@ -46,6 +46,7 @@ poem = { version = "3.1", features = [
|
||||||
password-hash = { version = "0.4", features = ["std"] }
|
password-hash = { version = "0.4", features = ["std"] }
|
||||||
delegate = "0.13"
|
delegate = "0.13"
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
|
schemars = "0.9.0"
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
|
|
459
config-schema.json
Normal file
459
config-schema.json
Normal file
|
@ -0,0 +1,459 @@
|
||||||
|
{
|
||||||
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||||
|
"title": "WarpgateConfigStore",
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"database_url": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "sqlite:data/db"
|
||||||
|
},
|
||||||
|
"external_host": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"http": {
|
||||||
|
"$ref": "#/$defs/HttpConfig",
|
||||||
|
"default": {
|
||||||
|
"certificate": "",
|
||||||
|
"cookie_max_age": "1day",
|
||||||
|
"enable": false,
|
||||||
|
"external_port": null,
|
||||||
|
"key": "",
|
||||||
|
"listen": "[::]:8888",
|
||||||
|
"session_max_age": "30m",
|
||||||
|
"trust_x_forwarded_headers": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"log": {
|
||||||
|
"$ref": "#/$defs/LogConfig",
|
||||||
|
"default": {
|
||||||
|
"retention": "7days",
|
||||||
|
"send_to": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mysql": {
|
||||||
|
"$ref": "#/$defs/MySqlConfig",
|
||||||
|
"default": {
|
||||||
|
"certificate": "",
|
||||||
|
"enable": false,
|
||||||
|
"external_port": null,
|
||||||
|
"key": "",
|
||||||
|
"listen": "[::]:33306"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"postgres": {
|
||||||
|
"$ref": "#/$defs/PostgresConfig",
|
||||||
|
"default": {
|
||||||
|
"certificate": "",
|
||||||
|
"enable": false,
|
||||||
|
"external_port": null,
|
||||||
|
"key": "",
|
||||||
|
"listen": "[::]:55432"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"recordings": {
|
||||||
|
"$ref": "#/$defs/RecordingsConfig",
|
||||||
|
"default": {
|
||||||
|
"enable": false,
|
||||||
|
"path": "./data/recordings"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ssh": {
|
||||||
|
"$ref": "#/$defs/SshConfig",
|
||||||
|
"default": {
|
||||||
|
"enable": false,
|
||||||
|
"external_port": null,
|
||||||
|
"host_key_verification": "prompt",
|
||||||
|
"inactivity_timeout": "5m",
|
||||||
|
"keepalive_interval": null,
|
||||||
|
"keys": "./data/keys",
|
||||||
|
"listen": "[::]:2222"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sso_providers": {
|
||||||
|
"type": "array",
|
||||||
|
"default": [],
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/$defs/SsoProviderConfig"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"$defs": {
|
||||||
|
"Duration": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"nanos": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint32",
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"secs": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "uint64",
|
||||||
|
"minimum": 0
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"secs",
|
||||||
|
"nanos"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"HttpConfig": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"certificate": {
|
||||||
|
"type": "string",
|
||||||
|
"default": ""
|
||||||
|
},
|
||||||
|
"cookie_max_age": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "1day"
|
||||||
|
},
|
||||||
|
"enable": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"external_port": {
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint16",
|
||||||
|
"default": null,
|
||||||
|
"maximum": 65535,
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string",
|
||||||
|
"default": ""
|
||||||
|
},
|
||||||
|
"listen": {
|
||||||
|
"$ref": "#/$defs/ListenEndpoint",
|
||||||
|
"default": "[::]:8888"
|
||||||
|
},
|
||||||
|
"session_max_age": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "30m"
|
||||||
|
},
|
||||||
|
"trust_x_forwarded_headers": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ListenEndpoint": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"LogConfig": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"retention": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "7days"
|
||||||
|
},
|
||||||
|
"send_to": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"MySqlConfig": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"certificate": {
|
||||||
|
"type": "string",
|
||||||
|
"default": ""
|
||||||
|
},
|
||||||
|
"enable": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"external_port": {
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint16",
|
||||||
|
"default": null,
|
||||||
|
"maximum": 65535,
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string",
|
||||||
|
"default": ""
|
||||||
|
},
|
||||||
|
"listen": {
|
||||||
|
"$ref": "#/$defs/ListenEndpoint",
|
||||||
|
"default": "[::]:33306"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"PostgresConfig": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"certificate": {
|
||||||
|
"type": "string",
|
||||||
|
"default": ""
|
||||||
|
},
|
||||||
|
"enable": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"external_port": {
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint16",
|
||||||
|
"default": null,
|
||||||
|
"maximum": 65535,
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"key": {
|
||||||
|
"type": "string",
|
||||||
|
"default": ""
|
||||||
|
},
|
||||||
|
"listen": {
|
||||||
|
"$ref": "#/$defs/ListenEndpoint",
|
||||||
|
"default": "[::]:55432"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"RecordingsConfig": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"enable": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"path": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "./data/recordings"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SshConfig": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"enable": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"external_port": {
|
||||||
|
"type": [
|
||||||
|
"integer",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"format": "uint16",
|
||||||
|
"default": null,
|
||||||
|
"maximum": 65535,
|
||||||
|
"minimum": 0
|
||||||
|
},
|
||||||
|
"host_key_verification": {
|
||||||
|
"$ref": "#/$defs/SshHostKeyVerificationMode",
|
||||||
|
"default": "prompt"
|
||||||
|
},
|
||||||
|
"inactivity_timeout": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "5m"
|
||||||
|
},
|
||||||
|
"keepalive_interval": {
|
||||||
|
"anyOf": [
|
||||||
|
{
|
||||||
|
"$ref": "#/$defs/Duration"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "null"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"default": null
|
||||||
|
},
|
||||||
|
"keys": {
|
||||||
|
"type": "string",
|
||||||
|
"default": "./data/keys"
|
||||||
|
},
|
||||||
|
"listen": {
|
||||||
|
"$ref": "#/$defs/ListenEndpoint",
|
||||||
|
"default": "[::]:2222"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"SshHostKeyVerificationMode": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": [
|
||||||
|
"prompt",
|
||||||
|
"auto_accept",
|
||||||
|
"auto_reject"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"SsoInternalProviderConfig": {
|
||||||
|
"oneOf": [
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"const": "google"
|
||||||
|
},
|
||||||
|
"client_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"client_secret": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"type",
|
||||||
|
"client_id",
|
||||||
|
"client_secret"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"const": "apple"
|
||||||
|
},
|
||||||
|
"client_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"client_secret": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"key_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"team_id": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"type",
|
||||||
|
"client_id",
|
||||||
|
"client_secret",
|
||||||
|
"key_id",
|
||||||
|
"team_id"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"const": "azure"
|
||||||
|
},
|
||||||
|
"client_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"client_secret": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"tenant": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"type",
|
||||||
|
"client_id",
|
||||||
|
"client_secret",
|
||||||
|
"tenant"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"type": "string",
|
||||||
|
"const": "custom"
|
||||||
|
},
|
||||||
|
"additional_trusted_audiences": {
|
||||||
|
"type": [
|
||||||
|
"array",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"client_id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"client_secret": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"issuer_url": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"role_mappings": {
|
||||||
|
"type": [
|
||||||
|
"object",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"additionalProperties": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"scopes": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"trust_unknown_audiences": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"type",
|
||||||
|
"client_id",
|
||||||
|
"client_secret",
|
||||||
|
"issuer_url",
|
||||||
|
"scopes"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"SsoProviderConfig": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"auto_create_users": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"type": [
|
||||||
|
"string",
|
||||||
|
"null"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"provider": {
|
||||||
|
"$ref": "#/$defs/SsoInternalProviderConfig"
|
||||||
|
},
|
||||||
|
"return_domain_whitelist": {
|
||||||
|
"type": [
|
||||||
|
"array",
|
||||||
|
"null"
|
||||||
|
],
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"name",
|
||||||
|
"provider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
3
justfile
3
justfile
|
@ -36,6 +36,9 @@ openapi-all:
|
||||||
openapi:
|
openapi:
|
||||||
cd warpgate-web && npm run openapi:client:admin && npm run openapi:client:gateway
|
cd warpgate-web && npm run openapi:client:admin && npm run openapi:client:gateway
|
||||||
|
|
||||||
|
config-schema:
|
||||||
|
cargo run -p warpgate-common --bin config-schema > config-schema.json
|
||||||
|
|
||||||
cleanup: (fix "--allow-dirty") (clippy "--fix" "--allow-dirty") fmt svelte-check lint
|
cleanup: (fix "--allow-dirty") (clippy "--fix" "--allow-dirty") fmt svelte-check lint
|
||||||
|
|
||||||
udeps:
|
udeps:
|
||||||
|
|
|
@ -4,6 +4,10 @@ license = "Apache-2.0"
|
||||||
name = "warpgate-common"
|
name = "warpgate-common"
|
||||||
version = "0.14.0"
|
version = "0.14.0"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "config-schema"
|
||||||
|
path = "src/config_schema.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
argon2 = "0.5"
|
argon2 = "0.5"
|
||||||
|
@ -45,3 +49,4 @@ rustls-pemfile = "1.0"
|
||||||
webpki = "0.22"
|
webpki = "0.22"
|
||||||
tokio-stream.workspace = true
|
tokio-stream.workspace = true
|
||||||
git-version = "0.3.9"
|
git-version = "0.3.9"
|
||||||
|
schemars.workspace = true
|
||||||
|
|
|
@ -8,6 +8,7 @@ use std::time::Duration;
|
||||||
use defaults::*;
|
use defaults::*;
|
||||||
use poem::http::uri;
|
use poem::http::uri;
|
||||||
use poem_openapi::{Object, Union};
|
use poem_openapi::{Object, Union};
|
||||||
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
pub use target::*;
|
pub use target::*;
|
||||||
use tracing::warn;
|
use tracing::warn;
|
||||||
|
@ -160,7 +161,7 @@ pub struct Role {
|
||||||
pub description: String,
|
pub description: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone, Default, PartialEq, Eq, Copy)]
|
#[derive(Debug, Deserialize, Serialize, Clone, Default, PartialEq, Eq, Copy, JsonSchema)]
|
||||||
pub enum SshHostKeyVerificationMode {
|
pub enum SshHostKeyVerificationMode {
|
||||||
#[serde(rename = "prompt")]
|
#[serde(rename = "prompt")]
|
||||||
#[default]
|
#[default]
|
||||||
|
@ -171,7 +172,7 @@ pub enum SshHostKeyVerificationMode {
|
||||||
AutoReject,
|
AutoReject,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone, JsonSchema)]
|
||||||
pub struct SshConfig {
|
pub struct SshConfig {
|
||||||
#[serde(default = "_default_false")]
|
#[serde(default = "_default_false")]
|
||||||
pub enable: bool,
|
pub enable: bool,
|
||||||
|
@ -189,6 +190,7 @@ pub struct SshConfig {
|
||||||
pub host_key_verification: SshHostKeyVerificationMode,
|
pub host_key_verification: SshHostKeyVerificationMode,
|
||||||
|
|
||||||
#[serde(default = "_default_ssh_inactivity_timeout", with = "humantime_serde")]
|
#[serde(default = "_default_ssh_inactivity_timeout", with = "humantime_serde")]
|
||||||
|
#[schemars(with = "String")]
|
||||||
pub inactivity_timeout: Duration,
|
pub inactivity_timeout: Duration,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
@ -215,7 +217,7 @@ impl SshConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone, JsonSchema)]
|
||||||
pub struct HttpConfig {
|
pub struct HttpConfig {
|
||||||
#[serde(default = "_default_false")]
|
#[serde(default = "_default_false")]
|
||||||
pub enable: bool,
|
pub enable: bool,
|
||||||
|
@ -236,9 +238,11 @@ pub struct HttpConfig {
|
||||||
pub trust_x_forwarded_headers: bool,
|
pub trust_x_forwarded_headers: bool,
|
||||||
|
|
||||||
#[serde(default = "_default_session_max_age", with = "humantime_serde")]
|
#[serde(default = "_default_session_max_age", with = "humantime_serde")]
|
||||||
|
#[schemars(with = "String")]
|
||||||
pub session_max_age: Duration,
|
pub session_max_age: Duration,
|
||||||
|
|
||||||
#[serde(default = "_default_cookie_max_age", with = "humantime_serde")]
|
#[serde(default = "_default_cookie_max_age", with = "humantime_serde")]
|
||||||
|
#[schemars(with = "String")]
|
||||||
pub cookie_max_age: Duration,
|
pub cookie_max_age: Duration,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,7 +267,7 @@ impl HttpConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone, JsonSchema)]
|
||||||
pub struct MySqlConfig {
|
pub struct MySqlConfig {
|
||||||
#[serde(default = "_default_false")]
|
#[serde(default = "_default_false")]
|
||||||
pub enable: bool,
|
pub enable: bool,
|
||||||
|
@ -299,7 +303,7 @@ impl MySqlConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone, JsonSchema)]
|
||||||
pub struct PostgresConfig {
|
pub struct PostgresConfig {
|
||||||
#[serde(default = "_default_false")]
|
#[serde(default = "_default_false")]
|
||||||
pub enable: bool,
|
pub enable: bool,
|
||||||
|
@ -335,7 +339,7 @@ impl PostgresConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone, JsonSchema)]
|
||||||
pub struct RecordingsConfig {
|
pub struct RecordingsConfig {
|
||||||
#[serde(default = "_default_false")]
|
#[serde(default = "_default_false")]
|
||||||
pub enable: bool,
|
pub enable: bool,
|
||||||
|
@ -353,9 +357,10 @@ impl Default for RecordingsConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
#[derive(Debug, Deserialize, Serialize, Clone, JsonSchema)]
|
||||||
pub struct LogConfig {
|
pub struct LogConfig {
|
||||||
#[serde(default = "_default_retention", with = "humantime_serde")]
|
#[serde(default = "_default_retention", with = "humantime_serde")]
|
||||||
|
#[schemars(with = "String")]
|
||||||
pub retention: Duration,
|
pub retention: Duration,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
@ -371,16 +376,7 @@ impl Default for LogConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone, PartialEq, Eq, Default)]
|
#[derive(Debug, Deserialize, Serialize, Clone, JsonSchema)]
|
||||||
pub enum ConfigProviderKind {
|
|
||||||
#[serde(rename = "file")]
|
|
||||||
File,
|
|
||||||
#[serde(rename = "database")]
|
|
||||||
#[default]
|
|
||||||
Database,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
|
||||||
pub struct WarpgateConfigStore {
|
pub struct WarpgateConfigStore {
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub sso_providers: Vec<SsoProviderConfig>,
|
pub sso_providers: Vec<SsoProviderConfig>,
|
||||||
|
@ -392,6 +388,7 @@ pub struct WarpgateConfigStore {
|
||||||
pub external_host: Option<String>,
|
pub external_host: Option<String>,
|
||||||
|
|
||||||
#[serde(default = "_default_database_url")]
|
#[serde(default = "_default_database_url")]
|
||||||
|
#[schemars(with = "String")]
|
||||||
pub database_url: Secret<String>,
|
pub database_url: Secret<String>,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
@ -408,9 +405,6 @@ pub struct WarpgateConfigStore {
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub log: LogConfig,
|
pub log: LogConfig,
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
pub config_provider: ConfigProviderKind,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for WarpgateConfigStore {
|
impl Default for WarpgateConfigStore {
|
||||||
|
@ -425,7 +419,6 @@ impl Default for WarpgateConfigStore {
|
||||||
mysql: <_>::default(),
|
mysql: <_>::default(),
|
||||||
postgres: <_>::default(),
|
postgres: <_>::default(),
|
||||||
log: <_>::default(),
|
log: <_>::default(),
|
||||||
config_provider: <_>::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
7
warpgate-common/src/config_schema.rs
Normal file
7
warpgate-common/src/config_schema.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
use schemars::schema_for;
|
||||||
|
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
fn main() {
|
||||||
|
let schema = schema_for!(warpgate_common::WarpgateConfigStore);
|
||||||
|
println!("{}", serde_json::to_string_pretty(&schema).unwrap());
|
||||||
|
}
|
|
@ -5,13 +5,14 @@ use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr, ToSocketAddrs};
|
||||||
use futures::stream::{iter, FuturesUnordered};
|
use futures::stream::{iter, FuturesUnordered};
|
||||||
use futures::{Stream, StreamExt, TryStreamExt};
|
use futures::{Stream, StreamExt, TryStreamExt};
|
||||||
use poem::listener::Listener;
|
use poem::listener::Listener;
|
||||||
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use tokio::net::{TcpListener, TcpStream};
|
use tokio::net::{TcpListener, TcpStream};
|
||||||
use tokio_stream::wrappers::TcpListenerStream;
|
use tokio_stream::wrappers::TcpListenerStream;
|
||||||
|
|
||||||
use crate::WarpgateError;
|
use crate::WarpgateError;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone, JsonSchema)]
|
||||||
pub struct ListenEndpoint(SocketAddr);
|
pub struct ListenEndpoint(SocketAddr);
|
||||||
|
|
||||||
impl ListenEndpoint {
|
impl ListenEndpoint {
|
||||||
|
|
|
@ -4,21 +4,19 @@ use std::time::Duration;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use sea_orm::DatabaseConnection;
|
use sea_orm::DatabaseConnection;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
use warpgate_common::{ConfigProviderKind, WarpgateConfig};
|
use warpgate_common::WarpgateConfig;
|
||||||
|
|
||||||
use crate::db::{connect_to_db, populate_db};
|
use crate::db::{connect_to_db, populate_db};
|
||||||
use crate::recordings::SessionRecordings;
|
use crate::recordings::SessionRecordings;
|
||||||
use crate::{AuthStateStore, ConfigProviderEnum, DatabaseConfigProvider, State};
|
use crate::{AuthStateStore, ConfigProviderEnum, DatabaseConfigProvider, State};
|
||||||
|
|
||||||
type ConfigProviderArc = Arc<Mutex<ConfigProviderEnum>>;
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Services {
|
pub struct Services {
|
||||||
pub db: Arc<Mutex<DatabaseConnection>>,
|
pub db: Arc<Mutex<DatabaseConnection>>,
|
||||||
pub recordings: Arc<Mutex<SessionRecordings>>,
|
pub recordings: Arc<Mutex<SessionRecordings>>,
|
||||||
pub config: Arc<Mutex<WarpgateConfig>>,
|
pub config: Arc<Mutex<WarpgateConfig>>,
|
||||||
pub state: Arc<Mutex<State>>,
|
pub state: Arc<Mutex<State>>,
|
||||||
pub config_provider: ConfigProviderArc,
|
pub config_provider: Arc<Mutex<ConfigProviderEnum>>,
|
||||||
pub auth_state_store: Arc<Mutex<AuthStateStore>>,
|
pub auth_state_store: Arc<Mutex<AuthStateStore>>,
|
||||||
pub admin_token: Arc<Mutex<Option<String>>>,
|
pub admin_token: Arc<Mutex<Option<String>>>,
|
||||||
}
|
}
|
||||||
|
@ -32,18 +30,9 @@ impl Services {
|
||||||
let recordings = SessionRecordings::new(db.clone(), &config)?;
|
let recordings = SessionRecordings::new(db.clone(), &config)?;
|
||||||
let recordings = Arc::new(Mutex::new(recordings));
|
let recordings = Arc::new(Mutex::new(recordings));
|
||||||
|
|
||||||
let provider = config.store.config_provider.clone();
|
|
||||||
let config = Arc::new(Mutex::new(config));
|
let config = Arc::new(Mutex::new(config));
|
||||||
|
|
||||||
let config_provider = match provider {
|
let config_provider = Arc::new(Mutex::new(DatabaseConfigProvider::new(&db).await.into()));
|
||||||
ConfigProviderKind::File => {
|
|
||||||
anyhow::bail!("File based config provider in no longer supported");
|
|
||||||
}
|
|
||||||
ConfigProviderKind::Database => {
|
|
||||||
Arc::new(Mutex::new(DatabaseConfigProvider::new(&db).await.into()))
|
|
||||||
as ConfigProviderArc
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let auth_state_store = Arc::new(Mutex::new(AuthStateStore::new(config_provider.clone())));
|
let auth_state_store = Arc::new(Mutex::new(AuthStateStore::new(config_provider.clone())));
|
||||||
|
|
||||||
|
|
|
@ -19,3 +19,4 @@ once_cell = "1.17"
|
||||||
jsonwebtoken = "9"
|
jsonwebtoken = "9"
|
||||||
data-encoding.workspace = true
|
data-encoding.workspace = true
|
||||||
futures.workspace = true
|
futures.workspace = true
|
||||||
|
schemars.workspace = true
|
||||||
|
|
|
@ -4,6 +4,7 @@ use std::time::SystemTime;
|
||||||
use data_encoding::BASE64;
|
use data_encoding::BASE64;
|
||||||
use once_cell::sync::Lazy;
|
use once_cell::sync::Lazy;
|
||||||
use openidconnect::{AuthType, ClientId, ClientSecret, IssuerUrl};
|
use openidconnect::{AuthType, ClientId, ClientSecret, IssuerUrl};
|
||||||
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use crate::SsoError;
|
use crate::SsoError;
|
||||||
|
@ -16,7 +17,7 @@ pub static GOOGLE_ISSUER_URL: Lazy<IssuerUrl> =
|
||||||
pub static APPLE_ISSUER_URL: Lazy<IssuerUrl> =
|
pub static APPLE_ISSUER_URL: Lazy<IssuerUrl> =
|
||||||
Lazy::new(|| IssuerUrl::new("https://appleid.apple.com".to_string()).unwrap());
|
Lazy::new(|| IssuerUrl::new("https://appleid.apple.com".to_string()).unwrap());
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
pub struct SsoProviderConfig {
|
pub struct SsoProviderConfig {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub label: Option<String>,
|
pub label: Option<String>,
|
||||||
|
@ -34,31 +35,40 @@ impl SsoProviderConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Serialize, Deserialize, JsonSchema)]
|
||||||
#[serde(tag = "type")]
|
#[serde(tag = "type")]
|
||||||
pub enum SsoInternalProviderConfig {
|
pub enum SsoInternalProviderConfig {
|
||||||
#[serde(rename = "google")]
|
#[serde(rename = "google")]
|
||||||
Google {
|
Google {
|
||||||
|
#[schemars(with = "String")]
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
|
#[schemars(with = "String")]
|
||||||
client_secret: ClientSecret,
|
client_secret: ClientSecret,
|
||||||
},
|
},
|
||||||
#[serde(rename = "apple")]
|
#[serde(rename = "apple")]
|
||||||
Apple {
|
Apple {
|
||||||
|
#[schemars(with = "String")]
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
|
#[schemars(with = "String")]
|
||||||
client_secret: ClientSecret,
|
client_secret: ClientSecret,
|
||||||
key_id: String,
|
key_id: String,
|
||||||
team_id: String,
|
team_id: String,
|
||||||
},
|
},
|
||||||
#[serde(rename = "azure")]
|
#[serde(rename = "azure")]
|
||||||
Azure {
|
Azure {
|
||||||
|
#[schemars(with = "String")]
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
|
#[schemars(with = "String")]
|
||||||
client_secret: ClientSecret,
|
client_secret: ClientSecret,
|
||||||
tenant: String,
|
tenant: String,
|
||||||
},
|
},
|
||||||
#[serde(rename = "custom")]
|
#[serde(rename = "custom")]
|
||||||
Custom {
|
Custom {
|
||||||
|
#[schemars(with = "String")]
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
|
#[schemars(with = "String")]
|
||||||
client_secret: ClientSecret,
|
client_secret: ClientSecret,
|
||||||
|
#[schemars(with = "String")]
|
||||||
issuer_url: IssuerUrl,
|
issuer_url: IssuerUrl,
|
||||||
scopes: Vec<String>,
|
scopes: Vec<String>,
|
||||||
role_mappings: Option<HashMap<String, String>>,
|
role_mappings: Option<HashMap<String, String>>,
|
||||||
|
|
|
@ -39,6 +39,7 @@ warpgate-protocol-http = { version = "*", path = "../warpgate-protocol-http" }
|
||||||
warpgate-protocol-mysql = { version = "*", path = "../warpgate-protocol-mysql" }
|
warpgate-protocol-mysql = { version = "*", path = "../warpgate-protocol-mysql" }
|
||||||
warpgate-protocol-postgres = { version = "*", path = "../warpgate-protocol-postgres" }
|
warpgate-protocol-postgres = { version = "*", path = "../warpgate-protocol-postgres" }
|
||||||
warpgate-protocol-ssh = { version = "*", path = "../warpgate-protocol-ssh" }
|
warpgate-protocol-ssh = { version = "*", path = "../warpgate-protocol-ssh" }
|
||||||
|
schemars.workspace = true
|
||||||
|
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
sd-notify = "0.4"
|
sd-notify = "0.4"
|
||||||
|
|
|
@ -293,6 +293,11 @@ pub(crate) async fn command(cli: &crate::Cli) -> Result<()> {
|
||||||
let yaml = serde_yaml::to_string(&store)?;
|
let yaml = serde_yaml::to_string(&store)?;
|
||||||
println!("{yaml}");
|
println!("{yaml}");
|
||||||
|
|
||||||
|
let yaml = format!(
|
||||||
|
"# Config generated in version {version}\n# yaml-language-server: $schema=https://raw.githubusercontent.com/warp-tech/warpgate/refs/heads/main/config-schema.json\n\n{yaml}",
|
||||||
|
version = warpgate_version()
|
||||||
|
);
|
||||||
|
|
||||||
File::create(&cli.config)?.write_all(yaml.as_bytes())?;
|
File::create(&cli.config)?.write_all(yaml.as_bytes())?;
|
||||||
info!("Saved into {}", cli.config.display());
|
info!("Saved into {}", cli.config.display());
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue