From e8ed4783b2ff692951ec16be35d6b5553728b86f Mon Sep 17 00:00:00 2001 From: Guillaume Bouvignies Date: Thu, 15 Feb 2024 17:02:45 +0100 Subject: [PATCH] feat: Workspace encryption key can be manually updated (#3223) * feat: Workspace encryption key can be manually updated * sqlx prepare --- ...a039a6ea6697e5a49a633b767c052aa3e0a18.json | 1 - ...3ee6b27c836197df6454d3bb5c59441c34f44.json | 1 - ...bd26be90efb17a4323b9673e93ff88513942a.json | 1 - ...2e47f57de0f073d3ce3bc7d21a7e404a83b5c.json | 1 - ...641ab71cc1b5049a104e0699e81484a61ae63.json | 22 ++++ ...0bccb19beeb9ddfa308ca97f254cd5ba8157e.json | 1 - ...7f5033b9c9afc344d9c3e385ba20a3ad2197a.json | 2 +- ...f7f6231a44b6ef5a52754074d136007f4f72a.json | 1 - ...337574398d63a6ab85171e43c3ab76400ec22.json | 15 +++ ...eda837cc63e4d8be912c0b5bfeea4a0c8db2e.json | 1 - ...550027cf7a3bb202269e8dda92d31bc8789dd.json | 34 ++++++ ...2433e1485324ff7dc802fe75d21c8c6db1d42.json | 1 - ...f22991f51e1c945efc2924df6253d62b83bba.json | 1 - backend/windmill-api/openapi-deref.yaml | 75 ++++++++++++- backend/windmill-api/openapi.yaml | 48 ++++++++ backend/windmill-api/src/openai.rs | 6 +- backend/windmill-api/src/variables.rs | 14 +-- backend/windmill-api/src/workspaces.rs | 105 +++++++++++++++++- .../(logged)/workspace_settings/+page.svelte | 94 +++++++++++++++- 19 files changed, 396 insertions(+), 28 deletions(-) create mode 100644 backend/.sqlx/query-3a637063e1d256639b0e900606b641ab71cc1b5049a104e0699e81484a61ae63.json create mode 100644 backend/.sqlx/query-7ee6056b7fb40b312333b489788337574398d63a6ab85171e43c3ab76400ec22.json create mode 100644 backend/.sqlx/query-b656f38e5f1d6a0799767a775b8550027cf7a3bb202269e8dda92d31bc8789dd.json diff --git a/backend/.sqlx/query-0a686ca61444d7ad7484071727aa039a6ea6697e5a49a633b767c052aa3e0a18.json b/backend/.sqlx/query-0a686ca61444d7ad7484071727aa039a6ea6697e5a49a633b767c052aa3e0a18.json index aa608ecc57..053857a0a0 100644 --- a/backend/.sqlx/query-0a686ca61444d7ad7484071727aa039a6ea6697e5a49a633b767c052aa3e0a18.json +++ b/backend/.sqlx/query-0a686ca61444d7ad7484071727aa039a6ea6697e5a49a633b767c052aa3e0a18.json @@ -48,7 +48,6 @@ "bash", "postgresql", "nativets", - "Nativets", "bun", "mysql", "bigquery", diff --git a/backend/.sqlx/query-254776959f60455a00a2c29a1783ee6b27c836197df6454d3bb5c59441c34f44.json b/backend/.sqlx/query-254776959f60455a00a2c29a1783ee6b27c836197df6454d3bb5c59441c34f44.json index b2421d64f2..03bd3e00c1 100644 --- a/backend/.sqlx/query-254776959f60455a00a2c29a1783ee6b27c836197df6454d3bb5c59441c34f44.json +++ b/backend/.sqlx/query-254776959f60455a00a2c29a1783ee6b27c836197df6454d3bb5c59441c34f44.json @@ -69,7 +69,6 @@ "bash", "postgresql", "nativets", - "Nativets", "bun", "mysql", "bigquery", diff --git a/backend/.sqlx/query-260feb784bb0b223bd9276d6a82bd26be90efb17a4323b9673e93ff88513942a.json b/backend/.sqlx/query-260feb784bb0b223bd9276d6a82bd26be90efb17a4323b9673e93ff88513942a.json index d3ccc22ef2..38795ced69 100644 --- a/backend/.sqlx/query-260feb784bb0b223bd9276d6a82bd26be90efb17a4323b9673e93ff88513942a.json +++ b/backend/.sqlx/query-260feb784bb0b223bd9276d6a82bd26be90efb17a4323b9673e93ff88513942a.json @@ -28,7 +28,6 @@ "bash", "postgresql", "nativets", - "Nativets", "bun", "mysql", "bigquery", diff --git a/backend/.sqlx/query-2f42460fdd8aa125c8fd46b3cd02e47f57de0f073d3ce3bc7d21a7e404a83b5c.json b/backend/.sqlx/query-2f42460fdd8aa125c8fd46b3cd02e47f57de0f073d3ce3bc7d21a7e404a83b5c.json index c9110033a5..030a85c000 100644 --- a/backend/.sqlx/query-2f42460fdd8aa125c8fd46b3cd02e47f57de0f073d3ce3bc7d21a7e404a83b5c.json +++ b/backend/.sqlx/query-2f42460fdd8aa125c8fd46b3cd02e47f57de0f073d3ce3bc7d21a7e404a83b5c.json @@ -42,7 +42,6 @@ "bash", "postgresql", "nativets", - "Nativets", "bun", "mysql", "bigquery", diff --git a/backend/.sqlx/query-3a637063e1d256639b0e900606b641ab71cc1b5049a104e0699e81484a61ae63.json b/backend/.sqlx/query-3a637063e1d256639b0e900606b641ab71cc1b5049a104e0699e81484a61ae63.json new file mode 100644 index 0000000000..ee0079608f --- /dev/null +++ b/backend/.sqlx/query-3a637063e1d256639b0e900606b641ab71cc1b5049a104e0699e81484a61ae63.json @@ -0,0 +1,22 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT key FROM workspace_key WHERE workspace_id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "key", + "type_info": "Varchar" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false + ] + }, + "hash": "3a637063e1d256639b0e900606b641ab71cc1b5049a104e0699e81484a61ae63" +} diff --git a/backend/.sqlx/query-620ddf29c5e867079df4c2aa6e80bccb19beeb9ddfa308ca97f254cd5ba8157e.json b/backend/.sqlx/query-620ddf29c5e867079df4c2aa6e80bccb19beeb9ddfa308ca97f254cd5ba8157e.json index 89583ff5ef..4598ac08df 100644 --- a/backend/.sqlx/query-620ddf29c5e867079df4c2aa6e80bccb19beeb9ddfa308ca97f254cd5ba8157e.json +++ b/backend/.sqlx/query-620ddf29c5e867079df4c2aa6e80bccb19beeb9ddfa308ca97f254cd5ba8157e.json @@ -62,7 +62,6 @@ "bash", "postgresql", "nativets", - "Nativets", "bun", "mysql", "bigquery", diff --git a/backend/.sqlx/query-661f472ff3860983322162420457f5033b9c9afc344d9c3e385ba20a3ad2197a.json b/backend/.sqlx/query-661f472ff3860983322162420457f5033b9c9afc344d9c3e385ba20a3ad2197a.json index 75b8108281..1fa370e682 100644 --- a/backend/.sqlx/query-661f472ff3860983322162420457f5033b9c9afc344d9c3e385ba20a3ad2197a.json +++ b/backend/.sqlx/query-661f472ff3860983322162420457f5033b9c9afc344d9c3e385ba20a3ad2197a.json @@ -5,7 +5,7 @@ "columns": [ { "ordinal": 0, - "name": "?column?", + "name": "bool", "type_info": "Bool" } ], diff --git a/backend/.sqlx/query-6b313cc9a57ae3c943bda4a3213f7f6231a44b6ef5a52754074d136007f4f72a.json b/backend/.sqlx/query-6b313cc9a57ae3c943bda4a3213f7f6231a44b6ef5a52754074d136007f4f72a.json index 7d9d04bc37..72c175aff7 100644 --- a/backend/.sqlx/query-6b313cc9a57ae3c943bda4a3213f7f6231a44b6ef5a52754074d136007f4f72a.json +++ b/backend/.sqlx/query-6b313cc9a57ae3c943bda4a3213f7f6231a44b6ef5a52754074d136007f4f72a.json @@ -37,7 +37,6 @@ "bash", "postgresql", "nativets", - "Nativets", "bun", "mysql", "bigquery", diff --git a/backend/.sqlx/query-7ee6056b7fb40b312333b489788337574398d63a6ab85171e43c3ab76400ec22.json b/backend/.sqlx/query-7ee6056b7fb40b312333b489788337574398d63a6ab85171e43c3ab76400ec22.json new file mode 100644 index 0000000000..846bda756e --- /dev/null +++ b/backend/.sqlx/query-7ee6056b7fb40b312333b489788337574398d63a6ab85171e43c3ab76400ec22.json @@ -0,0 +1,15 @@ +{ + "db_name": "PostgreSQL", + "query": "UPDATE workspace_key SET key = $1 WHERE workspace_id = $2", + "describe": { + "columns": [], + "parameters": { + "Left": [ + "Varchar", + "Text" + ] + }, + "nullable": [] + }, + "hash": "7ee6056b7fb40b312333b489788337574398d63a6ab85171e43c3ab76400ec22" +} diff --git a/backend/.sqlx/query-9d3556319411a27a875bf6cf0e5eda837cc63e4d8be912c0b5bfeea4a0c8db2e.json b/backend/.sqlx/query-9d3556319411a27a875bf6cf0e5eda837cc63e4d8be912c0b5bfeea4a0c8db2e.json index 983c1586f0..f296c4afc6 100644 --- a/backend/.sqlx/query-9d3556319411a27a875bf6cf0e5eda837cc63e4d8be912c0b5bfeea4a0c8db2e.json +++ b/backend/.sqlx/query-9d3556319411a27a875bf6cf0e5eda837cc63e4d8be912c0b5bfeea4a0c8db2e.json @@ -42,7 +42,6 @@ "bash", "postgresql", "nativets", - "Nativets", "bun", "mysql", "bigquery", diff --git a/backend/.sqlx/query-b656f38e5f1d6a0799767a775b8550027cf7a3bb202269e8dda92d31bc8789dd.json b/backend/.sqlx/query-b656f38e5f1d6a0799767a775b8550027cf7a3bb202269e8dda92d31bc8789dd.json new file mode 100644 index 0000000000..6ad2fc0ae1 --- /dev/null +++ b/backend/.sqlx/query-b656f38e5f1d6a0799767a775b8550027cf7a3bb202269e8dda92d31bc8789dd.json @@ -0,0 +1,34 @@ +{ + "db_name": "PostgreSQL", + "query": "SELECT path, value, is_secret FROM variable WHERE workspace_id = $1", + "describe": { + "columns": [ + { + "ordinal": 0, + "name": "path", + "type_info": "Varchar" + }, + { + "ordinal": 1, + "name": "value", + "type_info": "Varchar" + }, + { + "ordinal": 2, + "name": "is_secret", + "type_info": "Bool" + } + ], + "parameters": { + "Left": [ + "Text" + ] + }, + "nullable": [ + false, + false, + false + ] + }, + "hash": "b656f38e5f1d6a0799767a775b8550027cf7a3bb202269e8dda92d31bc8789dd" +} diff --git a/backend/.sqlx/query-b69891c25dd029b1a54e97ace292433e1485324ff7dc802fe75d21c8c6db1d42.json b/backend/.sqlx/query-b69891c25dd029b1a54e97ace292433e1485324ff7dc802fe75d21c8c6db1d42.json index 86a1402ad0..f95d9d95b2 100644 --- a/backend/.sqlx/query-b69891c25dd029b1a54e97ace292433e1485324ff7dc802fe75d21c8c6db1d42.json +++ b/backend/.sqlx/query-b69891c25dd029b1a54e97ace292433e1485324ff7dc802fe75d21c8c6db1d42.json @@ -42,7 +42,6 @@ "bash", "postgresql", "nativets", - "Nativets", "bun", "mysql", "bigquery", diff --git a/backend/.sqlx/query-ef132ac8d79579b08d7359789b6f22991f51e1c945efc2924df6253d62b83bba.json b/backend/.sqlx/query-ef132ac8d79579b08d7359789b6f22991f51e1c945efc2924df6253d62b83bba.json index 9ea1ab28f3..73af3f369c 100644 --- a/backend/.sqlx/query-ef132ac8d79579b08d7359789b6f22991f51e1c945efc2924df6253d62b83bba.json +++ b/backend/.sqlx/query-ef132ac8d79579b08d7359789b6f22991f51e1c945efc2924df6253d62b83bba.json @@ -42,7 +42,6 @@ "bash", "postgresql", "nativets", - "Nativets", "bun", "mysql", "bigquery", diff --git a/backend/windmill-api/openapi-deref.yaml b/backend/windmill-api/openapi-deref.yaml index e441c65507..9654b10550 100644 --- a/backend/windmill-api/openapi-deref.yaml +++ b/backend/windmill-api/openapi-deref.yaml @@ -1,6 +1,6 @@ openapi: 3.0.3 info: - version: 1.268.0 + version: 1.269.0 title: Windmill API contact: name: Windmill Team @@ -1961,6 +1961,58 @@ paths: text/plain: schema: type: string + /w/{workspace}/workspaces/encryption_key: + get: + summary: retrieves the encryption key for this workspace + operationId: getWorkspaceEncryptionKey + tags: + - workspace + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + responses: + '200': + description: status + content: + application/json: + schema: + type: object + properties: + key: + type: string + required: + - key + post: + summary: update the encryption key for this workspace + operationId: setWorkspaceEncryptionKey + tags: + - workspace + parameters: + - name: workspace + in: path + required: true + schema: *ref_0 + requestBody: + description: New encryption key + required: true + content: + application/json: + schema: + type: object + properties: + new_key: + type: string + required: + - new_key + responses: + '200': + description: status + content: + text/plain: + schema: + type: string /w/{workspace}/workspaces/default_app: get: summary: get default app for workspace @@ -7109,6 +7161,13 @@ paths: in: query schema: &ref_64 type: string + - name: all_workspaces + description: >- + get jobs from all workspaces (only valid if request come from the + `admins` workspace) + in: query + schema: + type: boolean responses: '200': description: All queued jobs @@ -7334,6 +7393,13 @@ paths: in: path required: true schema: *ref_0 + - name: all_workspaces + description: >- + get jobs from all workspaces (only valid if request come from the + `admins` workspace) + in: query + schema: + type: boolean responses: '200': description: queue count @@ -7706,6 +7772,13 @@ paths: in: query schema: type: boolean + - name: all_workspaces + description: >- + get jobs from all workspaces (only valid if request come from the + `admins` workspace) + in: query + schema: + type: boolean responses: '200': description: All jobs diff --git a/backend/windmill-api/openapi.yaml b/backend/windmill-api/openapi.yaml index 7f3e9778be..3ba52aca64 100644 --- a/backend/windmill-api/openapi.yaml +++ b/backend/windmill-api/openapi.yaml @@ -1574,6 +1574,54 @@ paths: schema: type: string + /w/{workspace}/workspaces/encryption_key: + get: + summary: retrieves the encryption key for this workspace + operationId: getWorkspaceEncryptionKey + tags: + - workspace + parameters: + - $ref: "#/components/parameters/WorkspaceId" + responses: + "200": + description: status + content: + application/json: + schema: + type: object + properties: + key: + type: string + required: + - key + post: + summary: update the encryption key for this workspace + operationId: setWorkspaceEncryptionKey + tags: + - workspace + parameters: + - $ref: "#/components/parameters/WorkspaceId" + requestBody: + description: New encryption key + required: true + content: + application/json: + schema: + type: object + properties: + new_key: + type: string + required: + - new_key + + responses: + "200": + description: status + content: + text/plain: + schema: + type: string + /w/{workspace}/workspaces/default_app: get: summary: get default app for workspace diff --git a/backend/windmill-api/src/openai.rs b/backend/windmill-api/src/openai.rs index c983a51805..c124252c0a 100644 --- a/backend/windmill-api/src/openai.rs +++ b/backend/windmill-api/src/openai.rs @@ -12,7 +12,6 @@ use axum::{ routing::post, Router, }; -use magic_crypt::MagicCryptTrait; use quick_cache::sync::Cache; use serde_json::value::RawValue; use windmill_audit::audit_ee::audit_log; @@ -22,6 +21,7 @@ use windmill_common::{ variables::build_crypt, }; +use crate::variables::decrypt; use serde::Deserialize; pub fn workspaced_service() -> Router { @@ -73,9 +73,7 @@ async fn get_variable_or_self(path: String, db: &DB, w_id: &String) -> Result( } else if !value.is_empty() { let mc = build_crypt(&mut tx, &w_id).await?; tx.commit().await?; - - mc.decrypt_base64_to_string(value) - .map_err(|e| Error::InternalErr(e.to_string()))? + decrypt(&mc, value)? } else { "".to_string() } @@ -653,3 +648,8 @@ pub async fn get_value_internal<'c>( pub fn encrypt(mc: &MagicCrypt256, value: &str) -> String { mc.encrypt_str_to_base64(value) } + +pub fn decrypt(mc: &MagicCrypt256, value: String) -> Result { + mc.decrypt_base64_to_string(value) + .map_err(|e| Error::InternalErr(e.to_string())) +} diff --git a/backend/windmill-api/src/workspaces.rs b/backend/windmill-api/src/workspaces.rs index 3107e8105e..2fb7347b20 100644 --- a/backend/windmill-api/src/workspaces.rs +++ b/backend/windmill-api/src/workspaces.rs @@ -33,7 +33,6 @@ use axum::{ use chrono::Utc; #[cfg(feature = "stripe")] use chrono::{Datelike, TimeZone, Timelike}; -use magic_crypt::MagicCryptTrait; use regex::Regex; #[cfg(feature = "stripe")] use stripe::CustomerId; @@ -57,6 +56,7 @@ use windmill_common::{ }; use windmill_queue::QueueTransaction; +use crate::variables::{decrypt, encrypt}; use hyper::{header, StatusCode}; use serde::{Deserialize, Serialize}; use serde_json::{json, Map}; @@ -64,6 +64,11 @@ use sqlx::{FromRow, Postgres, Transaction}; use tempfile::TempDir; use tokio::fs::File; use tokio_util::io::ReaderStream; +use windmill_common::utils::not_found_if_none; + +lazy_static::lazy_static! { + static ref WORKSPACE_KEY_REGEXP: Regex = Regex::new("^[a-zA-Z0-9]{64}$").unwrap(); +} pub fn workspaced_service() -> Router { let router = Router::new() @@ -95,6 +100,10 @@ pub fn workspaced_service() -> Router { .route("/edit_git_sync_config", post(edit_git_sync_config)) .route("/edit_default_app", post(edit_default_app)) .route("/default_app", get(get_default_app)) + .route( + "/encryption_key", + get(get_encryption_key).post(set_encryption_key), + ) .route("/leave", post(leave_workspace)); #[cfg(feature = "stripe")] @@ -1334,6 +1343,95 @@ async fn edit_error_handler( Ok(format!("Edit error_handler for workspace {}", &w_id)) } +#[derive(Serialize)] +pub struct GetEncryptionKeyResponse { + key: String, +} + +async fn get_encryption_key( + authed: ApiAuthed, + Extension(db): Extension, + Path(w_id): Path, +) -> JsonResult { + require_super_admin(&db, &authed.email).await?; + + let encryption_key_opt = sqlx::query_scalar!( + "SELECT key FROM workspace_key WHERE workspace_id = $1", + w_id + ) + .fetch_optional(&db) + .await?; + + let encryption_key = not_found_if_none(encryption_key_opt, "workspace_encryption_key", w_id)?; + return Ok(Json(GetEncryptionKeyResponse { key: encryption_key })); +} + +#[derive(Deserialize)] +struct SetEncryptionKeyRequest { + new_key: String, +} + +async fn set_encryption_key( + authed: ApiAuthed, + Extension(db): Extension, + Path(w_id): Path, + Json(request): Json, +) -> Result<()> { + require_super_admin(&db, &authed.email).await?; + + if !WORKSPACE_KEY_REGEXP.is_match(request.new_key.as_str()) { + return Err(Error::BadRequest( + "Encryption key should be an alphanumeric string of 64 characters".to_string(), + )); + } + + let mut tx = db.begin().await?; + let previous_encryption_key = build_crypt(&mut tx, w_id.as_str()).await?; + + sqlx::query!( + "UPDATE workspace_key SET key = $1 WHERE workspace_id = $2", + request.new_key.clone(), + w_id + ) + .execute(&mut *tx) + .await?; + let new_encryption_key = build_crypt(&mut tx, w_id.as_str()).await?; + + let mut truncated_new_key = request.new_key.clone(); + truncated_new_key.truncate(8); + tracing::warn!( + "Re-encrypting all secrets for workspace {}. New key is {}***", + w_id, + truncated_new_key + ); + + let all_variables = sqlx::query!( + "SELECT path, value, is_secret FROM variable WHERE workspace_id = $1", + w_id + ) + .fetch_all(&mut *tx) + .await?; + + for variable in all_variables { + if !variable.is_secret { + continue; + } + let decrypted_value = decrypt(&previous_encryption_key, variable.value)?; + let new_encrypted_value = encrypt(&new_encryption_key, decrypted_value.as_str()); + sqlx::query!( + "UPDATE variable SET value = $1 WHERE workspace_id = $2 AND path = $3", + new_encrypted_value, + w_id, + variable.path + ) + .execute(&mut *tx) + .await?; + } + + tx.commit().await?; + return Ok(()); +} + async fn list_workspaces_as_super_admin( authed: ApiAuthed, Extension(db): Extension, @@ -2321,10 +2419,7 @@ async fn tarball_workspace( && var.value.is_some() && var.is_secret { - var.value = Some( - mc.decrypt_base64_to_string(var.value.unwrap()) - .map_err(|e| Error::InternalErr(e.to_string()))?, - ); + var.value = Some(decrypt(&mc, var.value.unwrap())?); } let var_str = &to_string_without_metadata(&var, false).unwrap(); archive diff --git a/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte b/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte index 541c1ebe0c..c2c6878ed7 100644 --- a/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte +++ b/frontend/src/routes/(root)/(logged)/workspace_settings/+page.svelte @@ -33,7 +33,17 @@ } from '$lib/stores' import { sendUserToast } from '$lib/toast' import { setQueryWithoutLoad, emptyString, tryEvery } from '$lib/utils' - import { Scroll, Slack, XCircle, RotateCw, CheckCircle2, X, Plus, Loader2 } from 'lucide-svelte' + import { + Scroll, + Slack, + XCircle, + RotateCw, + CheckCircle2, + X, + Plus, + Loader2, + Save + } from 'lucide-svelte' import BarsStaggered from '$lib/components/icons/BarsStaggered.svelte' import PremiumInfo from '$lib/components/settings/PremiumInfo.svelte' @@ -101,6 +111,10 @@ status: 'running' | 'success' | 'failure' | undefined }[] let workspaceDefaultAppPath: string | undefined = undefined + let workspaceEncryptionKey: string | undefined = undefined + let editedWorkspaceEncryptionKey: string | undefined = undefined + let workspaceReencryptionInProgress: boolean = false + let encryptionKeyRegex = /^[a-zA-Z0-9]{64}$/ let codeCompletionEnabled: boolean = false let tab = ($page.url.searchParams.get('tab') as @@ -338,6 +352,37 @@ } } + async function loadWorkspaceEncryptionKey(): Promise { + let resp = await WorkspaceService.getWorkspaceEncryptionKey({ + workspace: $workspaceStore! + }) + workspaceEncryptionKey = resp.key + editedWorkspaceEncryptionKey = resp.key + } + + async function setWorkspaceEncryptionKey(): Promise { + if ( + emptyString(editedWorkspaceEncryptionKey) || + workspaceEncryptionKey === editedWorkspaceEncryptionKey + ) { + return + } + const timeStart = new Date().getTime() + workspaceReencryptionInProgress = true + await WorkspaceService.setWorkspaceEncryptionKey({ + workspace: $workspaceStore!, + requestBody: { + new_key: editedWorkspaceEncryptionKey ?? '' // cannot be undefined at this point + } + }) + await loadWorkspaceEncryptionKey() + const timeEnd = new Date().getTime() + sendUserToast('All workspace secrets have been re-encrypted with the new key') + setTimeout(() => { + workspaceReencryptionInProgress = false + }, 1000 - (timeEnd - timeStart)) + } + async function loadSettings(): Promise { const settings = await WorkspaceService.getSettings({ workspace: $workspaceStore! }) team_name = settings.slack_name @@ -601,6 +646,9 @@
Default App
+ +
Encryption
+
Delete Workspace
@@ -1367,6 +1415,50 @@ git push {/key} + {:else if tab == 'encryption'} + + + When updating the encryption key of a workspace, all secrets will be re-encrypted with the + new key and the previous key will be replaced by the new one. +
+ If you're manually updating the key to match another workspace key from another Windmill instance, + make sure not to use the 'SECRET_SALT' environment variable or, if you're using it, make sure + it the salt matches across both instances. +
+
+ +
+
Workspace encryption key
+
+ + +
+ {#if !emptyString(editedWorkspaceEncryptionKey) && !encryptionKeyRegex.test(editedWorkspaceEncryptionKey ?? '')} +
+ Key invalid - it should be 64 characters long and only contain letters and numbers. +
+ {/if} {/if} {:else}