mirror of
https://github.com/windmill-labs/windmill.git
synced 2026-08-18 16:02:10 +00:00
feat: OIDC support (#3017)
* oidc * update * feat: add support for multiselect in python * d * d * progress * all * all * all
This commit is contained in:
Generated
+310
-21
@@ -775,7 +775,7 @@ dependencies = [
|
||||
"hmac",
|
||||
"http",
|
||||
"once_cell",
|
||||
"p256",
|
||||
"p256 0.11.1",
|
||||
"percent-encoding",
|
||||
"ring 0.17.7",
|
||||
"sha2 0.10.8",
|
||||
@@ -1027,6 +1027,12 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "349a06037c7bf932dd7e7d1f653678b2038b9ad46a74102f1fc7bd7872678cce"
|
||||
|
||||
[[package]]
|
||||
name = "base16ct"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4c7f02d4ea65f2c1853089ffd8d2787bdbc63de2f0d29dedbcf8ccdfa0ccd4cf"
|
||||
|
||||
[[package]]
|
||||
name = "base64"
|
||||
version = "0.13.1"
|
||||
@@ -1898,8 +1904,10 @@ version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1912,6 +1920,34 @@ dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek"
|
||||
version = "4.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e89b8c6a2e4b1f45971ad09761aafb85514a84744b67a95e32c3cc1352d1f65c"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"curve25519-dalek-derive",
|
||||
"digest 0.10.7",
|
||||
"fiat-crypto",
|
||||
"platforms",
|
||||
"rustc_version 0.4.0",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "curve25519-dalek-derive"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.48",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.14.4"
|
||||
@@ -2439,11 +2475,49 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413301934810f597c1d19ca71c8710e99a3f1ba28a0d2ebc01551a2daeea3c5c"
|
||||
dependencies = [
|
||||
"der 0.6.1",
|
||||
"elliptic-curve",
|
||||
"rfc6979",
|
||||
"elliptic-curve 0.12.3",
|
||||
"rfc6979 0.3.1",
|
||||
"signature 1.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
version = "0.16.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee27f32b5c5292967d2d4a9d7f1e0b0aed2c15daded5a60300e4abb9d8020bca"
|
||||
dependencies = [
|
||||
"der 0.7.8",
|
||||
"digest 0.10.7",
|
||||
"elliptic-curve 0.13.8",
|
||||
"rfc6979 0.4.0",
|
||||
"signature 2.2.0",
|
||||
"spki 0.7.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ed25519"
|
||||
version = "2.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "115531babc129696a58c64a4fef0a8bf9e9698629fb97e9e40767d235cfbcd53"
|
||||
dependencies = [
|
||||
"pkcs8 0.10.2",
|
||||
"signature 2.2.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ed25519-dalek"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f628eaec48bfd21b865dc2950cfa014450c01d2fa2b69a86c2fd5844ec523c0"
|
||||
dependencies = [
|
||||
"curve25519-dalek",
|
||||
"ed25519",
|
||||
"serde",
|
||||
"sha2 0.10.8",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
@@ -2459,16 +2533,37 @@ version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e7bb888ab5300a19b8e5bceef25ac745ad065f3c9f7efc6de1b91958110891d3"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"base16ct 0.1.1",
|
||||
"crypto-bigint 0.4.9",
|
||||
"der 0.6.1",
|
||||
"digest 0.10.7",
|
||||
"ff",
|
||||
"ff 0.12.1",
|
||||
"generic-array",
|
||||
"group",
|
||||
"group 0.12.1",
|
||||
"pkcs8 0.9.0",
|
||||
"rand_core 0.6.4",
|
||||
"sec1",
|
||||
"sec1 0.3.0",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "elliptic-curve"
|
||||
version = "0.13.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
|
||||
dependencies = [
|
||||
"base16ct 0.2.0",
|
||||
"crypto-bigint 0.5.5",
|
||||
"digest 0.10.7",
|
||||
"ff 0.13.0",
|
||||
"generic-array",
|
||||
"group 0.13.0",
|
||||
"hkdf",
|
||||
"pem-rfc7468 0.7.0",
|
||||
"pkcs8 0.10.2",
|
||||
"rand_core 0.6.4",
|
||||
"sec1 0.7.3",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
@@ -2708,6 +2803,22 @@ dependencies = [
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ff"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
|
||||
dependencies = [
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fiat-crypto"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "27573eac26f4dd11e2b1916c3fe1baa56407c83c71a773a8ba17ec0bca03b6b7"
|
||||
|
||||
[[package]]
|
||||
name = "filetime"
|
||||
version = "0.2.23"
|
||||
@@ -3143,6 +3254,7 @@ checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
"version_check",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3263,7 +3375,18 @@ version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5dfbfb3a6cfbd390d5c9564ab283a0349b9b9fcd46a706c1eb10e0db70bfbac7"
|
||||
dependencies = [
|
||||
"ff",
|
||||
"ff 0.12.1",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "group"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0f9ef7462f7c099f518d754361858f86d8a07af53ba9af0fe635bbccb151a63"
|
||||
dependencies = [
|
||||
"ff 0.13.0",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
]
|
||||
@@ -3612,6 +3735,7 @@ checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.14.3",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4542,6 +4666,26 @@ version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3"
|
||||
|
||||
[[package]]
|
||||
name = "oauth2"
|
||||
version = "4.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c38841cdd844847e3e7c8d29cef9dcfed8877f8f56f9071f77843ecf3baf937f"
|
||||
dependencies = [
|
||||
"base64 0.13.1",
|
||||
"chrono",
|
||||
"getrandom 0.2.12",
|
||||
"http",
|
||||
"rand 0.8.5",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
"sha2 0.10.8",
|
||||
"thiserror",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.32.2"
|
||||
@@ -4625,6 +4769,38 @@ dependencies = [
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openidconnect"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62d6050f6a84b81f23c569f5607ad883293e57491036e318fafe6fc4895fadb1"
|
||||
dependencies = [
|
||||
"base64 0.13.1",
|
||||
"chrono",
|
||||
"dyn-clone",
|
||||
"ed25519-dalek",
|
||||
"hmac",
|
||||
"http",
|
||||
"itertools 0.10.5",
|
||||
"log",
|
||||
"oauth2",
|
||||
"p256 0.13.2",
|
||||
"p384",
|
||||
"rand 0.8.5",
|
||||
"rsa 0.9.6",
|
||||
"serde",
|
||||
"serde-value",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"serde_path_to_error",
|
||||
"serde_plain",
|
||||
"serde_with",
|
||||
"sha2 0.10.8",
|
||||
"subtle",
|
||||
"thiserror",
|
||||
"url",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "openssl"
|
||||
version = "0.10.62"
|
||||
@@ -4675,6 +4851,15 @@ version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
|
||||
|
||||
[[package]]
|
||||
name = "ordered-float"
|
||||
version = "2.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "outref"
|
||||
version = "0.5.1"
|
||||
@@ -4693,8 +4878,32 @@ version = "0.11.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51f44edd08f51e2ade572f141051021c5af22677e42b7dd28a88155151c33594"
|
||||
dependencies = [
|
||||
"ecdsa",
|
||||
"elliptic-curve",
|
||||
"ecdsa 0.14.8",
|
||||
"elliptic-curve 0.12.3",
|
||||
"sha2 0.10.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "p256"
|
||||
version = "0.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9863ad85fa8f4460f9c48cb909d38a0d689dba1f6f6988a5e3e0d31071bcd4b"
|
||||
dependencies = [
|
||||
"ecdsa 0.16.9",
|
||||
"elliptic-curve 0.13.8",
|
||||
"primeorder",
|
||||
"sha2 0.10.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "p384"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "70786f51bcc69f6a4c0360e063a4cac5419ef7c5cd5b3c99ad70f3be5ba79209"
|
||||
dependencies = [
|
||||
"ecdsa 0.16.9",
|
||||
"elliptic-curve 0.13.8",
|
||||
"primeorder",
|
||||
"sha2 0.10.8",
|
||||
]
|
||||
|
||||
@@ -5056,6 +5265,12 @@ dependencies = [
|
||||
"array-init-cursor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "platforms"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "626dec3cac7cc0e1577a2ec3fc496277ec2baa084bebad95bb6fdbfae235f84c"
|
||||
|
||||
[[package]]
|
||||
name = "pmutil"
|
||||
version = "0.5.3"
|
||||
@@ -5543,6 +5758,15 @@ dependencies = [
|
||||
"syn 2.0.48",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "primeorder"
|
||||
version = "0.13.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "353e1ca18966c16d9deb1c69278edbc5f194139612772bd9537af60ac231e1e6"
|
||||
dependencies = [
|
||||
"elliptic-curve 0.13.8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "1.3.1"
|
||||
@@ -6130,6 +6354,16 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rfc6979"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f8dd2a808d456c4a54e300a23e9f5a67e122c3024119acbfd73e3bf664491cb2"
|
||||
dependencies = [
|
||||
"hmac",
|
||||
"subtle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "riff"
|
||||
version = "1.0.1"
|
||||
@@ -6647,7 +6881,7 @@ version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3be24c1842290c45df0a7bf069e0c268a747ad05a192f2fd7dcfdbc1cba40928"
|
||||
dependencies = [
|
||||
"base16ct",
|
||||
"base16ct 0.1.1",
|
||||
"der 0.6.1",
|
||||
"generic-array",
|
||||
"pkcs8 0.9.0",
|
||||
@@ -6655,6 +6889,20 @@ dependencies = [
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sec1"
|
||||
version = "0.7.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
|
||||
dependencies = [
|
||||
"base16ct 0.2.0",
|
||||
"der 0.7.8",
|
||||
"generic-array",
|
||||
"pkcs8 0.10.2",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "security-framework"
|
||||
version = "2.9.2"
|
||||
@@ -6728,6 +6976,16 @@ dependencies = [
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-value"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
|
||||
dependencies = [
|
||||
"ordered-float",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-wasm-bindgen"
|
||||
version = "0.4.5"
|
||||
@@ -6872,6 +7130,35 @@ dependencies = [
|
||||
"v8",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23"
|
||||
dependencies = [
|
||||
"base64 0.21.7",
|
||||
"chrono",
|
||||
"hex",
|
||||
"indexmap 1.9.3",
|
||||
"indexmap 2.1.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_with_macros",
|
||||
"time",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with_macros"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788"
|
||||
dependencies = [
|
||||
"darling 0.20.3",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.48",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.9.30"
|
||||
@@ -7520,9 +7807,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
checksum = "ccbca6f34534eb78dbee83f6b2c9442fea7113f43d9e80ea320f0972ae5dc08d"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
@@ -9315,12 +9602,13 @@ dependencies = [
|
||||
"hf-hub",
|
||||
"hmac",
|
||||
"hyper",
|
||||
"itertools 0.12.0",
|
||||
"itertools 0.9.0",
|
||||
"lazy_static",
|
||||
"magic-crypt",
|
||||
"mail-send",
|
||||
"mime_guess",
|
||||
"object_store",
|
||||
"openidconnect",
|
||||
"polars",
|
||||
"polars-io",
|
||||
"prometheus",
|
||||
@@ -9405,7 +9693,7 @@ dependencies = [
|
||||
"hex",
|
||||
"hmac",
|
||||
"hyper",
|
||||
"itertools 0.12.0",
|
||||
"itertools 0.9.0",
|
||||
"lazy_static",
|
||||
"magic-crypt",
|
||||
"prometheus",
|
||||
@@ -9464,7 +9752,7 @@ version = "1.245.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"gosyn",
|
||||
"itertools 0.12.0",
|
||||
"itertools 0.9.0",
|
||||
"lazy_static",
|
||||
"regex",
|
||||
"windmill-parser",
|
||||
@@ -9486,7 +9774,7 @@ name = "windmill-parser-py"
|
||||
version = "1.245.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"itertools 0.12.0",
|
||||
"itertools 0.9.0",
|
||||
"rustpython-parser",
|
||||
"serde_json",
|
||||
"windmill-parser",
|
||||
@@ -9498,7 +9786,7 @@ version = "1.245.1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
"itertools 0.12.0",
|
||||
"itertools 0.9.0",
|
||||
"lazy_static",
|
||||
"phf 0.11.2",
|
||||
"regex",
|
||||
@@ -9563,14 +9851,14 @@ dependencies = [
|
||||
"anyhow",
|
||||
"async-recursion",
|
||||
"axum",
|
||||
"bigdecimal 0.4.2",
|
||||
"bigdecimal 0.3.1",
|
||||
"chrono",
|
||||
"chrono-tz",
|
||||
"cron",
|
||||
"futures-core",
|
||||
"hex",
|
||||
"hmac",
|
||||
"itertools 0.12.0",
|
||||
"itertools 0.9.0",
|
||||
"lazy_static",
|
||||
"prometheus",
|
||||
"regex",
|
||||
@@ -9613,13 +9901,14 @@ dependencies = [
|
||||
"gcp_auth",
|
||||
"git-version",
|
||||
"hex",
|
||||
"itertools 0.12.0",
|
||||
"itertools 0.9.0",
|
||||
"jsonwebtoken",
|
||||
"lazy_static",
|
||||
"mysql_async",
|
||||
"native-tls",
|
||||
"nix",
|
||||
"once_cell",
|
||||
"openidconnect",
|
||||
"pem 3.0.3",
|
||||
"postgres-native-tls",
|
||||
"prometheus",
|
||||
|
||||
@@ -216,3 +216,4 @@ aws-config = "1.0.3"
|
||||
polars = { version = "0.35.2", features = ["lazy", "parquet", "aws", "csv", "dtype-full"] }
|
||||
polars-io = { version = "0.35.2", features = ["csv"] }
|
||||
object_store = { version = "0.8.0", features = ["aws"] }
|
||||
openidconnect = { version = "3.4.0" }
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
-- Add down migration script here
|
||||
@@ -0,0 +1,2 @@
|
||||
-- Add up migration script here
|
||||
ALTER TABLE token ADD COLUMN IF NOT EXISTS job UUID;
|
||||
@@ -781,6 +781,7 @@ async fn handle_zombie_jobs<R: rsmq_async::RsmqConnection + Send + Sync + Clone>
|
||||
"ephemeral-script",
|
||||
*SCRIPT_TOKEN_EXPIRY,
|
||||
&job.email,
|
||||
&job.id,
|
||||
)
|
||||
.await
|
||||
.expect("could not create job token");
|
||||
|
||||
@@ -300,7 +300,7 @@ mod suspend_resume {
|
||||
let second = completed.next().await.unwrap();
|
||||
// print_job(second, &db).await;
|
||||
|
||||
let token = windmill_worker::create_token_for_owner(&db, "test-workspace", "u/test-user", "", 100, "").await.unwrap();
|
||||
let token = windmill_worker::create_token_for_owner(&db, "test-workspace", "u/test-user", "", 100, "", &Uuid::nil()).await.unwrap();
|
||||
let secret = reqwest::get(format!(
|
||||
"http://localhost:{port}/api/w/test-workspace/jobs/job_signature/{second}/0?token={token}&approver=ruben"
|
||||
))
|
||||
@@ -401,7 +401,7 @@ mod suspend_resume {
|
||||
/* ... and send a request resume it. */
|
||||
let second = completed.next().await.unwrap();
|
||||
|
||||
let token = windmill_worker::create_token_for_owner(&db, "test-workspace", "u/test-user", "", 100, "").await.unwrap();
|
||||
let token = windmill_worker::create_token_for_owner(&db, "test-workspace", "u/test-user", "", 100, "", &Uuid::nil()).await.unwrap();
|
||||
let secret = reqwest::get(format!(
|
||||
"http://localhost:{port}/api/w/test-workspace/jobs/job_signature/{second}/0?token={token}"
|
||||
))
|
||||
|
||||
@@ -9,7 +9,7 @@ name = "windmill_api"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[features]
|
||||
enterprise = ["windmill-queue/enterprise", "windmill-audit/enterprise", "windmill-git-sync/enterprise"]
|
||||
enterprise = ["windmill-queue/enterprise", "windmill-audit/enterprise", "windmill-git-sync/enterprise", "openidconnect"]
|
||||
stripe = ["async-stripe"]
|
||||
enterprise_saml = ["samael"]
|
||||
benchmark = []
|
||||
@@ -89,3 +89,4 @@ aws-sdk-s3.workspace = true
|
||||
polars.workspace = true
|
||||
polars-io.workspace = true
|
||||
object_store.workspace = true
|
||||
openidconnect = { workspace = true, optional = true}
|
||||
|
||||
@@ -1681,6 +1681,29 @@ paths:
|
||||
items:
|
||||
$ref: "#/components/schemas/TruncatedToken"
|
||||
|
||||
/w/{workspace}/oidc/token/{audience}:
|
||||
post:
|
||||
summary: get OIDC token (ee only)
|
||||
operationId: getOidcToken
|
||||
tags:
|
||||
- oidc
|
||||
parameters:
|
||||
- $ref: "#/components/parameters/WorkspaceId"
|
||||
- name: audience
|
||||
in: path
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
|
||||
responses:
|
||||
"200":
|
||||
description: new oidc token
|
||||
content:
|
||||
text/plain:
|
||||
schema:
|
||||
type: string
|
||||
|
||||
|
||||
/w/{workspace}/variables/create:
|
||||
post:
|
||||
summary: create variable
|
||||
|
||||
@@ -63,6 +63,8 @@ pub mod job_helpers;
|
||||
pub mod job_metrics;
|
||||
pub mod jobs;
|
||||
pub mod oauth2;
|
||||
|
||||
mod oidc;
|
||||
mod openai;
|
||||
mod raw_apps;
|
||||
mod resources;
|
||||
@@ -212,7 +214,8 @@ pub async fn run_server(
|
||||
users::workspaced_service().layer(Extension(argon2.clone())),
|
||||
)
|
||||
.nest("/variables", variables::workspaced_service())
|
||||
.nest("/workspaces", workspaces::workspaced_service()),
|
||||
.nest("/workspaces", workspaces::workspaced_service())
|
||||
.nest("/oidc", oidc::workspaced_service()),
|
||||
)
|
||||
.nest("/workspaces", workspaces::global_service())
|
||||
.nest(
|
||||
@@ -235,6 +238,7 @@ pub async fn run_server(
|
||||
.route_layer(from_extractor::<ApiAuthed>())
|
||||
.route_layer(from_extractor::<users::Tokened>())
|
||||
.nest("/jobs", jobs::global_root_service())
|
||||
.nest("/oidc", oidc::global_service())
|
||||
.nest(
|
||||
"/saml",
|
||||
saml::global_service().layer(Extension(Arc::new(sp_extension.0))),
|
||||
|
||||
@@ -0,0 +1,296 @@
|
||||
/*
|
||||
* Author: Ruben Fiszel
|
||||
* Copyright: Windmill Labs, Inc 2023
|
||||
* This file and its contents are licensed under the AGPLv3 License.
|
||||
* Please see the included NOTICE for copyright information and
|
||||
* LICENSE-AGPL for a copy of the license.
|
||||
*/
|
||||
|
||||
use std::process::Command;
|
||||
|
||||
use anyhow;
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
use openidconnect::{
|
||||
core::{
|
||||
CoreClaimName, CoreJsonWebKeySet, CoreJwsSigningAlgorithm, CoreProviderMetadata,
|
||||
CoreResponseType, CoreRsaPrivateSigningKey, CoreSubjectIdentifierType,
|
||||
},
|
||||
AdditionalClaims, AuthUrl, EmptyAdditionalProviderMetadata, IssuerUrl, JsonWebKeyId,
|
||||
JsonWebKeySetUrl, ResponseTypes,
|
||||
};
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
impl AdditionalClaims for JobClaim {}
|
||||
|
||||
use crate::db::DB;
|
||||
use axum::extract::Path;
|
||||
use axum::routing::get;
|
||||
use axum::Extension;
|
||||
use axum::{Json, Router};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub fn global_service() -> Router {
|
||||
Router::new()
|
||||
.route(
|
||||
"/.well-known/openid-configuration",
|
||||
get(openid_configuration),
|
||||
)
|
||||
.route("/jwks", get(jwks))
|
||||
}
|
||||
#[cfg(not(feature = "enterprise"))]
|
||||
pub fn global_service() -> Router {
|
||||
Router::new()
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "enterprise"))]
|
||||
pub fn workspaced_service() -> Router {
|
||||
Router::new()
|
||||
}
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub fn workspaced_service() -> Router {
|
||||
Router::new().route("/token/:audience", get(gen_token))
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize)]
|
||||
struct Keys {
|
||||
private_key: String,
|
||||
}
|
||||
|
||||
async fn gen_pems(db: &DB) -> anyhow::Result<Keys> {
|
||||
let private_key_cmd = Command::new("openssl")
|
||||
.arg("genrsa")
|
||||
.arg("--traditional")
|
||||
.arg("2048")
|
||||
.output()
|
||||
.expect("failed to execute process");
|
||||
|
||||
let private_key = String::from_utf8(private_key_cmd.stdout).unwrap();
|
||||
|
||||
tracing::debug!("Generated private key: {}", private_key);
|
||||
let keys = Keys { private_key };
|
||||
|
||||
sqlx::query!(
|
||||
"INSERT INTO global_settings (name, value) VALUES ('rsa_keys', $1)",
|
||||
serde_json::to_value(&keys).unwrap()
|
||||
)
|
||||
.execute(db)
|
||||
.await?;
|
||||
|
||||
Ok(keys)
|
||||
}
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
async fn get_private_key(db: &DB) -> anyhow::Result<String> {
|
||||
let key = sqlx::query_scalar!(
|
||||
"SELECT value->>'private_key' FROM global_settings WHERE name = 'rsa_keys'",
|
||||
)
|
||||
.fetch_optional(db)
|
||||
.await?
|
||||
.flatten();
|
||||
|
||||
if let Some(key) = key {
|
||||
return Ok(key);
|
||||
} else {
|
||||
let keys = gen_pems(db).await?;
|
||||
return Ok(keys.private_key);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub async fn jwks(
|
||||
Extension(db): Extension<DB>,
|
||||
) -> windmill_common::error::JsonResult<CoreJsonWebKeySet> {
|
||||
use openidconnect::PrivateSigningKey;
|
||||
|
||||
let private_key = get_private_key(&db).await?;
|
||||
let jwks = CoreJsonWebKeySet::new(vec![CoreRsaPrivateSigningKey::from_pem(
|
||||
&private_key,
|
||||
Some(JsonWebKeyId::new("windmill".to_string())),
|
||||
)
|
||||
.map_err(|e| anyhow::anyhow!("Failed to parse PEM: {}", e))?
|
||||
.as_verification_key()]);
|
||||
|
||||
Ok(Json(jwks))
|
||||
}
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub async fn openid_configuration() -> windmill_common::error::JsonResult<CoreProviderMetadata> {
|
||||
use windmill_common::BASE_URL;
|
||||
|
||||
let base_url = BASE_URL.read().await.clone();
|
||||
return get_provider_metadata(base_url)
|
||||
.map(Json)
|
||||
.map_err(|e| e.into());
|
||||
}
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub fn get_provider_metadata(base_url: String) -> anyhow::Result<CoreProviderMetadata> {
|
||||
let provider_metadata = CoreProviderMetadata::new(
|
||||
IssuerUrl::new(format!("{base_url}/api/oidc/"))?,
|
||||
AuthUrl::new(format!("{base_url}/api/oidc/"))?,
|
||||
JsonWebKeySetUrl::new(format!("{base_url}/api/oidc/jwks"))?,
|
||||
vec![
|
||||
// Optional: support the implicit flow.
|
||||
ResponseTypes::new(vec![CoreResponseType::Token, CoreResponseType::IdToken]), // Other flows including hybrid flows may also be specified here.
|
||||
],
|
||||
vec![CoreSubjectIdentifierType::Public],
|
||||
vec![CoreJwsSigningAlgorithm::RsaSsaPssSha256],
|
||||
EmptyAdditionalProviderMetadata {},
|
||||
)
|
||||
// Recommended: specify the supported ID token claims.
|
||||
.set_claims_supported(Some(vec![
|
||||
// Providers may also define an enum instead of using CoreClaimName.
|
||||
CoreClaimName::new("sub".to_string()),
|
||||
CoreClaimName::new("aud".to_string()),
|
||||
CoreClaimName::new("email".to_string()),
|
||||
CoreClaimName::new("email_verified".to_string()),
|
||||
CoreClaimName::new("exp".to_string()),
|
||||
CoreClaimName::new("iat".to_string()),
|
||||
CoreClaimName::new("iss".to_string()),
|
||||
CoreClaimName::new("name".to_string()),
|
||||
CoreClaimName::new("given_name".to_string()),
|
||||
CoreClaimName::new("family_name".to_string()),
|
||||
CoreClaimName::new("picture".to_string()),
|
||||
CoreClaimName::new("locale".to_string()),
|
||||
]));
|
||||
return Ok(provider_metadata);
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, Deserialize, PartialEq, Eq, Serialize)]
|
||||
struct JobClaim {
|
||||
job_id: String,
|
||||
path: Option<String>,
|
||||
flow_path: Option<String>,
|
||||
groups: Vec<String>,
|
||||
username: String,
|
||||
email: String,
|
||||
workspace: String,
|
||||
}
|
||||
|
||||
use crate::db::ApiAuthed;
|
||||
use crate::users::Tokened;
|
||||
|
||||
#[cfg(feature = "enterprise")]
|
||||
pub async fn gen_token(
|
||||
authed: ApiAuthed,
|
||||
token: Tokened,
|
||||
Extension(db): Extension<DB>,
|
||||
Path((w_id, audience)): Path<(String, String)>,
|
||||
) -> windmill_common::error::Result<String> {
|
||||
use chrono::{Duration, Utc};
|
||||
use openidconnect::{
|
||||
core::{CoreGenderClaim, CoreJsonWebKeyType, CoreJweContentEncryptionAlgorithm},
|
||||
Audience, EndUserEmail, IdToken, IdTokenClaims, StandardClaims, SubjectIdentifier,
|
||||
};
|
||||
use windmill_queue::get_queued_job;
|
||||
|
||||
use crate::users::get_groups_for_user;
|
||||
|
||||
let private_key = get_private_key(&db).await?;
|
||||
|
||||
let username = authed.username;
|
||||
let email = authed.email;
|
||||
|
||||
let job_id = {
|
||||
let job = sqlx::query_scalar!("SELECT job FROM token WHERE token = $1", token.token)
|
||||
.fetch_optional(&db)
|
||||
.await?
|
||||
.flatten();
|
||||
if job.is_none() {
|
||||
return Err(anyhow::anyhow!("Token not found").into());
|
||||
} else {
|
||||
job.unwrap()
|
||||
}
|
||||
};
|
||||
let mut tx = db.begin().await?;
|
||||
let job = get_queued_job(job_id, &w_id, &mut tx).await?;
|
||||
tx.commit().await?;
|
||||
|
||||
let job = job.ok_or_else(|| anyhow::anyhow!("Queued job {} not found", job_id))?;
|
||||
let issue_url = crate::BASE_URL.read().await.clone();
|
||||
let flow_path = if let Some(uuid) = job.parent_job {
|
||||
sqlx::query_scalar!("SELECT script_path FROM queue WHERE id = $1", uuid)
|
||||
.fetch_optional(&db)
|
||||
.await?
|
||||
.flatten()
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let groups = get_groups_for_user(&w_id, &username, &email, &db)
|
||||
.await
|
||||
.ok()
|
||||
.unwrap_or_default();
|
||||
|
||||
let id_token = IdToken::<
|
||||
JobClaim,
|
||||
CoreGenderClaim,
|
||||
CoreJweContentEncryptionAlgorithm,
|
||||
CoreJwsSigningAlgorithm,
|
||||
CoreJsonWebKeyType,
|
||||
>::new(
|
||||
IdTokenClaims::<JobClaim, CoreGenderClaim>::new(
|
||||
// Specify the issuer URL for the OpenID Connect Provider.
|
||||
IssuerUrl::new(issue_url)
|
||||
.map_err(|e| anyhow::anyhow!("Failed to generate IssueUrl: {}", e))?,
|
||||
// The audience is usually a single entry with the client ID of the client for whom
|
||||
// the ID token is intended. This is a required claim.
|
||||
vec![Audience::new(audience)],
|
||||
// The ID token expiration is usually much shorter than that of the access or refresh
|
||||
// tokens issued to clients.
|
||||
Utc::now() + Duration::seconds(300),
|
||||
// The issue time is usually the current time.
|
||||
Utc::now(),
|
||||
// Set the standard claims defined by the OpenID Connect Core spec.
|
||||
StandardClaims::new(
|
||||
// Stable subject identifiers are recommended in place of e-mail addresses or other
|
||||
// potentially unstable identifiers. This is the only required claim.
|
||||
SubjectIdentifier::new("windmill".to_string()),
|
||||
)
|
||||
// Optional: specify the user's e-mail address. This should only be provided if the
|
||||
// client has been granted the 'profile' or 'email' scopes.
|
||||
.set_email(Some(EndUserEmail::new(job.email.clone())))
|
||||
// Optional: specify whether the provider has verified the user's e-mail address.
|
||||
.set_email_verified(Some(true)),
|
||||
// OpenID Connect Providers may supply custom claims by providing a struct that
|
||||
// implements the AdditionalClaims trait. This requires manually using the
|
||||
// generic IdTokenClaims struct rather than the CoreIdTokenClaims type alias,
|
||||
// however.
|
||||
JobClaim {
|
||||
job_id: job_id.to_string(),
|
||||
path: job.script_path,
|
||||
flow_path,
|
||||
username: job.created_by,
|
||||
email: job.email,
|
||||
workspace: job.workspace_id,
|
||||
groups,
|
||||
},
|
||||
),
|
||||
// The private key used for signing the ID token. For confidential clients (those able
|
||||
// to maintain a client secret), a CoreHmacKey can also be used, in conjunction
|
||||
// with one of the CoreJwsSigningAlgorithm::HmacSha* signing algorithms. When using an
|
||||
// HMAC-based signing algorithm, the UTF-8 representation of the client secret should
|
||||
// be used as the HMAC key.
|
||||
&CoreRsaPrivateSigningKey::from_pem(
|
||||
&private_key,
|
||||
Some(JsonWebKeyId::new("windmill".to_string())),
|
||||
)
|
||||
.map_err(|e| anyhow::anyhow!("Invalid private key: {}", e))?,
|
||||
// Uses the RS256 signature algorithm. This crate supports any RS*, PS*, or HS*
|
||||
// signature algorithm.
|
||||
CoreJwsSigningAlgorithm::RsaSsaPkcs1V15Sha256,
|
||||
// When returning the ID token alongside an access token (e.g., in the Authorization Code
|
||||
// flow), it is recommended to pass the access token here to set the `at_hash` claim
|
||||
// automatically.
|
||||
None,
|
||||
// When returning the ID token alongside an authorization code (e.g., in the implicit
|
||||
// flow), it is recommended to pass the authorization code here to set the `c_hash` claim
|
||||
// automatically.
|
||||
None,
|
||||
)
|
||||
.map_err(|e| anyhow::anyhow!("Failed to generate token: {}", e))?;
|
||||
Ok(id_token.to_string())
|
||||
}
|
||||
@@ -544,6 +544,8 @@ pub async fn transform_json_value<'c>(
|
||||
flow_path,
|
||||
job.schedule_path.clone(),
|
||||
job.flow_step_id.clone(),
|
||||
job.root_job.map(|x| x.to_string()),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
|
||||
|
||||
@@ -69,6 +69,8 @@ async fn list_contextual_variables(
|
||||
Some("u/user/encapsulating_flow_path".to_string()),
|
||||
Some("u/user/triggering_flow_path".to_string()),
|
||||
Some("c".to_string()),
|
||||
Some("017e0ad5-f499-73b6-5488-92a61c5196dd".to_string()),
|
||||
Some("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c".to_string()),
|
||||
)
|
||||
.await
|
||||
.to_vec(),
|
||||
|
||||
@@ -144,7 +144,9 @@ pub async fn get_reserved_variables(
|
||||
flow_path: Option<String>,
|
||||
schedule_path: Option<String>,
|
||||
step_id: Option<String>,
|
||||
) -> [ContextualVariable; 15] {
|
||||
root_flow_id: Option<String>,
|
||||
jwt_token: Option<String>,
|
||||
) -> [ContextualVariable; 17] {
|
||||
let state_path = {
|
||||
let trigger = if schedule_path.is_some() {
|
||||
username.to_string()
|
||||
@@ -233,11 +235,17 @@ pub async fn get_reserved_variables(
|
||||
value: flow_id.unwrap_or_else(|| "".to_string()),
|
||||
description: "Job id of the encapsulating flow if the job is a flow step".to_string(),
|
||||
},
|
||||
ContextualVariable {
|
||||
name: "WM_ROOT_FLOW_JOB_ID".to_string(),
|
||||
value: root_flow_id.unwrap_or_else(|| "".to_string()),
|
||||
description: "Job id of the root flow if the job is a flow step".to_string(),
|
||||
},
|
||||
ContextualVariable {
|
||||
name: "WM_FLOW_PATH".to_string(),
|
||||
value: flow_path.unwrap_or_else(|| "".to_string()),
|
||||
description: "Path of the encapsulating flow if the job is a flow step".to_string(),
|
||||
},
|
||||
|
||||
ContextualVariable {
|
||||
name: "WM_SCHEDULE_PATH".to_string(),
|
||||
value: schedule_path.unwrap_or_else(|| "".to_string()),
|
||||
@@ -269,6 +277,11 @@ pub async fn get_reserved_variables(
|
||||
name: "WM_OBJECT_PATH".to_string(),
|
||||
value: object_path,
|
||||
description: "Script or flow step execution unique path, useful for storing results in an external service".to_string(),
|
||||
}
|
||||
},
|
||||
ContextualVariable {
|
||||
name: "WM_OIDC_JWT".to_string(),
|
||||
value: jwt_token.unwrap_or_else(|| "".to_string()),
|
||||
description: "OIDC JWT token (EE only)".to_string(),
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ path = "src/lib.rs"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
enterprise = ["windmill-queue/enterprise", "windmill-git-sync/enterprise", "dep:gcp_auth", "dep:jsonwebtoken", "dep:pem", "dep:sha2", "dep:tiberius", "dep:tokio-util"]
|
||||
enterprise = ["windmill-queue/enterprise", "windmill-git-sync/enterprise", "dep:gcp_auth", "dep:jsonwebtoken", "dep:openidconnect", "dep:pem", "dep:sha2", "dep:tiberius", "dep:tokio-util"]
|
||||
benchmark = ["windmill-queue/benchmark"]
|
||||
flamegraph = []
|
||||
|
||||
@@ -78,6 +78,7 @@ reqwest.workspace = true
|
||||
hex.workspace = true
|
||||
tiberius = { workspace = true, optional = true }
|
||||
tokio-util = { workspace = true, optional = true }
|
||||
openidconnect = { workspace = true, optional = true}
|
||||
|
||||
[build-dependencies]
|
||||
deno_fetch.workspace = true
|
||||
|
||||
@@ -733,6 +733,8 @@ pub async fn start_worker(
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
let context_envs = build_envs_map(context.to_vec()).await;
|
||||
|
||||
@@ -274,6 +274,8 @@ pub async fn transform_json_value(
|
||||
flow_path,
|
||||
job.schedule_path.clone(),
|
||||
job.flow_step_id.clone(),
|
||||
job.root_job.clone().map(|x| x.to_string()),
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -383,6 +385,8 @@ pub async fn get_reserved_variables(
|
||||
flow_path,
|
||||
job.schedule_path.clone(),
|
||||
job.flow_step_id.clone(),
|
||||
job.root_job.clone().map(|x| x.to_string()),
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.to_vec();
|
||||
|
||||
@@ -48,7 +48,7 @@ pub async fn handle_dedicated_process(
|
||||
job_dir: &str,
|
||||
context_envs: HashMap<String, String>,
|
||||
envs: HashMap<String, String>,
|
||||
reserved_variables: [variables::ContextualVariable; 15],
|
||||
reserved_variables: [variables::ContextualVariable; 17],
|
||||
common_bun_proc_envs: HashMap<String, String>,
|
||||
args: Vec<&str>,
|
||||
mut killpill_rx: tokio::sync::broadcast::Receiver<()>,
|
||||
|
||||
@@ -423,6 +423,8 @@ pub async fn start_worker(
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
let context_envs = build_envs_map(context.to_vec()).await;
|
||||
|
||||
@@ -888,6 +888,8 @@ pub async fn start_worker(
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.to_vec();
|
||||
@@ -1005,6 +1007,8 @@ for line in sys.stdin:
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.await;
|
||||
|
||||
|
||||
@@ -113,6 +113,7 @@ pub async fn create_token_for_owner_in_bg(
|
||||
let w_id = job.workspace_id.clone();
|
||||
let owner = job.permissioned_as.clone();
|
||||
let email = job.email.clone();
|
||||
let job_id = job.id.clone();
|
||||
tokio::spawn(async move {
|
||||
let token = create_token_for_owner(
|
||||
&db.clone(),
|
||||
@@ -121,6 +122,7 @@ pub async fn create_token_for_owner_in_bg(
|
||||
"ephemeral-script",
|
||||
*SCRIPT_TOKEN_EXPIRY,
|
||||
&email,
|
||||
&job_id,
|
||||
)
|
||||
.await
|
||||
.expect("could not create job token");
|
||||
@@ -138,6 +140,7 @@ pub async fn create_token_for_owner(
|
||||
label: &str,
|
||||
expires_in: u64,
|
||||
email: &str,
|
||||
job_id: &Uuid,
|
||||
) -> error::Result<String> {
|
||||
// TODO: Bad implementation. We should not have access to this DB here.
|
||||
if let Some(token) = JOB_TOKEN.as_ref() {
|
||||
@@ -156,15 +159,16 @@ pub async fn create_token_for_owner(
|
||||
|
||||
sqlx::query_scalar!(
|
||||
"INSERT INTO token
|
||||
(workspace_id, token, owner, label, expiration, super_admin, email)
|
||||
VALUES ($1, $2, $3, $4, now() + ($5 || ' seconds')::interval, $6, $7)",
|
||||
(workspace_id, token, owner, label, expiration, super_admin, email, job)
|
||||
VALUES ($1, $2, $3, $4, now() + ($5 || ' seconds')::interval, $6, $7, $8)",
|
||||
&w_id,
|
||||
token,
|
||||
owner,
|
||||
label,
|
||||
expires_in.to_string(),
|
||||
is_super_admin,
|
||||
email
|
||||
email,
|
||||
job_id
|
||||
)
|
||||
.execute(db)
|
||||
.await?;
|
||||
|
||||
@@ -111,7 +111,8 @@
|
||||
workspace: $workspaceStore!,
|
||||
id: job,
|
||||
requestBody: {
|
||||
reason: 'Connection did not resolve after 5s'
|
||||
reason:
|
||||
'Connection did not resolve after 5s. Do you have native workers or a worker group listening to the proper tag available?'
|
||||
}
|
||||
})
|
||||
} catch (err) {
|
||||
|
||||
@@ -33,8 +33,14 @@ export const settings: Record<string, Setting[]> = {
|
||||
fieldType: 'text',
|
||||
placeholder: 'https://windmill.com',
|
||||
storage: 'setting',
|
||||
error: 'Base url must start with http:// or https:// and not end with / or a space',
|
||||
isValid: (value: string | undefined) =>
|
||||
value ? value?.startsWith('http') && value.includes('://') && !value?.endsWith('/') : true
|
||||
value
|
||||
? value?.startsWith('http') &&
|
||||
value.includes('://') &&
|
||||
!value?.endsWith('/') &&
|
||||
!value?.endsWith(' ')
|
||||
: true
|
||||
},
|
||||
{
|
||||
label: 'Request Size Limit In MB',
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
windmill-api/
|
||||
|
||||
Binary file not shown.
BIN
Binary file not shown.
@@ -219,6 +219,9 @@ class Windmill:
|
||||
def get_job(self, job_id: str) -> dict:
|
||||
return self.get(f"/w/{self.workspace}/jobs_u/get/{job_id}").json()
|
||||
|
||||
def get_id_token(self, audience: str) -> dict:
|
||||
return self.get(f"/w/{self.workspace}/oidc/token/{audience}").text
|
||||
|
||||
def get_job_status(self, job_id: str) -> JobStatus:
|
||||
job = self.get_job(job_id)
|
||||
job_type = job.get("type", "")
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,6 +1,12 @@
|
||||
import { ResourceService, VariableService, JobService, HelpersService } from "./index";
|
||||
import {
|
||||
ResourceService,
|
||||
VariableService,
|
||||
JobService,
|
||||
HelpersService,
|
||||
} from "./index";
|
||||
import { OpenAPI } from "./index";
|
||||
import type { DenoS3LightClientSettings } from "./index";
|
||||
import { OidcService } from "./src";
|
||||
|
||||
export {
|
||||
AdminService,
|
||||
@@ -269,18 +275,20 @@ export async function databaseUrlFromResource(path: string): Promise<string> {
|
||||
// });
|
||||
// }
|
||||
|
||||
export async function denoS3LightClientSettings(s3_resource_path: string | undefined): Promise<DenoS3LightClientSettings> {
|
||||
export async function denoS3LightClientSettings(
|
||||
s3_resource_path: string | undefined
|
||||
): Promise<DenoS3LightClientSettings> {
|
||||
!clientSet && setClient();
|
||||
const workspace = getWorkspace();
|
||||
const s3Resource = await HelpersService.s3ResourceInfo({
|
||||
workspace: workspace,
|
||||
requestBody: {
|
||||
s3_resource_path: s3_resource_path
|
||||
}
|
||||
s3_resource_path: s3_resource_path,
|
||||
},
|
||||
});
|
||||
let settings: DenoS3LightClientSettings = {
|
||||
...s3Resource,
|
||||
}
|
||||
};
|
||||
return settings;
|
||||
}
|
||||
|
||||
@@ -316,6 +324,20 @@ export function getResumeEndpoints(approver?: string): Promise<{
|
||||
return getResumeUrls(approver);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an OIDC jwt token for auth to external services (e.g: Vault, AWS) (ee only)
|
||||
* @param audience audience of the token
|
||||
* @returns jwt token
|
||||
*/
|
||||
export async function getIdToken(audience: string): Promise<string> {
|
||||
!clientSet && setClient();
|
||||
const workspace = getWorkspace();
|
||||
return await OidcService.getOidcToken({
|
||||
workspace,
|
||||
audience,
|
||||
});
|
||||
}
|
||||
|
||||
export function base64ToUint8Array(data: string): Uint8Array {
|
||||
return Uint8Array.from(atob(data), (c) => c.charCodeAt(0));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user