elsa-core
elsa-core copied to clipboard
[FEAT] Secrets
Introduce a new "Secrets" feature to securely manage sensitive data that various activities within a workflow might require. Examples include API keys for HTTP requests or connection strings for database queries.
Key Entities
Secret
- Id: Unique identifier for the secret.
- TenantId: Identifies the tenant the secret belongs to.
- Name: Human-readable name for the secret.
- Value: The actual secret value.
Secret Storage
- The
Secret
entity will be stored via theISecretStore
abstraction. - Multiple implementations of
ISecretStore
will be supported, allowing for different storage options:- EF Core: Store secrets in a relational database.
-
Azure KeyVault: Retrieve secrets from Azure KeyVault via the
AzureKeyVaultSecretProvider
implementation.
Contracts
-
ISecretStore: Manages secrets (CRUD operations). Provided by the
Elsa.Secrets.Management
module. - ISecretProvider: Read-only access to underlying secret stores.
This architecture allows for flexible secret management, enabling scenarios like using a DatabaseSecretProvider
to fetch secrets from a database or an AzureKeyVaultSecretProvider
to fetch them from Azure KeyVault.
UI Enhancements for Variable Types
Dynamic UI Components
- Boolean: Render as a radio button list with options "True" and "False".
- DateTime: Render as a DateTimePicker for easy selection.
- Secret: Render as a dropdown list populated with secrets defined in the Secrets UI.
- Global: Render as a dropdown list populated with globals defined in the Globals UI.
Globals
- Introduce a "Globals" module similar to the Secrets module, where global values can be centrally managed.
- Globals should also be evaluated at runtime, with a pluggable persistence store for various integrations.
Conclusion
This feature enhances the security, flexibility, and extensibility of Elsa Workflows by centralizing the management of sensitive and non-sensitive data, ensuring that secrets and global values are handled securely and efficiently across different workflows.
Some of our activities require more information about the current context/session like current userid, tenantid, preferred language, environment type (prod or stage). Other activities require a per user secret (e.g. current OAuth2 token).
So I'm wondering if an extra session/context would make sense or if the concept of the secrets store should be extended as both could be a simple list of key/values.
Indeed. How about a new object called Environment
or Vault
that is basically a list of key/values. Some values need to be stored encrypted, such as API keys. This environment would be tenant-specific, and accessible from any activity (either by injecting an e.g. IEnvironmentAccessor
or via WorkflowExecutionContext.Environment
.
Do you confirm we can't store password securely in workflow for now ?
Yes, Elsa won't encrypt secrets for now. You need to store encrypted information yourself.
Ideas based on discussions with @jdevillard and @mohdali
Improve the extensibility and user interaction of variable types by integrating custom UI components based on selected variable types and introducing a new variable type for managing secrets.
-
Dynamic UI Components: Depending on the variable type selected, the Default Value field's UI will adapt. For example:
- Boolean: Display options as a radio button list with choices "True" and "False".
- DateTime: Incorporate a DateTimePicker to facilitate date and time selection.
- Secret: Use a dropdown list, populated with secrets defined in the Secrets UI (similar to the implementation in V2).
- Global: Use a dropdown list, populated with globals defined in the Globals UI (new idea).
-Secret
-
This is a new type introduced by the Secrets module (to be implemented).
-
Secrets are centrally managed through a UI similar to the way this works in Elsa 2.
-
The value provided by a secret should be able to provide a value at runtime, enabling scenarios such as providing a JWT based on credentials such as an API key. In this example, the API key would be stored in the Secret object, but when evaluated at runtime, it would request a JWT from an identity server.
-
The Secrets module should have a pluggable persistence store, allowing for integration with services such as Azure KeyVault.
-
Globals:
- Similar to Secrets, we might have a "Globals" module, which provides a UI for users to define and manage global values centrally.
- Similar to the Secrets module, the value provided by a Global should be able to provide a value at runtime.
- The Globals module should have a pluggable persistence store, allowing for integration with services such as Table Storage, Azure KeyVault, etc.
@sfmskywalker secrets we use often have an expiration date, and as such we need someone to renew that secret from time to time. Could support for, minimally, adding expiration date tracking that can be queried via API br included? A published expiration event at a certain threshold (at time, 30, 90 days, etc.) would be ideal, giving us the ability to respond as needed.
I totally agree. In fact, it is already part of the design that I'm working on. Thanks for the request, it perfectly confirms my thinking 👍🏻