windmill-components 1.665.1 → 1.677.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/sharedUtils/assets/tokens/colorTokensConfig.d.ts +2 -0
- package/dist/sharedUtils/base.d.ts +1 -0
- package/dist/sharedUtils/cloud.d.ts +1 -0
- package/dist/sharedUtils/common.d.ts +111 -0
- package/dist/sharedUtils/components/apps/components/display/dbtable/queries/count.d.ts +5 -0
- package/dist/sharedUtils/components/apps/components/display/dbtable/queries/delete.d.ts +5 -0
- package/dist/sharedUtils/components/apps/components/display/dbtable/queries/insert.d.ts +5 -0
- package/dist/sharedUtils/components/apps/components/display/dbtable/queries/select.d.ts +13 -0
- package/dist/sharedUtils/components/apps/components/display/dbtable/queries/update.d.ts +11 -0
- package/dist/sharedUtils/components/apps/components/display/dbtable/utils.d.ts +95 -0
- package/dist/sharedUtils/components/apps/editor/appPolicy.d.ts +6 -0
- package/dist/sharedUtils/components/apps/editor/appUtilsCore.d.ts +7 -0
- package/dist/sharedUtils/components/apps/editor/appUtilsS3.d.ts +33 -0
- package/dist/sharedUtils/components/apps/editor/commonAppUtils.d.ts +10 -0
- package/dist/sharedUtils/components/apps/editor/component/components.d.ts +5371 -0
- package/dist/sharedUtils/components/apps/editor/component/default-codes.d.ts +3 -0
- package/dist/sharedUtils/components/apps/editor/component/index.d.ts +3 -0
- package/dist/sharedUtils/components/apps/editor/component/sets.d.ts +7 -0
- package/dist/sharedUtils/components/apps/editor/componentsPanel/componentDefaultProps.d.ts +3 -0
- package/dist/sharedUtils/components/apps/gridUtils.d.ts +14 -0
- package/dist/sharedUtils/components/apps/inputType.d.ts +178 -0
- package/dist/sharedUtils/components/apps/rx.d.ts +29 -0
- package/dist/sharedUtils/components/apps/sharedTypes.d.ts +21 -0
- package/dist/sharedUtils/components/apps/types.d.ts +274 -0
- package/dist/sharedUtils/components/assets/lib.d.ts +25 -0
- package/dist/sharedUtils/components/common/alert/model.d.ts +2 -0
- package/dist/sharedUtils/components/common/badge/model.d.ts +8 -0
- package/dist/sharedUtils/components/common/button/model.d.ts +45 -0
- package/dist/sharedUtils/components/common/fileInput/model.d.ts +1 -0
- package/dist/sharedUtils/components/common/index.d.ts +24 -0
- package/dist/sharedUtils/components/common/skeleton/model.d.ts +21 -0
- package/dist/sharedUtils/components/dbTypes.d.ts +14 -0
- package/dist/sharedUtils/components/diff_drawer.d.ts +26 -0
- package/dist/sharedUtils/components/ducklake.d.ts +1 -0
- package/dist/sharedUtils/components/flows/scheduleUtils.d.ts +7 -0
- package/dist/sharedUtils/components/icons/index.d.ts +101 -0
- package/dist/sharedUtils/components/random_positive_adjetive.d.ts +1 -0
- package/dist/sharedUtils/components/raw_apps/rawAppPolicy.d.ts +10 -0
- package/dist/sharedUtils/components/raw_apps/utils.d.ts +15 -0
- package/dist/sharedUtils/components/triggers/email/utils.d.ts +4 -0
- package/dist/sharedUtils/components/triggers/gcp/utils.d.ts +2 -0
- package/dist/sharedUtils/components/triggers/http/utils.d.ts +11 -0
- package/dist/sharedUtils/components/triggers/kafka/utils.d.ts +2 -0
- package/dist/sharedUtils/components/triggers/mqtt/utils.d.ts +2 -0
- package/dist/sharedUtils/components/triggers/nats/utils.d.ts +2 -0
- package/dist/sharedUtils/components/triggers/postgres/utils.d.ts +8 -0
- package/dist/sharedUtils/components/triggers/sqs/utils.d.ts +2 -0
- package/dist/sharedUtils/components/triggers/triggers.svelte.d.ts +32 -0
- package/dist/sharedUtils/components/triggers/utils.d.ts +80 -0
- package/dist/sharedUtils/components/triggers/websocket/utils.d.ts +2 -0
- package/dist/sharedUtils/components/triggers.d.ts +20 -0
- package/dist/sharedUtils/gen/core/ApiError.d.ts +10 -0
- package/dist/sharedUtils/gen/core/ApiRequestOptions.d.ts +13 -0
- package/dist/sharedUtils/gen/core/ApiResult.d.ts +7 -0
- package/dist/sharedUtils/gen/core/CancelablePromise.d.ts +26 -0
- package/dist/sharedUtils/gen/core/OpenAPI.d.ts +27 -0
- package/dist/sharedUtils/gen/core/request.d.ts +29 -0
- package/dist/sharedUtils/gen/index.d.ts +6 -0
- package/dist/sharedUtils/gen/schemas.gen.d.ts +7036 -0
- package/dist/sharedUtils/gen/services.gen.d.ts +6047 -0
- package/dist/sharedUtils/gen/types.gen.d.ts +21881 -0
- package/dist/sharedUtils/history.svelte.d.ts +9 -0
- package/dist/sharedUtils/hub.d.ts +49 -0
- package/dist/sharedUtils/jsr.json +6 -0
- package/dist/sharedUtils/lib.d.ts +5 -0
- package/dist/sharedUtils/lib.es.js +1588 -0
- package/dist/sharedUtils/package.json +12 -0
- package/dist/sharedUtils/schema.d.ts +3 -0
- package/dist/sharedUtils/stores.d.ts +97 -0
- package/dist/sharedUtils/svelte5Utils.svelte.d.ts +80 -0
- package/dist/sharedUtils/toast.d.ts +8 -0
- package/dist/sharedUtils/utils.d.ts +265 -0
- package/package/components/AddUser.svelte +67 -34
- package/package/components/AppConnectInner.svelte +9 -1
- package/package/components/ArgInfo.svelte +9 -1
- package/package/components/ArgInput.svelte +21 -1
- package/package/components/CompareWorkspaces.svelte +11 -2
- package/package/components/DedicatedWorkersSelector.svelte +262 -247
- package/package/components/DefaultTagsInner.svelte +40 -2
- package/package/components/DeployWorkspace.svelte +13 -0
- package/package/components/DiffEditor.svelte +44 -1
- package/package/components/EditableSchemaForm.svelte +5 -2
- package/package/components/EditableSchemaForm.svelte.d.ts +1 -0
- package/package/components/Editor.svelte +5 -1
- package/package/components/EditorBar.svelte +12 -3
- package/package/components/FilterSearchbar.svelte +26 -2
- package/package/components/FlowBuilder.svelte +6 -3
- package/package/components/FlowGraphDiffViewer.svelte +16 -17
- package/package/components/FlowGraphViewer.svelte +20 -6
- package/package/components/FlowGraphViewer.svelte.d.ts +2 -0
- package/package/components/FlowGraphViewerStep.svelte +14 -32
- package/package/components/FlowMetadata.svelte +4 -1
- package/package/components/FlowPreviewContent.svelte +2 -0
- package/package/components/FlowStatusWaitingForEvents.svelte +25 -4
- package/package/components/HighlightCode.svelte +3 -0
- package/package/components/InstanceSetting.svelte +9 -25
- package/package/components/InstanceSettings.svelte +16 -0
- package/package/components/LabelsInput.svelte +149 -0
- package/package/components/LabelsInput.svelte.d.ts +8 -0
- package/package/components/Login.svelte +6 -1
- package/package/components/ObjectStoreConfigSettings.svelte +273 -1
- package/package/components/OktaSetting.svelte +6 -5
- package/package/components/Password.svelte +74 -20
- package/package/components/Password.svelte.d.ts +1 -0
- package/package/components/PasswordArgInput.svelte +2 -2
- package/package/components/PasswordArgInput.svelte.d.ts +1 -0
- package/package/components/Path.svelte +8 -10
- package/package/components/PathNameAutocomplete.svelte +308 -0
- package/package/components/PathNameAutocomplete.svelte.d.ts +27 -0
- package/package/components/PowerShellCommonParams.svelte +84 -0
- package/package/components/PowerShellCommonParams.svelte.d.ts +6 -0
- package/package/components/Range.svelte +8 -3
- package/package/components/ResourceEditor.svelte +6 -2
- package/package/components/RunForm.svelte +71 -7
- package/package/components/RunForm.svelte.d.ts +2 -1
- package/package/components/ScriptBuilder.svelte +7 -3
- package/package/components/ScriptEditor.svelte +221 -187
- package/package/components/ScriptEditor.svelte.d.ts +1 -1
- package/package/components/ScriptSchema.svelte +1 -1
- package/package/components/StringTypeNarrowing.svelte +1 -1
- package/package/components/StringTypeNarrowing.svelte.d.ts +1 -1
- package/package/components/SummaryPathDisplay.svelte +32 -10
- package/package/components/SummaryPathDisplay.svelte.d.ts +2 -1
- package/package/components/VariableEditor.svelte +9 -2
- package/package/components/WorkerGroup.svelte +47 -2
- package/package/components/apps/editor/DeploymentHistory.svelte +112 -13
- package/package/components/apps/editor/inlineScriptsPanel/InlineScriptRunnableByPath.svelte +135 -35
- package/package/components/apps/editor/inlineScriptsPanel/InlineScriptRunnableByPath.svelte.d.ts +3 -1
- package/package/components/apps/editor/settingsPanel/mainInput/RunnableSelector.svelte +11 -35
- package/package/components/apps/editor/settingsPanel/mainInput/runnableSelectorUtils.d.ts +10 -0
- package/package/components/apps/editor/settingsPanel/mainInput/runnableSelectorUtils.js +14 -0
- package/package/components/apps/editor/settingsPanel/mainInput/runnableSelectorUtils.test.d.ts +1 -0
- package/package/components/apps/editor/settingsPanel/mainInput/runnableSelectorUtils.test.js +34 -0
- package/package/components/assets/AssetButtons.svelte +21 -25
- package/package/components/assets/AssetsUsageDrawer.svelte +7 -9
- package/package/components/common/fileUpload/FileUpload.svelte +6 -2
- package/package/components/common/languageIcons/LanguageIcon.svelte +3 -0
- package/package/components/common/table/AppRow.svelte +18 -0
- package/package/components/common/table/FlowRow.svelte +18 -0
- package/package/components/common/table/ScriptRow.svelte +18 -0
- package/package/components/copilot/chat/AIChatManager.svelte.js +3 -3
- package/package/components/copilot/chat/flow/openFlow.json +1 -1
- package/package/components/copilot/chat/flow/openFlowZod.js +3 -3
- package/package/components/custom_ui.d.ts +2 -0
- package/package/components/details/DetailPageHeader.svelte +2 -2
- package/package/components/details/DetailPageHeader.svelte.d.ts +2 -1
- package/package/components/flows/agentToolUtils.d.ts +5 -0
- package/package/components/flows/agentToolUtils.js +49 -0
- package/package/components/flows/agentToolUtils.test.d.ts +1 -0
- package/package/components/flows/agentToolUtils.test.js +55 -0
- package/package/components/flows/content/FlowInput.svelte +2 -0
- package/package/components/flows/content/FlowInputsQuick.svelte +1 -1
- package/package/components/flows/content/FlowLoop.svelte +5 -12
- package/package/components/flows/content/FlowModuleScript.svelte +5 -3
- package/package/components/flows/content/FlowPathViewer.svelte +2 -2
- package/package/components/flows/content/FlowPathViewer.svelte.d.ts +1 -0
- package/package/components/flows/content/FlowSettings.svelte +2 -0
- package/package/components/flows/content/FlowWhileLoop.svelte +5 -12
- package/package/components/flows/flowInfers.js +8 -3
- package/package/components/flows/flowStore.svelte.d.ts +1 -1
- package/package/components/flows/map/FlowModuleSchemaMap.svelte +49 -9
- package/package/components/flows/pickers/PickHubScriptQuick.svelte +5 -3
- package/package/components/flows/scheduleUtils.js +2 -1
- package/package/components/graph/FlowGraphV2.svelte +13 -1
- package/package/components/graph/WacDiagram.svelte +96 -0
- package/package/components/graph/WacDiagram.svelte.d.ts +7 -0
- package/package/components/graph/noteEditor.svelte.d.ts +1 -1
- package/package/components/graph/noteEditor.svelte.js +12 -1
- package/package/components/graph/noteUtils.svelte.d.ts +1 -1
- package/package/components/graph/noteUtils.svelte.js +9 -2
- package/package/components/graph/renderers/edges/WacEdge.svelte +41 -0
- package/package/components/graph/renderers/edges/WacEdge.svelte.d.ts +4 -0
- package/package/components/graph/renderers/nodes/WacControlNode.svelte +51 -0
- package/package/components/graph/renderers/nodes/WacControlNode.svelte.d.ts +9 -0
- package/package/components/graph/renderers/nodes/WacStepNode.svelte +35 -0
- package/package/components/graph/renderers/nodes/WacStepNode.svelte.d.ts +9 -0
- package/package/components/graph/wacDagLayout.d.ts +10 -0
- package/package/components/graph/wacDagLayout.js +120 -0
- package/package/components/graph/wacToFlow.js +1 -1
- package/package/components/home/ItemsList.svelte +28 -4
- package/package/components/icons/RIcon.svelte +32 -0
- package/package/components/icons/RIcon.svelte.d.ts +7 -0
- package/package/components/instanceSettings/DbHealth.svelte +723 -0
- package/package/components/instanceSettings/DbHealth.svelte.d.ts +3 -0
- package/package/components/instanceSettings/SecretBackendConfig.svelte +343 -304
- package/package/components/instanceSettings/SmtpSettings.svelte +8 -0
- package/package/components/instanceSettings.js +14 -5
- package/package/components/mcp/McpScopeSelector.svelte +82 -16
- package/package/components/moveRenameManager.d.ts +1 -0
- package/package/components/moveRenameManager.js +7 -4
- package/package/components/raw_apps/RawAppInlineScriptRunnable.svelte +14 -1
- package/package/components/raw_apps/rawAppPolicy.js +3 -2
- package/package/components/raw_apps/utils.test.d.ts +1 -0
- package/package/components/raw_apps/utils.test.js +38 -0
- package/package/components/resources/resourcesFilter.d.ts +15 -2
- package/package/components/resources/resourcesFilter.js +11 -2
- package/package/components/runs/JobDetailFieldConfig.js +5 -3
- package/package/components/runs/JobDetailHeader.svelte +5 -2
- package/package/components/runs/JobRunsPreview.svelte +1 -0
- package/package/components/runs/RunBadges.svelte +7 -4
- package/package/components/runs/RunRow.svelte +7 -7
- package/package/components/schedules/schedulesFilter.d.ts +15 -2
- package/package/components/schedules/schedulesFilter.js +11 -2
- package/package/components/schema/EditableSchemaWrapper.svelte +6 -8
- package/package/components/schema/PropertyEditor.svelte +22 -1
- package/package/components/schema/PropertyEditor.svelte.d.ts +1 -0
- package/package/components/schema/editable_schema_wrapper.d.ts +1 -0
- package/package/components/secretArgUtils.d.ts +7 -0
- package/package/components/secretArgUtils.js +45 -0
- package/package/components/settings/WorkspaceUserSettings.svelte +359 -286
- package/package/components/sidebar/OperatorMenu.svelte +215 -197
- package/package/components/triggers/CaptureWrapper.svelte +1 -1
- package/package/components/triggers/TriggerFilters.svelte +17 -5
- package/package/components/triggers/TriggerFilters.svelte.d.ts +2 -1
- package/package/components/triggers/kafka/KafkaCapture.svelte +6 -2
- package/package/components/triggers/kafka/KafkaCapture.svelte.d.ts +1 -1
- package/package/components/triggers/kafka/KafkaTriggerEditorInner.svelte +5 -1
- package/package/components/triggers/kafka/utils.js +1 -0
- package/package/components/triggers/mqtt/MqttEditorConfigSection.svelte.d.ts +1 -1
- package/package/components/triggers/schedules/ScheduleEditorInner.svelte +6 -0
- package/package/components/triggers/websocket/WebsocketTriggerEditorInner.svelte +87 -1
- package/package/components/triggers/websocket/utils.js +2 -0
- package/package/components/variables/variablesFilter.d.ts +15 -2
- package/package/components/variables/variablesFilter.js +11 -2
- package/package/components/worker_group.js +1 -0
- package/package/components/workspaceSettings/DucklakeSettings.svelte +33 -41
- package/package/consts.d.ts +1 -0
- package/package/consts.js +1 -0
- package/package/editorLangUtils.d.ts +1 -1
- package/package/editorLangUtils.js +2 -0
- package/package/gen/core/OpenAPI.js +1 -1
- package/package/gen/schemas.gen.d.ts +346 -4
- package/package/gen/schemas.gen.js +347 -5
- package/package/gen/services.gen.d.ts +163 -1
- package/package/gen/services.gen.js +323 -17
- package/package/gen/types.gen.d.ts +671 -5
- package/package/hubPaths.json +6 -3
- package/package/infer.d.ts +55 -0
- package/package/infer.js +131 -0
- package/package/infer.svelte.js +2 -0
- package/package/mcpEndpointTools.js +213 -22
- package/package/script_helpers.d.ts +3 -0
- package/package/script_helpers.js +26 -0
- package/package/scripts.d.ts +2 -1
- package/package/scripts.js +15 -3
- package/package/stores.d.ts +2 -0
- package/package/system_prompts/prompts.d.ts +6 -5
- package/package/system_prompts/prompts.js +188 -29
- package/package/user.js +5 -1
- package/package/utils.js +21 -0
- package/package/utils_deployable.d.ts +11 -0
- package/package/utils_workspace_deploy.js +36 -8
- package/package.json +5 -4
|
@@ -3,28 +3,23 @@ import Password from '../Password.svelte';
|
|
|
3
3
|
import { SettingService } from '../../gen';
|
|
4
4
|
import { sendUserToast } from '../../toast';
|
|
5
5
|
import TextInput from '../text_input/TextInput.svelte';
|
|
6
|
-
import { Database, Lock, Server, ArrowLeft, ArrowRight } from 'lucide-svelte';
|
|
6
|
+
import { Database, Lock, Server, ArrowLeft, ArrowRight, Cloud } from 'lucide-svelte';
|
|
7
7
|
import { enterpriseLicense } from '../../stores';
|
|
8
8
|
import ToggleButtonGroup from '../common/toggleButton-v2/ToggleButtonGroup.svelte';
|
|
9
9
|
import ToggleButton from '../common/toggleButton-v2/ToggleButton.svelte';
|
|
10
10
|
import ConfirmationModal from '../common/confirmationModal/ConfirmationModal.svelte';
|
|
11
11
|
import EEOnly from '../EEOnly.svelte';
|
|
12
12
|
let { values, disabled = false } = $props();
|
|
13
|
-
// Initialize default values if not set
|
|
14
13
|
$effect(() => {
|
|
15
14
|
if (!$values['secret_backend']) {
|
|
16
15
|
$values['secret_backend'] = { type: 'Database' };
|
|
17
16
|
}
|
|
18
17
|
});
|
|
19
18
|
let selectedType = $derived($values['secret_backend']?.type ?? 'Database');
|
|
20
|
-
// Derive auth method from current config
|
|
21
|
-
// We check jwt_role === null because setAuthMethod explicitly sets jwt_role to null for token mode
|
|
22
|
-
// and sets token to null for jwt mode. This allows empty token values while still tracking the selection.
|
|
23
19
|
let authMethod = $derived.by(() => {
|
|
24
20
|
const config = $values['secret_backend'];
|
|
25
21
|
if (!config || config.type !== 'HashiCorpVault')
|
|
26
22
|
return 'jwt';
|
|
27
|
-
// If jwt_role is explicitly null, we're in token mode; otherwise jwt mode
|
|
28
23
|
return config.jwt_role === null ? 'token' : 'jwt';
|
|
29
24
|
});
|
|
30
25
|
let testingConnection = $state(false);
|
|
@@ -32,15 +27,22 @@ let migratingToVault = $state(false);
|
|
|
32
27
|
let migratingToDatabase = $state(false);
|
|
33
28
|
let migrateToVaultModalOpen = $state(false);
|
|
34
29
|
let migrateToDatabaseModalOpen = $state(false);
|
|
35
|
-
|
|
30
|
+
let testingAzureKvConnection = $state(false);
|
|
31
|
+
let migratingToAzureKv = $state(false);
|
|
32
|
+
let migratingFromAzureKv = $state(false);
|
|
33
|
+
let migrateToAzureKvModalOpen = $state(false);
|
|
34
|
+
let migrateFromAzureKvModalOpen = $state(false);
|
|
35
|
+
let testingAwsSmConnection = $state(false);
|
|
36
|
+
let migratingToAwsSm = $state(false);
|
|
37
|
+
let migratingFromAwsSm = $state(false);
|
|
38
|
+
let migrateToAwsSmModalOpen = $state(false);
|
|
39
|
+
let migrateFromAwsSmModalOpen = $state(false);
|
|
36
40
|
let vaultDisabled = $derived(!$enterpriseLicense);
|
|
37
41
|
function setBackendType(type) {
|
|
38
42
|
if (!type)
|
|
39
43
|
return;
|
|
40
|
-
|
|
41
|
-
if (type === 'HashiCorpVault' && vaultDisabled) {
|
|
44
|
+
if ((type === 'HashiCorpVault' || type === 'AzureKeyVault' || type === 'AwsSecretsManager') && vaultDisabled)
|
|
42
45
|
return;
|
|
43
|
-
}
|
|
44
46
|
if (type === 'Database') {
|
|
45
47
|
$values['secret_backend'] = { type: 'Database' };
|
|
46
48
|
}
|
|
@@ -54,27 +56,35 @@ function setBackendType(type) {
|
|
|
54
56
|
token: $values['secret_backend']?.token ?? null
|
|
55
57
|
};
|
|
56
58
|
}
|
|
59
|
+
else if (type === 'AzureKeyVault') {
|
|
60
|
+
$values['secret_backend'] = {
|
|
61
|
+
type: 'AzureKeyVault',
|
|
62
|
+
vault_url: $values['secret_backend']?.vault_url ?? '',
|
|
63
|
+
tenant_id: $values['secret_backend']?.tenant_id ?? '',
|
|
64
|
+
client_id: $values['secret_backend']?.client_id ?? '',
|
|
65
|
+
client_secret: $values['secret_backend']?.client_secret ?? null,
|
|
66
|
+
token: $values['secret_backend']?.token ?? null
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
else if (type === 'AwsSecretsManager') {
|
|
70
|
+
$values['secret_backend'] = {
|
|
71
|
+
type: 'AwsSecretsManager',
|
|
72
|
+
region: $values['secret_backend']?.region ?? 'us-east-1',
|
|
73
|
+
access_key_id: $values['secret_backend']?.access_key_id ?? null,
|
|
74
|
+
secret_access_key: $values['secret_backend']?.secret_access_key ?? null,
|
|
75
|
+
endpoint_url: $values['secret_backend']?.endpoint_url ?? null,
|
|
76
|
+
prefix: $values['secret_backend']?.prefix ?? 'windmill/'
|
|
77
|
+
};
|
|
78
|
+
}
|
|
57
79
|
}
|
|
58
80
|
function setAuthMethod(method) {
|
|
59
|
-
if (!method ||
|
|
60
|
-
!$values['secret_backend'] ||
|
|
61
|
-
$values['secret_backend'].type !== 'HashiCorpVault')
|
|
81
|
+
if (!method || !$values['secret_backend'] || $values['secret_backend'].type !== 'HashiCorpVault')
|
|
62
82
|
return;
|
|
63
83
|
if (method === 'token') {
|
|
64
|
-
|
|
65
|
-
$values['secret_backend'] = {
|
|
66
|
-
...$values['secret_backend'],
|
|
67
|
-
jwt_role: null,
|
|
68
|
-
token: $values['secret_backend'].token ?? ''
|
|
69
|
-
};
|
|
84
|
+
$values['secret_backend'] = { ...$values['secret_backend'], jwt_role: null, token: $values['secret_backend'].token ?? '' };
|
|
70
85
|
}
|
|
71
86
|
else if (method === 'jwt') {
|
|
72
|
-
|
|
73
|
-
$values['secret_backend'] = {
|
|
74
|
-
...$values['secret_backend'],
|
|
75
|
-
token: null,
|
|
76
|
-
jwt_role: $values['secret_backend'].jwt_role ?? 'windmill-secrets'
|
|
77
|
-
};
|
|
87
|
+
$values['secret_backend'] = { ...$values['secret_backend'], token: null, jwt_role: $values['secret_backend'].jwt_role ?? 'windmill-secrets' };
|
|
78
88
|
}
|
|
79
89
|
}
|
|
80
90
|
function getVaultSettings() {
|
|
@@ -87,14 +97,11 @@ function getVaultSettings() {
|
|
|
87
97
|
};
|
|
88
98
|
}
|
|
89
99
|
async function testVaultConnection() {
|
|
90
|
-
if (!$values['secret_backend'] || $values['secret_backend'].type !== 'HashiCorpVault')
|
|
100
|
+
if (!$values['secret_backend'] || $values['secret_backend'].type !== 'HashiCorpVault')
|
|
91
101
|
return;
|
|
92
|
-
}
|
|
93
102
|
testingConnection = true;
|
|
94
103
|
try {
|
|
95
|
-
await SettingService.testSecretBackend({
|
|
96
|
-
requestBody: getVaultSettings()
|
|
97
|
-
});
|
|
104
|
+
await SettingService.testSecretBackend({ requestBody: getVaultSettings() });
|
|
98
105
|
sendUserToast('Successfully connected to HashiCorp Vault');
|
|
99
106
|
}
|
|
100
107
|
catch (error) {
|
|
@@ -105,24 +112,18 @@ async function testVaultConnection() {
|
|
|
105
112
|
}
|
|
106
113
|
}
|
|
107
114
|
async function migrateSecretsToVault() {
|
|
108
|
-
if (!$values['secret_backend'] || $values['secret_backend'].type !== 'HashiCorpVault')
|
|
115
|
+
if (!$values['secret_backend'] || $values['secret_backend'].type !== 'HashiCorpVault')
|
|
109
116
|
return;
|
|
110
|
-
}
|
|
111
117
|
migratingToVault = true;
|
|
112
118
|
try {
|
|
113
|
-
const report = await SettingService.migrateSecretsToVault({
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
sendUserToast(`
|
|
118
|
-
console.error('Migration failures:', report.failures);
|
|
119
|
-
}
|
|
120
|
-
else {
|
|
121
|
-
sendUserToast(`Successfully migrated ${report.migrated_count}/${report.total_secrets} secrets to Vault`);
|
|
122
|
-
}
|
|
119
|
+
const report = await SettingService.migrateSecretsToVault({ requestBody: getVaultSettings() });
|
|
120
|
+
if (report.failed_count > 0)
|
|
121
|
+
sendUserToast(`Migration: ${report.migrated_count}/${report.total_secrets} migrated, ${report.failed_count} failed`, true);
|
|
122
|
+
else
|
|
123
|
+
sendUserToast(`Migrated ${report.migrated_count}/${report.total_secrets} secrets to Vault`);
|
|
123
124
|
}
|
|
124
125
|
catch (error) {
|
|
125
|
-
sendUserToast('Failed
|
|
126
|
+
sendUserToast('Failed: ' + error.message, true);
|
|
126
127
|
}
|
|
127
128
|
finally {
|
|
128
129
|
migratingToVault = false;
|
|
@@ -130,24 +131,18 @@ async function migrateSecretsToVault() {
|
|
|
130
131
|
}
|
|
131
132
|
}
|
|
132
133
|
async function migrateSecretsToDatabase() {
|
|
133
|
-
if (!$values['secret_backend'] || $values['secret_backend'].type !== 'HashiCorpVault')
|
|
134
|
+
if (!$values['secret_backend'] || $values['secret_backend'].type !== 'HashiCorpVault')
|
|
134
135
|
return;
|
|
135
|
-
}
|
|
136
136
|
migratingToDatabase = true;
|
|
137
137
|
try {
|
|
138
|
-
const report = await SettingService.migrateSecretsToDatabase({
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
sendUserToast(`
|
|
143
|
-
console.error('Migration failures:', report.failures);
|
|
144
|
-
}
|
|
145
|
-
else {
|
|
146
|
-
sendUserToast(`Successfully migrated ${report.migrated_count}/${report.total_secrets} secrets to database`);
|
|
147
|
-
}
|
|
138
|
+
const report = await SettingService.migrateSecretsToDatabase({ requestBody: getVaultSettings() });
|
|
139
|
+
if (report.failed_count > 0)
|
|
140
|
+
sendUserToast(`Migration: ${report.migrated_count}/${report.total_secrets} migrated, ${report.failed_count} failed`, true);
|
|
141
|
+
else
|
|
142
|
+
sendUserToast(`Migrated ${report.migrated_count}/${report.total_secrets} secrets to database`);
|
|
148
143
|
}
|
|
149
144
|
catch (error) {
|
|
150
|
-
sendUserToast('Failed
|
|
145
|
+
sendUserToast('Failed: ' + error.message, true);
|
|
151
146
|
}
|
|
152
147
|
finally {
|
|
153
148
|
migratingToDatabase = false;
|
|
@@ -155,45 +150,167 @@ async function migrateSecretsToDatabase() {
|
|
|
155
150
|
}
|
|
156
151
|
}
|
|
157
152
|
function isVaultConfigValid() {
|
|
158
|
-
if (!$values['secret_backend'] || $values['secret_backend'].type !== 'HashiCorpVault')
|
|
153
|
+
if (!$values['secret_backend'] || $values['secret_backend'].type !== 'HashiCorpVault')
|
|
159
154
|
return false;
|
|
160
|
-
}
|
|
161
155
|
const hasAddress = $values['secret_backend'].address?.trim() !== '';
|
|
162
156
|
const hasMountPath = $values['secret_backend'].mount_path?.trim() !== '';
|
|
163
157
|
const hasToken = $values['secret_backend'].token?.trim();
|
|
164
158
|
const hasJwtRole = $values['secret_backend'].jwt_role?.trim();
|
|
165
|
-
// Must have address and mount path, plus either token OR jwt_role (not both)
|
|
166
159
|
return hasAddress && hasMountPath && (hasToken || hasJwtRole);
|
|
167
160
|
}
|
|
168
|
-
|
|
161
|
+
function getAzureKvSettings() {
|
|
162
|
+
return {
|
|
163
|
+
vault_url: $values['secret_backend'].vault_url,
|
|
164
|
+
tenant_id: $values['secret_backend'].tenant_id,
|
|
165
|
+
client_id: $values['secret_backend'].client_id,
|
|
166
|
+
client_secret: $values['secret_backend'].client_secret || undefined,
|
|
167
|
+
token: $values['secret_backend'].token || undefined
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
async function testAzureKvConnection() {
|
|
171
|
+
if (!$values['secret_backend'] || $values['secret_backend'].type !== 'AzureKeyVault')
|
|
172
|
+
return;
|
|
173
|
+
testingAzureKvConnection = true;
|
|
174
|
+
try {
|
|
175
|
+
await SettingService.testAzureKvBackend({ requestBody: getAzureKvSettings() });
|
|
176
|
+
sendUserToast('Successfully connected to Azure Key Vault');
|
|
177
|
+
}
|
|
178
|
+
catch (error) {
|
|
179
|
+
sendUserToast('Failed: ' + error.message, true);
|
|
180
|
+
}
|
|
181
|
+
finally {
|
|
182
|
+
testingAzureKvConnection = false;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
async function migrateSecretsToAzureKv() {
|
|
186
|
+
if (!$values['secret_backend'] || $values['secret_backend'].type !== 'AzureKeyVault')
|
|
187
|
+
return;
|
|
188
|
+
migratingToAzureKv = true;
|
|
189
|
+
try {
|
|
190
|
+
const report = await SettingService.migrateSecretsToAzureKv({ requestBody: getAzureKvSettings() });
|
|
191
|
+
if (report.failed_count > 0)
|
|
192
|
+
sendUserToast(`Migration: ${report.migrated_count}/${report.total_secrets} migrated, ${report.failed_count} failed`, true);
|
|
193
|
+
else
|
|
194
|
+
sendUserToast(`Migrated ${report.migrated_count}/${report.total_secrets} secrets to Azure Key Vault`);
|
|
195
|
+
}
|
|
196
|
+
catch (error) {
|
|
197
|
+
sendUserToast('Failed: ' + error.message, true);
|
|
198
|
+
}
|
|
199
|
+
finally {
|
|
200
|
+
migratingToAzureKv = false;
|
|
201
|
+
migrateToAzureKvModalOpen = false;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
async function migrateSecretsFromAzureKv() {
|
|
205
|
+
if (!$values['secret_backend'] || $values['secret_backend'].type !== 'AzureKeyVault')
|
|
206
|
+
return;
|
|
207
|
+
migratingFromAzureKv = true;
|
|
208
|
+
try {
|
|
209
|
+
const report = await SettingService.migrateSecretsFromAzureKv({ requestBody: getAzureKvSettings() });
|
|
210
|
+
if (report.failed_count > 0)
|
|
211
|
+
sendUserToast(`Migration: ${report.migrated_count}/${report.total_secrets} migrated, ${report.failed_count} failed`, true);
|
|
212
|
+
else
|
|
213
|
+
sendUserToast(`Migrated ${report.migrated_count}/${report.total_secrets} secrets to database`);
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
sendUserToast('Failed: ' + error.message, true);
|
|
217
|
+
}
|
|
218
|
+
finally {
|
|
219
|
+
migratingFromAzureKv = false;
|
|
220
|
+
migrateFromAzureKvModalOpen = false;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
function isAzureKvConfigValid() {
|
|
224
|
+
if (!$values['secret_backend'] || $values['secret_backend'].type !== 'AzureKeyVault')
|
|
225
|
+
return false;
|
|
226
|
+
return ($values['secret_backend'].vault_url?.trim() !== '' &&
|
|
227
|
+
$values['secret_backend'].tenant_id?.trim() !== '' &&
|
|
228
|
+
$values['secret_backend'].client_id?.trim() !== '' &&
|
|
229
|
+
(!!$values['secret_backend'].client_secret?.trim() || !!$values['secret_backend'].token?.trim()));
|
|
230
|
+
}
|
|
231
|
+
function getAwsSmSettings() {
|
|
232
|
+
return {
|
|
233
|
+
region: $values['secret_backend'].region,
|
|
234
|
+
access_key_id: $values['secret_backend'].access_key_id || undefined,
|
|
235
|
+
secret_access_key: $values['secret_backend'].secret_access_key || undefined,
|
|
236
|
+
endpoint_url: $values['secret_backend'].endpoint_url || undefined,
|
|
237
|
+
prefix: $values['secret_backend'].prefix || undefined
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
async function testAwsSmConnection() {
|
|
241
|
+
if (!$values['secret_backend'] || $values['secret_backend'].type !== 'AwsSecretsManager')
|
|
242
|
+
return;
|
|
243
|
+
testingAwsSmConnection = true;
|
|
244
|
+
try {
|
|
245
|
+
await SettingService.testAwsSmBackend({ requestBody: getAwsSmSettings() });
|
|
246
|
+
sendUserToast('Successfully connected to AWS Secrets Manager');
|
|
247
|
+
}
|
|
248
|
+
catch (error) {
|
|
249
|
+
sendUserToast('Failed: ' + error.message, true);
|
|
250
|
+
}
|
|
251
|
+
finally {
|
|
252
|
+
testingAwsSmConnection = false;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
async function migrateSecretsToAwsSm() {
|
|
256
|
+
if (!$values['secret_backend'] || $values['secret_backend'].type !== 'AwsSecretsManager')
|
|
257
|
+
return;
|
|
258
|
+
migratingToAwsSm = true;
|
|
259
|
+
try {
|
|
260
|
+
const report = await SettingService.migrateSecretsToAwsSm({ requestBody: getAwsSmSettings() });
|
|
261
|
+
if (report.failed_count > 0)
|
|
262
|
+
sendUserToast(`Migration: ${report.migrated_count}/${report.total_secrets} migrated, ${report.failed_count} failed`, true);
|
|
263
|
+
else
|
|
264
|
+
sendUserToast(`Migrated ${report.migrated_count}/${report.total_secrets} secrets to AWS Secrets Manager`);
|
|
265
|
+
}
|
|
266
|
+
catch (error) {
|
|
267
|
+
sendUserToast('Failed: ' + error.message, true);
|
|
268
|
+
}
|
|
269
|
+
finally {
|
|
270
|
+
migratingToAwsSm = false;
|
|
271
|
+
migrateToAwsSmModalOpen = false;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
async function migrateSecretsFromAwsSm() {
|
|
275
|
+
if (!$values['secret_backend'] || $values['secret_backend'].type !== 'AwsSecretsManager')
|
|
276
|
+
return;
|
|
277
|
+
migratingFromAwsSm = true;
|
|
278
|
+
try {
|
|
279
|
+
const report = await SettingService.migrateSecretsFromAwsSm({ requestBody: getAwsSmSettings() });
|
|
280
|
+
if (report.failed_count > 0)
|
|
281
|
+
sendUserToast(`Migration: ${report.migrated_count}/${report.total_secrets} migrated, ${report.failed_count} failed`, true);
|
|
282
|
+
else
|
|
283
|
+
sendUserToast(`Migrated ${report.migrated_count}/${report.total_secrets} secrets to database`);
|
|
284
|
+
}
|
|
285
|
+
catch (error) {
|
|
286
|
+
sendUserToast('Failed: ' + error.message, true);
|
|
287
|
+
}
|
|
288
|
+
finally {
|
|
289
|
+
migratingFromAwsSm = false;
|
|
290
|
+
migrateFromAwsSmModalOpen = false;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
function isAwsSmConfigValid() {
|
|
294
|
+
if (!$values['secret_backend'] || $values['secret_backend'].type !== 'AwsSecretsManager')
|
|
295
|
+
return false;
|
|
296
|
+
return $values['secret_backend'].region?.trim() !== '';
|
|
297
|
+
}
|
|
169
298
|
let baseUrl = $derived($values['base_url'] ?? 'https://your-windmill-instance.com');
|
|
170
299
|
</script>
|
|
171
300
|
|
|
172
301
|
<div class="space-y-6">
|
|
173
|
-
<!-- Backend Type Selector -->
|
|
174
302
|
<div class="flex flex-col gap-2 mt-1">
|
|
175
303
|
<ToggleButtonGroup selected={selectedType} onSelected={(v) => setBackendType(v)}>
|
|
176
304
|
{#snippet children({ item: toggleButton })}
|
|
177
|
-
<ToggleButton
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
item={toggleButton}
|
|
182
|
-
/>
|
|
183
|
-
<ToggleButton
|
|
184
|
-
value="HashiCorpVault"
|
|
185
|
-
label="HashiCorp Vault (Beta)"
|
|
186
|
-
tooltip={vaultDisabled
|
|
187
|
-
? 'HashiCorp Vault integration requires Enterprise Edition'
|
|
188
|
-
: 'Store secrets in HashiCorp Vault (Beta feature)'}
|
|
189
|
-
item={toggleButton}
|
|
190
|
-
disabled={vaultDisabled}
|
|
191
|
-
/>
|
|
305
|
+
<ToggleButton value="Database" label="Database" tooltip="Store secrets encrypted in the database (default)" item={toggleButton} />
|
|
306
|
+
<ToggleButton value="HashiCorpVault" label="HashiCorp Vault (Beta)" tooltip={vaultDisabled ? 'Requires Enterprise Edition' : 'Store secrets in HashiCorp Vault'} item={toggleButton} disabled={vaultDisabled} />
|
|
307
|
+
<ToggleButton value="AzureKeyVault" label="Azure Key Vault" tooltip={vaultDisabled ? 'Requires Enterprise Edition' : 'Store secrets in Azure Key Vault'} item={toggleButton} disabled={vaultDisabled} />
|
|
308
|
+
<ToggleButton value="AwsSecretsManager" label="AWS Secrets Manager (Beta)" tooltip={vaultDisabled ? 'Requires Enterprise Edition' : 'Store secrets in AWS Secrets Manager'} item={toggleButton} disabled={vaultDisabled} />
|
|
192
309
|
{/snippet}
|
|
193
310
|
</ToggleButtonGroup>
|
|
194
311
|
{#if vaultDisabled}
|
|
195
312
|
<div class="flex items-center gap-1">
|
|
196
|
-
<EEOnly>
|
|
313
|
+
<EEOnly>External secret store integrations require Enterprise Edition</EEOnly>
|
|
197
314
|
</div>
|
|
198
315
|
{/if}
|
|
199
316
|
</div>
|
|
@@ -203,125 +320,54 @@ let baseUrl = $derived($values['base_url'] ?? 'https://your-windmill-instance.co
|
|
|
203
320
|
<Database class="text-primary" size={20} />
|
|
204
321
|
<div>
|
|
205
322
|
<p class="text-sm font-medium text-emphasis">Database Storage (Default)</p>
|
|
206
|
-
<p class="text-xs text-secondary">
|
|
207
|
-
Secrets are encrypted using workspace-specific keys and stored in the PostgreSQL database.
|
|
208
|
-
</p>
|
|
323
|
+
<p class="text-xs text-secondary">Secrets are encrypted using workspace-specific keys and stored in the PostgreSQL database.</p>
|
|
209
324
|
</div>
|
|
210
325
|
</div>
|
|
211
326
|
{:else if selectedType === 'HashiCorpVault'}
|
|
212
|
-
<!-- Vault Configuration -->
|
|
213
327
|
<div class="space-y-4 p-4 border rounded-lg">
|
|
214
328
|
<div class="flex items-center gap-2 mb-4">
|
|
215
329
|
<Lock class="text-primary" size={20} />
|
|
216
330
|
<div>
|
|
217
|
-
<p class="text-sm font-medium text-emphasis">
|
|
218
|
-
|
|
219
|
-
<span
|
|
220
|
-
class="ml-2 px-1.5 py-0.5 text-2xs font-medium bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200 rounded"
|
|
221
|
-
>Beta</span
|
|
222
|
-
>
|
|
223
|
-
</p>
|
|
224
|
-
<p class="text-xs text-secondary">
|
|
225
|
-
Store secrets in an external HashiCorp Vault instance.
|
|
226
|
-
</p>
|
|
331
|
+
<p class="text-sm font-medium text-emphasis">HashiCorp Vault Configuration <span class="ml-2 px-1.5 py-0.5 text-2xs font-medium bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200 rounded">Beta</span></p>
|
|
332
|
+
<p class="text-xs text-secondary">Store secrets in an external HashiCorp Vault instance.</p>
|
|
227
333
|
</div>
|
|
228
334
|
</div>
|
|
229
|
-
|
|
230
335
|
<div class="grid grid-cols-1 gap-4">
|
|
231
336
|
<div class="flex flex-col gap-1">
|
|
232
|
-
<label for="vault_address" class="block text-xs font-semibold text-emphasis"
|
|
233
|
-
|
|
234
|
-
>
|
|
235
|
-
<TextInput
|
|
236
|
-
inputProps={{
|
|
237
|
-
type: 'text',
|
|
238
|
-
id: 'vault_address',
|
|
239
|
-
placeholder: 'https://vault.company.com:8200',
|
|
240
|
-
disabled: disabled
|
|
241
|
-
}}
|
|
242
|
-
bind:value={$values['secret_backend'].address}
|
|
243
|
-
/>
|
|
337
|
+
<label for="vault_address" class="block text-xs font-semibold text-emphasis">Vault Address</label>
|
|
338
|
+
<TextInput inputProps={{ type: 'text', id: 'vault_address', placeholder: 'https://vault.company.com:8200', disabled }} bind:value={$values['secret_backend'].address} />
|
|
244
339
|
</div>
|
|
245
|
-
|
|
246
340
|
<div class="flex flex-col gap-1">
|
|
247
|
-
<label for="vault_mount_path" class="block text-xs font-semibold text-emphasis"
|
|
248
|
-
>KV Mount Path</label
|
|
249
|
-
>
|
|
341
|
+
<label for="vault_mount_path" class="block text-xs font-semibold text-emphasis">KV Mount Path</label>
|
|
250
342
|
<span class="text-2xs text-secondary">The KV v2 secrets engine mount path in Vault</span>
|
|
251
|
-
<TextInput
|
|
252
|
-
inputProps={{
|
|
253
|
-
type: 'text',
|
|
254
|
-
id: 'vault_mount_path',
|
|
255
|
-
placeholder: 'windmill',
|
|
256
|
-
disabled: disabled
|
|
257
|
-
}}
|
|
258
|
-
bind:value={$values['secret_backend'].mount_path}
|
|
259
|
-
/>
|
|
343
|
+
<TextInput inputProps={{ type: 'text', id: 'vault_mount_path', placeholder: 'windmill', disabled }} bind:value={$values['secret_backend'].mount_path} />
|
|
260
344
|
</div>
|
|
261
|
-
|
|
262
|
-
<!-- Authentication Method Toggle -->
|
|
263
345
|
<div class="flex flex-col gap-2">
|
|
264
346
|
<span class="block text-xs font-semibold text-emphasis">Authentication Method</span>
|
|
265
347
|
<ToggleButtonGroup selected={authMethod} onSelected={(v) => setAuthMethod(v)}>
|
|
266
348
|
{#snippet children({ item: toggleButton })}
|
|
267
|
-
<ToggleButton
|
|
268
|
-
|
|
269
|
-
label="JWT Auth"
|
|
270
|
-
tooltip="Authenticate using Windmill-signed JWTs (recommended for production)"
|
|
271
|
-
item={toggleButton}
|
|
272
|
-
{disabled}
|
|
273
|
-
/>
|
|
274
|
-
<ToggleButton
|
|
275
|
-
value="token"
|
|
276
|
-
label="Static Token"
|
|
277
|
-
tooltip="Use a static Vault token (for testing/development)"
|
|
278
|
-
item={toggleButton}
|
|
279
|
-
{disabled}
|
|
280
|
-
/>
|
|
349
|
+
<ToggleButton value="jwt" label="JWT Auth" tooltip="Authenticate using Windmill-signed JWTs" item={toggleButton} {disabled} />
|
|
350
|
+
<ToggleButton value="token" label="Static Token" tooltip="Use a static Vault token" item={toggleButton} {disabled} />
|
|
281
351
|
{/snippet}
|
|
282
352
|
</ToggleButtonGroup>
|
|
283
353
|
</div>
|
|
284
|
-
|
|
285
354
|
{#if authMethod === 'token'}
|
|
286
355
|
<div class="flex flex-col gap-1 p-3 bg-surface-secondary rounded-lg">
|
|
287
|
-
<label for="vault_token" class="block text-xs font-semibold text-emphasis"
|
|
288
|
-
|
|
289
|
-
>
|
|
290
|
-
<span class="text-2xs text-secondary"
|
|
291
|
-
>Static token for authentication. Recommended only for testing/development.</span
|
|
292
|
-
>
|
|
356
|
+
<label for="vault_token" class="block text-xs font-semibold text-emphasis">Vault Token</label>
|
|
357
|
+
<span class="text-2xs text-secondary">Static token. Recommended only for testing/development.</span>
|
|
293
358
|
<Password bind:password={$values['secret_backend'].token} small {disabled} />
|
|
294
359
|
</div>
|
|
295
360
|
{:else}
|
|
296
361
|
<div class="flex flex-col gap-2 p-3 bg-surface-secondary rounded-lg">
|
|
297
|
-
<label for="vault_jwt_role" class="block text-xs font-semibold text-emphasis"
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
<span class="text-2xs text-secondary"
|
|
301
|
-
>The JWT authentication role configured in Vault.</span
|
|
302
|
-
>
|
|
303
|
-
<TextInput
|
|
304
|
-
inputProps={{
|
|
305
|
-
type: 'text',
|
|
306
|
-
id: 'vault_jwt_role',
|
|
307
|
-
placeholder: 'windmill-secrets',
|
|
308
|
-
disabled: disabled
|
|
309
|
-
}}
|
|
310
|
-
bind:value={$values['secret_backend'].jwt_role}
|
|
311
|
-
/>
|
|
312
|
-
|
|
313
|
-
<!-- Vault JWT Setup Instructions -->
|
|
362
|
+
<label for="vault_jwt_role" class="block text-xs font-semibold text-emphasis">JWT Auth Role</label>
|
|
363
|
+
<span class="text-2xs text-secondary">The JWT authentication role configured in Vault.</span>
|
|
364
|
+
<TextInput inputProps={{ type: 'text', id: 'vault_jwt_role', placeholder: 'windmill-secrets', disabled }} bind:value={$values['secret_backend'].jwt_role} />
|
|
314
365
|
<details class="mt-2">
|
|
315
|
-
<summary class="text-xs font-medium text-secondary cursor-pointer hover:text-primary"
|
|
316
|
-
>Vault JWT Setup Instructions</summary
|
|
317
|
-
>
|
|
366
|
+
<summary class="text-xs font-medium text-secondary cursor-pointer hover:text-primary">Vault JWT Setup Instructions</summary>
|
|
318
367
|
<div class="mt-2 p-2 bg-surface rounded text-2xs text-secondary space-y-2">
|
|
319
368
|
<p>Configure Vault to accept JWTs from Windmill:</p>
|
|
320
|
-
<div
|
|
321
|
-
|
|
322
|
-
>
|
|
323
|
-
<pre
|
|
324
|
-
># Enable JWT auth method
|
|
369
|
+
<div class="bg-gray-100 dark:bg-gray-800 p-2 rounded font-mono text-2xs overflow-x-auto">
|
|
370
|
+
<pre># Enable JWT auth method
|
|
325
371
|
vault auth enable jwt
|
|
326
372
|
|
|
327
373
|
# Configure JWT auth with Windmill's JWKS endpoint
|
|
@@ -345,102 +391,139 @@ vault write auth/jwt/role/windmill-secrets \
|
|
|
345
391
|
bound_audiences="{baseUrl}" \
|
|
346
392
|
user_claim="email" \
|
|
347
393
|
policies="windmill-secrets" \
|
|
348
|
-
ttl="1h"</pre
|
|
349
|
-
>
|
|
394
|
+
ttl="1h"</pre>
|
|
350
395
|
</div>
|
|
351
|
-
<p class="text-yellow-600 dark:text-yellow-400">
|
|
352
|
-
Replace <code>windmill-secrets</code> with your role name if different.
|
|
353
|
-
</p>
|
|
354
396
|
</div>
|
|
355
397
|
</details>
|
|
356
398
|
</div>
|
|
357
399
|
{/if}
|
|
358
|
-
|
|
359
400
|
<div class="flex flex-col gap-1">
|
|
360
|
-
<label for="vault_namespace" class="block text-xs font-semibold text-emphasis"
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
<span class="text-2xs text-secondary"
|
|
364
|
-
>Vault Enterprise namespace (leave empty if not using namespaces)</span
|
|
365
|
-
>
|
|
366
|
-
<TextInput
|
|
367
|
-
inputProps={{
|
|
368
|
-
type: 'text',
|
|
369
|
-
id: 'vault_namespace',
|
|
370
|
-
placeholder: 'admin/my-namespace',
|
|
371
|
-
disabled: disabled
|
|
372
|
-
}}
|
|
373
|
-
bind:value={$values['secret_backend'].namespace}
|
|
374
|
-
/>
|
|
401
|
+
<label for="vault_namespace" class="block text-xs font-semibold text-emphasis">Namespace (optional)</label>
|
|
402
|
+
<span class="text-2xs text-secondary">Vault Enterprise namespace</span>
|
|
403
|
+
<TextInput inputProps={{ type: 'text', id: 'vault_namespace', placeholder: 'admin/my-namespace', disabled }} bind:value={$values['secret_backend'].namespace} />
|
|
375
404
|
</div>
|
|
376
405
|
</div>
|
|
377
|
-
|
|
378
|
-
<!-- Action Buttons -->
|
|
379
406
|
<div class="flex flex-col gap-4 pt-4 border-t">
|
|
380
|
-
<
|
|
381
|
-
<Button
|
|
382
|
-
unifiedSize="md"
|
|
383
|
-
variant="accent"
|
|
384
|
-
onclick={testVaultConnection}
|
|
385
|
-
disabled={disabled || !isVaultConfigValid() || testingConnection}
|
|
386
|
-
loading={testingConnection}
|
|
387
|
-
startIcon={{ icon: Server }}
|
|
388
|
-
>
|
|
389
|
-
Test Connection
|
|
390
|
-
</Button>
|
|
391
|
-
</div>
|
|
392
|
-
|
|
393
|
-
<!-- Migration Section -->
|
|
407
|
+
<Button unifiedSize="md" variant="accent" onclick={testVaultConnection} disabled={disabled || !isVaultConfigValid() || testingConnection} loading={testingConnection} startIcon={{ icon: Server }}>Test Connection</Button>
|
|
394
408
|
<div class="flex flex-col gap-4 pt-4 border-t">
|
|
395
409
|
<span class="block text-xs font-semibold text-emphasis">Secret Migration</span>
|
|
396
|
-
<span class="text-2xs text-secondary">
|
|
397
|
-
Migrate secrets between the database and HashiCorp Vault. Original values are NOT
|
|
398
|
-
deleted to allow for rollback.
|
|
399
|
-
</span>
|
|
400
|
-
|
|
410
|
+
<span class="text-2xs text-secondary">Original values are NOT deleted to allow for rollback.</span>
|
|
401
411
|
<div class="flex gap-4">
|
|
402
|
-
<!-- Database to Vault -->
|
|
403
412
|
<div class="flex-1 p-3 border rounded-lg">
|
|
404
|
-
<div class="flex items-center gap-2 mb-2">
|
|
405
|
-
<Database size={16} />
|
|
406
|
-
<ArrowRight size={16} />
|
|
407
|
-
<Lock size={16} />
|
|
408
|
-
</div>
|
|
413
|
+
<div class="flex items-center gap-2 mb-2"><Database size={16} /><ArrowRight size={16} /><Lock size={16} /></div>
|
|
409
414
|
<p class="text-xs font-medium mb-2">Database → Vault</p>
|
|
410
|
-
<
|
|
411
|
-
Decrypt secrets from database and store in Vault
|
|
412
|
-
</p>
|
|
413
|
-
<Button
|
|
414
|
-
unifiedSize="sm"
|
|
415
|
-
variant="default"
|
|
416
|
-
onclick={() => (migrateToVaultModalOpen = true)}
|
|
417
|
-
disabled={disabled || !isVaultConfigValid() || migratingToVault}
|
|
418
|
-
startIcon={{ icon: ArrowRight }}
|
|
419
|
-
>
|
|
420
|
-
Migrate to Vault
|
|
421
|
-
</Button>
|
|
415
|
+
<Button unifiedSize="sm" variant="default" onclick={() => (migrateToVaultModalOpen = true)} disabled={disabled || !isVaultConfigValid() || migratingToVault} startIcon={{ icon: ArrowRight }}>Migrate to Vault</Button>
|
|
422
416
|
</div>
|
|
423
|
-
|
|
424
|
-
<!-- Vault to Database -->
|
|
425
417
|
<div class="flex-1 p-3 border rounded-lg">
|
|
426
|
-
<div class="flex items-center gap-2 mb-2">
|
|
427
|
-
<Lock size={16} />
|
|
428
|
-
<ArrowLeft size={16} />
|
|
429
|
-
<Database size={16} />
|
|
430
|
-
</div>
|
|
418
|
+
<div class="flex items-center gap-2 mb-2"><Lock size={16} /><ArrowLeft size={16} /><Database size={16} /></div>
|
|
431
419
|
<p class="text-xs font-medium mb-2">Vault → Database</p>
|
|
432
|
-
<
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
420
|
+
<Button unifiedSize="sm" variant="default" onclick={() => (migrateToDatabaseModalOpen = true)} disabled={disabled || !isVaultConfigValid() || migratingToDatabase} startIcon={{ icon: ArrowLeft }}>Migrate to Database</Button>
|
|
421
|
+
</div>
|
|
422
|
+
</div>
|
|
423
|
+
</div>
|
|
424
|
+
</div>
|
|
425
|
+
</div>
|
|
426
|
+
{:else if selectedType === 'AzureKeyVault'}
|
|
427
|
+
<div class="space-y-4 p-4 border rounded-lg">
|
|
428
|
+
<div class="flex items-center gap-2 mb-4">
|
|
429
|
+
<Cloud class="text-primary" size={20} />
|
|
430
|
+
<div>
|
|
431
|
+
<p class="text-sm font-medium text-emphasis">Azure Key Vault Configuration</p>
|
|
432
|
+
<p class="text-xs text-secondary">Store secrets in an Azure Key Vault instance.</p>
|
|
433
|
+
</div>
|
|
434
|
+
</div>
|
|
435
|
+
<div class="grid grid-cols-1 gap-4">
|
|
436
|
+
<div class="flex flex-col gap-1">
|
|
437
|
+
<label for="azure_vault_url" class="block text-xs font-semibold text-emphasis">Vault URL</label>
|
|
438
|
+
<TextInput inputProps={{ type: 'text', id: 'azure_vault_url', placeholder: 'https://my-vault.vault.azure.net', disabled }} bind:value={$values['secret_backend'].vault_url} />
|
|
439
|
+
</div>
|
|
440
|
+
<div class="flex flex-col gap-1">
|
|
441
|
+
<label for="azure_tenant_id" class="block text-xs font-semibold text-emphasis">Tenant ID</label>
|
|
442
|
+
<TextInput inputProps={{ type: 'text', id: 'azure_tenant_id', placeholder: '00000000-0000-0000-0000-000000000000', disabled }} bind:value={$values['secret_backend'].tenant_id} />
|
|
443
|
+
</div>
|
|
444
|
+
<div class="flex flex-col gap-1">
|
|
445
|
+
<label for="azure_client_id" class="block text-xs font-semibold text-emphasis">Client ID</label>
|
|
446
|
+
<TextInput inputProps={{ type: 'text', id: 'azure_client_id', placeholder: '00000000-0000-0000-0000-000000000000', disabled }} bind:value={$values['secret_backend'].client_id} />
|
|
447
|
+
</div>
|
|
448
|
+
<div class="flex flex-col gap-1 p-3 bg-surface-secondary rounded-lg">
|
|
449
|
+
<label for="azure_client_secret" class="block text-xs font-semibold text-emphasis">Client Secret</label>
|
|
450
|
+
<Password bind:password={$values['secret_backend'].client_secret} small {disabled} />
|
|
451
|
+
</div>
|
|
452
|
+
<div class="flex flex-col gap-1 p-3 bg-surface-secondary rounded-lg">
|
|
453
|
+
<label for="azure_token" class="block text-xs font-semibold text-emphasis">Token (optional)</label>
|
|
454
|
+
<span class="text-2xs text-secondary">Static Bearer token for testing. If provided, OAuth2 is skipped.</span>
|
|
455
|
+
<Password bind:password={$values['secret_backend'].token} small {disabled} />
|
|
456
|
+
</div>
|
|
457
|
+
</div>
|
|
458
|
+
<div class="flex flex-col gap-4 pt-4 border-t">
|
|
459
|
+
<Button unifiedSize="md" variant="accent" onclick={testAzureKvConnection} disabled={disabled || !isAzureKvConfigValid() || testingAzureKvConnection} loading={testingAzureKvConnection} startIcon={{ icon: Server }}>Test Connection</Button>
|
|
460
|
+
<div class="flex flex-col gap-4 pt-4 border-t">
|
|
461
|
+
<span class="block text-xs font-semibold text-emphasis">Secret Migration</span>
|
|
462
|
+
<span class="text-2xs text-secondary">Original values are NOT deleted to allow for rollback.</span>
|
|
463
|
+
<div class="flex gap-4">
|
|
464
|
+
<div class="flex-1 p-3 border rounded-lg">
|
|
465
|
+
<div class="flex items-center gap-2 mb-2"><Database size={16} /><ArrowRight size={16} /><Cloud size={16} /></div>
|
|
466
|
+
<p class="text-xs font-medium mb-2">Database → Azure Key Vault</p>
|
|
467
|
+
<Button unifiedSize="sm" variant="default" onclick={() => (migrateToAzureKvModalOpen = true)} disabled={disabled || !isAzureKvConfigValid() || migratingToAzureKv} startIcon={{ icon: ArrowRight }}>Migrate to Azure KV</Button>
|
|
468
|
+
</div>
|
|
469
|
+
<div class="flex-1 p-3 border rounded-lg">
|
|
470
|
+
<div class="flex items-center gap-2 mb-2"><Cloud size={16} /><ArrowLeft size={16} /><Database size={16} /></div>
|
|
471
|
+
<p class="text-xs font-medium mb-2">Azure Key Vault → Database</p>
|
|
472
|
+
<Button unifiedSize="sm" variant="default" onclick={() => (migrateFromAzureKvModalOpen = true)} disabled={disabled || !isAzureKvConfigValid() || migratingFromAzureKv} startIcon={{ icon: ArrowLeft }}>Migrate to Database</Button>
|
|
473
|
+
</div>
|
|
474
|
+
</div>
|
|
475
|
+
</div>
|
|
476
|
+
</div>
|
|
477
|
+
</div>
|
|
478
|
+
{:else if selectedType === 'AwsSecretsManager'}
|
|
479
|
+
<div class="space-y-4 p-4 border rounded-lg">
|
|
480
|
+
<div class="flex items-center gap-2 mb-4">
|
|
481
|
+
<Cloud class="text-primary" size={20} />
|
|
482
|
+
<div>
|
|
483
|
+
<p class="text-sm font-medium text-emphasis">AWS Secrets Manager Configuration <span class="ml-2 px-1.5 py-0.5 text-2xs font-medium bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200 rounded">Beta</span></p>
|
|
484
|
+
<p class="text-xs text-secondary">Store secrets in AWS Secrets Manager.</p>
|
|
485
|
+
</div>
|
|
486
|
+
</div>
|
|
487
|
+
<div class="grid grid-cols-1 gap-4">
|
|
488
|
+
<div class="flex flex-col gap-1">
|
|
489
|
+
<label for="aws_sm_region" class="block text-xs font-semibold text-emphasis">Region</label>
|
|
490
|
+
<TextInput inputProps={{ type: 'text', id: 'aws_sm_region', placeholder: 'us-east-1', disabled }} bind:value={$values['secret_backend'].region} />
|
|
491
|
+
</div>
|
|
492
|
+
<div class="flex flex-col gap-1">
|
|
493
|
+
<label for="aws_sm_access_key_id" class="block text-xs font-semibold text-emphasis">Access Key ID (optional)</label>
|
|
494
|
+
<span class="text-2xs text-secondary">If not provided, the default AWS credential chain is used (env vars, instance profile, EKS pod identity)</span>
|
|
495
|
+
<TextInput inputProps={{ type: 'text', id: 'aws_sm_access_key_id', placeholder: 'AKIA...', disabled }} bind:value={$values['secret_backend'].access_key_id} />
|
|
496
|
+
</div>
|
|
497
|
+
<div class="flex flex-col gap-1 p-3 bg-surface-secondary rounded-lg">
|
|
498
|
+
<label for="aws_sm_secret_access_key" class="block text-xs font-semibold text-emphasis">Secret Access Key (optional)</label>
|
|
499
|
+
<Password bind:password={$values['secret_backend'].secret_access_key} small {disabled} />
|
|
500
|
+
</div>
|
|
501
|
+
<div class="flex flex-col gap-1">
|
|
502
|
+
<label for="aws_sm_prefix" class="block text-xs font-semibold text-emphasis">Secret Name Prefix (optional)</label>
|
|
503
|
+
<span class="text-2xs text-secondary">Prefix for secret names in AWS Secrets Manager (default: windmill/)</span>
|
|
504
|
+
<TextInput inputProps={{ type: 'text', id: 'aws_sm_prefix', placeholder: 'windmill/', disabled }} bind:value={$values['secret_backend'].prefix} />
|
|
505
|
+
</div>
|
|
506
|
+
<div class="flex flex-col gap-1">
|
|
507
|
+
<label for="aws_sm_endpoint_url" class="block text-xs font-semibold text-emphasis">Endpoint URL (optional)</label>
|
|
508
|
+
<span class="text-2xs text-secondary">Custom endpoint for LocalStack or other compatible services</span>
|
|
509
|
+
<TextInput inputProps={{ type: 'text', id: 'aws_sm_endpoint_url', placeholder: 'http://localhost:4566', disabled }} bind:value={$values['secret_backend'].endpoint_url} />
|
|
510
|
+
</div>
|
|
511
|
+
</div>
|
|
512
|
+
<div class="flex flex-col gap-4 pt-4 border-t">
|
|
513
|
+
<Button unifiedSize="md" variant="accent" onclick={testAwsSmConnection} disabled={disabled || !isAwsSmConfigValid() || testingAwsSmConnection} loading={testingAwsSmConnection} startIcon={{ icon: Server }}>Test Connection</Button>
|
|
514
|
+
<div class="flex flex-col gap-4 pt-4 border-t">
|
|
515
|
+
<span class="block text-xs font-semibold text-emphasis">Secret Migration</span>
|
|
516
|
+
<span class="text-2xs text-secondary">Original values are NOT deleted to allow for rollback.</span>
|
|
517
|
+
<div class="flex gap-4">
|
|
518
|
+
<div class="flex-1 p-3 border rounded-lg">
|
|
519
|
+
<div class="flex items-center gap-2 mb-2"><Database size={16} /><ArrowRight size={16} /><Cloud size={16} /></div>
|
|
520
|
+
<p class="text-xs font-medium mb-2">Database → AWS Secrets Manager</p>
|
|
521
|
+
<Button unifiedSize="sm" variant="default" onclick={() => (migrateToAwsSmModalOpen = true)} disabled={disabled || !isAwsSmConfigValid() || migratingToAwsSm} startIcon={{ icon: ArrowRight }}>Migrate to AWS SM</Button>
|
|
522
|
+
</div>
|
|
523
|
+
<div class="flex-1 p-3 border rounded-lg">
|
|
524
|
+
<div class="flex items-center gap-2 mb-2"><Cloud size={16} /><ArrowLeft size={16} /><Database size={16} /></div>
|
|
525
|
+
<p class="text-xs font-medium mb-2">AWS Secrets Manager → Database</p>
|
|
526
|
+
<Button unifiedSize="sm" variant="default" onclick={() => (migrateFromAwsSmModalOpen = true)} disabled={disabled || !isAwsSmConfigValid() || migratingFromAwsSm} startIcon={{ icon: ArrowLeft }}>Migrate to Database</Button>
|
|
444
527
|
</div>
|
|
445
528
|
</div>
|
|
446
529
|
</div>
|
|
@@ -449,65 +532,21 @@ vault write auth/jwt/role/windmill-secrets \
|
|
|
449
532
|
{/if}
|
|
450
533
|
</div>
|
|
451
534
|
|
|
452
|
-
|
|
453
|
-
<
|
|
454
|
-
title="Migrate Secrets to Vault"
|
|
455
|
-
confirmationText="Migrate"
|
|
456
|
-
open={migrateToVaultModalOpen}
|
|
457
|
-
loading={migratingToVault}
|
|
458
|
-
type="reload"
|
|
459
|
-
onCanceled={() => {
|
|
460
|
-
migrateToVaultModalOpen = false
|
|
461
|
-
}}
|
|
462
|
-
onConfirmed={migrateSecretsToVault}
|
|
463
|
-
>
|
|
464
|
-
{#snippet children()}
|
|
465
|
-
<div class="flex flex-col gap-2">
|
|
466
|
-
<p>
|
|
467
|
-
This will migrate all existing secrets from the database to HashiCorp Vault. The process
|
|
468
|
-
will:
|
|
469
|
-
</p>
|
|
470
|
-
<ol class="list-decimal list-inside text-sm space-y-1">
|
|
471
|
-
<li>Read all encrypted secrets from the database</li>
|
|
472
|
-
<li>Decrypt them using the workspace encryption keys</li>
|
|
473
|
-
<li>Store them in HashiCorp Vault under the configured mount path</li>
|
|
474
|
-
</ol>
|
|
475
|
-
<p class="text-yellow-600 dark:text-yellow-400 text-sm mt-2">
|
|
476
|
-
Note: Database values are NOT deleted automatically. You can manually clear them after
|
|
477
|
-
verifying the migration was successful.
|
|
478
|
-
</p>
|
|
479
|
-
<p>Are you sure you want to proceed?</p>
|
|
480
|
-
</div>
|
|
481
|
-
{/snippet}
|
|
535
|
+
<ConfirmationModal title="Migrate to AWS Secrets Manager" confirmationText="Migrate" open={migrateToAwsSmModalOpen} loading={migratingToAwsSm} type="reload" onCanceled={() => { migrateToAwsSmModalOpen = false }} onConfirmed={migrateSecretsToAwsSm}>
|
|
536
|
+
{#snippet children()}<div class="flex flex-col gap-2"><p>This will copy all secrets from the database to AWS Secrets Manager.</p><p class="text-yellow-600 dark:text-yellow-400 text-sm">Database values are NOT deleted automatically.</p></div>{/snippet}
|
|
482
537
|
</ConfirmationModal>
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
}}
|
|
494
|
-
|
|
495
|
-
>
|
|
496
|
-
{#snippet children()}
|
|
497
|
-
<div class="flex flex-col gap-2">
|
|
498
|
-
<p>
|
|
499
|
-
This will migrate all secrets from HashiCorp Vault back to the database. The process will:
|
|
500
|
-
</p>
|
|
501
|
-
<ol class="list-decimal list-inside text-sm space-y-1">
|
|
502
|
-
<li>List all secrets in Vault for each workspace</li>
|
|
503
|
-
<li>Read each secret value from Vault</li>
|
|
504
|
-
<li>Encrypt and store them in the database</li>
|
|
505
|
-
</ol>
|
|
506
|
-
<p class="text-yellow-600 dark:text-yellow-400 text-sm mt-2">
|
|
507
|
-
Note: Vault values are NOT deleted automatically. Only secrets that already exist in the
|
|
508
|
-
database will be updated.
|
|
509
|
-
</p>
|
|
510
|
-
<p>Are you sure you want to proceed?</p>
|
|
511
|
-
</div>
|
|
512
|
-
{/snippet}
|
|
538
|
+
<ConfirmationModal title="Migrate to Database" confirmationText="Migrate" open={migrateFromAwsSmModalOpen} loading={migratingFromAwsSm} type="reload" onCanceled={() => { migrateFromAwsSmModalOpen = false }} onConfirmed={migrateSecretsFromAwsSm}>
|
|
539
|
+
{#snippet children()}<div class="flex flex-col gap-2"><p>This will copy all secrets from AWS Secrets Manager back to the database.</p><p class="text-yellow-600 dark:text-yellow-400 text-sm">AWS Secrets Manager values are NOT deleted automatically.</p></div>{/snippet}
|
|
540
|
+
</ConfirmationModal>
|
|
541
|
+
<ConfirmationModal title="Migrate to Azure Key Vault" confirmationText="Migrate" open={migrateToAzureKvModalOpen} loading={migratingToAzureKv} type="reload" onCanceled={() => { migrateToAzureKvModalOpen = false }} onConfirmed={migrateSecretsToAzureKv}>
|
|
542
|
+
{#snippet children()}<div class="flex flex-col gap-2"><p>This will copy all secrets to Azure Key Vault.</p><p class="text-yellow-600 dark:text-yellow-400 text-sm">Database values are NOT deleted automatically.</p></div>{/snippet}
|
|
543
|
+
</ConfirmationModal>
|
|
544
|
+
<ConfirmationModal title="Migrate to Database" confirmationText="Migrate" open={migrateFromAzureKvModalOpen} loading={migratingFromAzureKv} type="reload" onCanceled={() => { migrateFromAzureKvModalOpen = false }} onConfirmed={migrateSecretsFromAzureKv}>
|
|
545
|
+
{#snippet children()}<div class="flex flex-col gap-2"><p>This will copy all secrets from Azure Key Vault back to the database.</p></div>{/snippet}
|
|
546
|
+
</ConfirmationModal>
|
|
547
|
+
<ConfirmationModal title="Migrate to Vault" confirmationText="Migrate" open={migrateToVaultModalOpen} loading={migratingToVault} type="reload" onCanceled={() => { migrateToVaultModalOpen = false }} onConfirmed={migrateSecretsToVault}>
|
|
548
|
+
{#snippet children()}<div class="flex flex-col gap-2"><p>This will copy all secrets to HashiCorp Vault.</p><p class="text-yellow-600 dark:text-yellow-400 text-sm">Database values are NOT deleted automatically.</p></div>{/snippet}
|
|
549
|
+
</ConfirmationModal>
|
|
550
|
+
<ConfirmationModal title="Migrate to Database" confirmationText="Migrate" open={migrateToDatabaseModalOpen} loading={migratingToDatabase} type="reload" onCanceled={() => { migrateToDatabaseModalOpen = false }} onConfirmed={migrateSecretsToDatabase}>
|
|
551
|
+
{#snippet children()}<div class="flex flex-col gap-2"><p>This will copy all secrets from Vault back to the database.</p></div>{/snippet}
|
|
513
552
|
</ConfirmationModal>
|