Martini Vault Functions
Overview
Martini Vault Functions let you interact with HashiCorp Vault directly from your services and workflows. Use them to securely store and retrieve secrets with the KV secret engine, or to encrypt, decrypt, sign, and verify data using the transit secret engine. This removes the need to manage sensitive data in application code and centralizes secrets in a dedicated, auditable secret store.
What You Will Learn
- How to write, read, and delete secrets in HashiCorp Vault using KV Engine v1 and KV Engine v2 functions
- How to retrieve a specific secret field value using
readDataandreadVersionedData - How to restore or permanently destroy a specific secret version in KV Engine v2
- How to encrypt and decrypt data using the transit secret engine
- How to sign data and verify signatures using transit engine signing keys
- How to rotate encryption keys and rewrap existing ciphertext to the latest key version
When To Use This
Use Vault Functions when you need to keep sensitive data — such as passwords, API keys, or tokens — out of your code and managed in a centralized, auditable secret store.
- Use this when you need to read, write, or delete secrets stored in HashiCorp Vault.
- Use this when you need to encrypt sensitive values before storing or transmitting them, or decrypt previously encrypted data at runtime.
- Use this when you want to sign data and later verify its signature to confirm integrity and authenticity.
- Use this when you need to rotate transit keys or rewrap ciphertext as part of a key lifecycle management process.
Prerequisites
- Martini Designer installed and running
- A Martini package in the current workspace
- A service or workflow to invoke the functions from
- Basic understanding of how to invoke functions:
- Invoke Function Node for workflows
- Function Step for services
- Vault configured in Martini
KV Engine Secret Management
Martini provides KV Engine functions for storing, retrieving, and removing secrets in HashiCorp Vault. Functions are available for both KV Engine v1 (unversioned) and KV Engine v2 (versioned), so you can choose the appropriate engine based on how your Vault instance is configured.
Understanding the packageName Parameter
Every Vault Function accepts a packageName input parameter that determines which Martini package's Vault configuration to use.
Understanding when to provide this value is essential for connecting to the correct Vault instance.
| Scenario | What to Set packageName To |
|---|---|
| Vault is configured in the same package you are working in | Leave empty — no value required |
| Vault is configured in a different package in your workspace | Provide the name of the package that holds the Vault configuration |
No Dependency Required
The package containing the Vault configuration does not need to be a dependency of your current package. It only needs to be started in the current workspace.
Writing Secrets to Vault
Use these functions to store key-value secret data at a path in HashiCorp Vault. Each function targets a specific KV engine version.
| Function | Engine Version | Description |
|---|---|---|
write(packageName, task) |
KV v1 | Writes secret data without versioning |
writeVersioned(packageName, task) |
KV v2 | Writes secret data and creates a new secret version |
Required task properties:
| Property | Applicable To | Description |
|---|---|---|
mountPath |
writeVersioned only |
The KV v2 engine mount point |
pathToKey |
Both | The Vault path where the secret will be stored |
values |
Both | A data model array of key-value entries representing the secret's fields |
The task.values property holds one entry per secret field.
Specify the field name in key and its value in value.
Add more entries to include additional fields:
1 2 3 4 5 6 7 8 9 10 11 | |
Return values:
| Function | Output Model | Notes |
|---|---|---|
write(...) |
vaultResponse |
KV v1 does not return any data on write, so response properties are null |
writeVersioned(...) |
versionedResponse |
Returns the version number and metadata of the stored secret |
Reading Secrets from Vault
Use these functions to retrieve secret data stored in HashiCorp Vault. You can retrieve all fields at a path, or target a single field by name.
Retrieve all fields at a path:
| Function | Engine Version | Description |
|---|---|---|
read(packageName, task) |
KV v1 | Reads all secret data without versioning |
readVersioned(packageName, task) |
KV v2 | Reads all secret data at a specific version |
Required task properties:
| Property | Applicable To | Description |
|---|---|---|
mountPath |
readVersioned only |
The KV v2 engine mount point |
pathToKey |
Both | The Vault path to read from |
version |
readVersioned only |
(Optional) The version to retrieve. Omit to return the latest version |
The secret fields are returned under the data model of the response.
Access them via vaultResponse.data (KV v1) or versionedResponse.data (KV v2):
1 2 3 4 | |
Retrieve a single field by name:
| Function | Engine Version | Description |
|---|---|---|
readData(packageName, task, fieldKey) |
KV v1 | Returns the value of a single field without versioning |
readVersionedData(packageName, task, fieldKey) |
KV v2 | Returns the value of a single field at a specific version |
Set fieldKey to the name of the field you want to retrieve.
Both functions return the field value as a String.
The task properties follow the same requirements as read and readVersioned respectively.
Deleting Secrets from Vault
Use these functions to remove secret data from HashiCorp Vault. KV v2 supports soft-deletion and permanent destruction in addition to standard deletion.
Standard deletion (KV v1 and KV v2):
| Function | Engine Version | Description |
|---|---|---|
delete(packageName, task) |
KV v1 | Removes the secret at the specified path |
deleteVersioned(packageName, task) |
KV v2 | Soft-deletes a specific version at the specified path |
Required task properties:
| Property | Applicable To | Description |
|---|---|---|
mountPath |
deleteVersioned only |
The KV v2 engine mount point |
pathToKey |
Both | The Vault path of the secret to delete |
version |
deleteVersioned only |
(Optional) The version to delete. Omit to target the latest version |
KV v2 version lifecycle management:
KV v2 provides two additional operations for managing the lifecycle of versioned secrets beyond soft-deletion:
| Function | Description | When to Use |
|---|---|---|
undeleteVersioned(packageName, task) |
Restores a soft-deleted version of the secret | When you need to recover a previously deleted version |
destroyVersioned(packageName, task) |
Permanently removes a specific version — cannot be undone | When you need to irreversibly destroy a version |
For both undeleteVersioned and destroyVersioned, the following task properties are all required:
| Property | Description |
|---|---|
mountPath |
The KV v2 engine mount point |
pathToKey |
The Vault path of the secret |
version |
The specific version to target |
Transit Secret Engine Operations
The Vault transit secret engine provides cryptographic operations — encryption, decryption, signing, and signature verification — without exposing key material. Martini exposes these capabilities through transit functions that integrate directly into your services and workflows.
Transit Key Requirement
The transit key used in any transit function must already exist in Vault before invoking these functions.
All transit functions also accept a packageName parameter.
See Understanding the packageName Parameter for details on when to provide it.
Encrypting Data with Vault Transit
Use these functions to encrypt plaintext data using a named transit key.
The resulting ciphertext can be safely stored or transmitted, and later decrypted using decrypt(...).
| Function | Input Type | Description |
|---|---|---|
encryptString(packageName, task) |
String | Encrypts a string plaintext value |
encryptByteArray(packageName, task) |
Byte array | Encrypts a byte array plaintext value |
Required task properties:
| Property | Description |
|---|---|
mountPath |
The transit engine mount point |
transitOpts.encryptionKey |
The name of the transit key to use for encryption |
transitOpts.plaintextAsString |
The string value to encrypt (for encryptString) |
transitOpts.plaintextAsByteArray |
The byte array value to encrypt (for encryptByteArray) |
Output — cipherText data model:
| Property | Description |
|---|---|
cipherText |
The encrypted value |
context |
A data model carrying any additional encryption context |
Decrypting Data with Vault Transit
Use the decrypt function to convert a Vault-encrypted ciphertext back to its original plaintext form.
Use the same transit key that was used during encryption.
| Function | Description |
|---|---|
decrypt(packageName, task) |
Decrypts a ciphertext value using the specified transit key |
Required task properties:
| Property | Description |
|---|---|
mountPath |
The transit engine mount point |
transitOpts.encryptionKey |
The name of the transit key to use for decryption |
transitOpts.ciphertext |
The ciphertext value to decrypt |
Output — plainText data model:
| Property | Description |
|---|---|
plainText |
The decrypted value, returned as a byte array |
context |
A data model carrying any additional decryption context |
Rewrapping and Rotating Transit Keys
Vault lets you rotate transit keys and rewrap existing ciphertext to the new key version, enabling ongoing key hygiene without disrupting existing secrets.
Rewrap ciphertext to the latest key version:
Use rewrap(packageName, task) to re-encrypt an existing ciphertext under the latest version of its transit key.
Run this after rotating a key to bring existing ciphertext up to date.
Required task properties:
| Property | Description |
|---|---|
mountPath |
The transit engine mount point |
transitOpts.encryptionKey |
The name of the transit key |
transitOpts.ciphertext |
The ciphertext to re-encrypt |
Output: A String containing the rewrapped ciphertext under the latest key version.
Rotate the transit key version:
Use rotate(packageName, task) to advance the transit key to a new version.
After rotation, new encryption operations use the updated key version.
Existing ciphertext encrypted under previous versions can be brought up to date using rewrap(...).
Required task properties:
| Property | Description |
|---|---|
mountPath |
The transit engine mount point |
transitOpts.encryptionKey |
The name of the transit key to rotate |
Signing Data with Vault Transit
Use these functions to generate a cryptographic signature for a plaintext value using a transit key that supports signing operations.
Signatures can later be verified with verifyString(...) or verifyByteArray(...).
Signing Capability Requirement
The transit key used for signing must support signing operations.
| Function | Input Type | Description |
|---|---|---|
signString(packageName, task) |
String | Signs a string plaintext value |
signByteArray(packageName, task) |
Byte array | Signs a byte array plaintext value |
Required task properties:
| Property | Description |
|---|---|
mountPath |
The transit engine mount point |
transitOpts.encryptionKey |
The name of the signing key |
transitOpts.plaintextAsString |
The string plaintext to sign (for signString) |
transitOpts.plaintextAsByteArray |
The byte array plaintext to sign (for signByteArray) |
Output — signature data model:
| Property | Description |
|---|---|
signature |
The generated signature value |
Verifying Signatures with Vault Transit
Use these functions to confirm that a signature matches the expected plaintext, verifying that the data has not been altered. Use the transit key name associated with the signature.
| Function | Input Type | Description |
|---|---|---|
verifyString(packageName, task) |
String | Verifies the signature of a string plaintext |
verifyByteArray(packageName, task) |
Byte array | Verifies the signature of a byte array plaintext |
Required task properties:
| Property | Description |
|---|---|
mountPath |
The transit engine mount point |
transitOpts.encryptionKey |
The name of the transit key used to create the original signature |
transitOpts.plaintextAsString |
The original string plaintext (for verifyString) |
transitOpts.plaintextAsByteArray |
The original byte array plaintext (for verifyByteArray) |
transitOpts.signature |
The signature to verify |
Output: Returns true if the signature is valid, false if it is not.
Troubleshooting
| Problem | Detection | Cause | Fix |
|---|---|---|---|
| Error thrown when invoking any Vault function | Runtime error stating that the Vault feature is not supported | Vault has not been configured in Martini | Configure Vault in Martini, then restart the package before retrying |
readData(...) returns null |
Function output is null even though the secret exists at the path |
The value in fieldKey does not match any stored field name — field names are case-sensitive |
Use read(...) or readVersioned(...) to inspect the available field names at the path, then update fieldKey to match exactly |
| Function fails with a mount-related error | Runtime error indicating the mount path was not found or is invalid | The mountPath value does not match the actual engine mount point configured in Vault |
Verify the correct mount path in your Vault instance and update mountPath to match |
| Transit key not found | Runtime error referencing an unknown or missing key name | The key specified in transitOpts.encryptionKey does not exist in Vault |
Create the transit key in Vault before invoking any encryption, decryption, signing, or verification function |
signString(...) or signByteArray(...) fails |
Runtime error from Vault indicating the key does not support signing operations | The transit key specified in transitOpts.encryptionKey was not created with signing capability |
Use a transit key that supports signing |
Helpful Resources
- Configuring Vault in Martini - Set up HashiCorp Vault integration with Martini
- Invoke Function Node - Call Vault Functions from within a workflow
- Function Step - Call Vault Functions from within a service
- Martini Packages - Understand how Martini packages are organized in the workspace
- Community Q&A: Martini Community
Have a question? Post or search it here.