Skip to content
Talk to our solutions team

Secrets and security

Vault access, secret generation, hashing, encryption and certificates. Every parameter with its type, default and description, plus worked examples.

Platform-integrated secret management using HashiCorp Vault with mTLS authentication.

ParameterTypeRequiredDefaultDescription
operationstringNoreadOperation: read, get, write, set
urlstringYes-Vault server URL
clusterstringYes-Cluster name
datacenterstringYes-Datacenter name
workspacestringYes-Workspace/environment name
customerstringYes-Customer identifier
forgeslugstringYes-Forge/product slug
productiondomainstringYes-Tenant domain
certificatestringYes-TLS certificate for authentication
keystringYes-TLS private key for authentication
issuerlistYes-Certificate issuers
secretnamestringYes-Name of the secret to read/write
secretvaluestringNo-Value to write (required for write)
servicestringNovulcanService name
setvarstringNo-Variable to store result
name: vault-read
vars:
vault_url: "{{env.VAULT_URL}}"
cluster: production
datacenter: us-east-1
tasks:
- name: get-db-password
vault:
operation: read
url: "{{vault_url}}"
cluster: "{{cluster}}"
datacenter: "{{datacenter}}"
workspace: production
customer: acme
forgeslug: webapp
productiondomain: acme.example.com
certificate: "{{tls_cert}}"
key: "{{tls_key}}"
issuer:
- "{{ca_cert}}"
secretname: database-password
setvar: db_password
name: vault-write
tasks:
- name: store-api-key
vault:
operation: write
url: "{{vault_url}}"
cluster: "{{cluster}}"
datacenter: "{{datacenter}}"
workspace: production
customer: acme
forgeslug: webapp
productiondomain: acme.example.com
certificate: "{{tls_cert}}"
key: "{{tls_key}}"
issuer:
- "{{ca_cert}}"
secretname: api-key
secretvalue: "{{generated_key}}"

For simpler vault access from scripts, use the vault namespace instead of the vault task. The namespace uses the service’s pre-initialized vault client, requiring only a secret name — no TLS, datacenter, or cluster params needed:

- name: get-secret
script:
namespaces: http,vault
code: |
var secret = vault.get("database-password");
vault.save({name: "new-key", value: "value123", indefinite: true});

See vault namespace docs for full reference.

Secret reads and service tokens, through the service vault client.

FunctionReturns
vault.get(){success, name, value, error}
vault.exists(){success, exists, error}
vault.serviceJwt()A service token for the named service
FunctionParameterDescription
get, existsnameThe secret’s name. A bare string is accepted as shorthand
serviceJwtserviceThe service to issue a token for
if (vault.exists({ name: "database-production-password" }).exists) {
let s = vault.get({ name: "database-production-password" })
// s.value holds the secret
}
// Bare-string shorthand for { name: … }
let s2 = vault.get("database-production-password")

A secret is addressed by name — there is no path-and-key pair.

The namespace reads; it does not write. Creating and rotating secrets is a deliberate act with an audit trail, not something a transform should do in passing, so those stay with the vault: task and the Vault block’s own API.

Prefer vault.exists where you would otherwise read a secret only to check it is there. Reading leaves an access record; testing does not.

Generate secrets, passwords, and passphrases.

ParameterTypeRequiredDefaultDescription
operationstringNogenerateOperation: generate, encode, decode, hash
setvarstringYes-Variable to store result
lengthintNo32Length of generated secret
patternstringNo-Predefined pattern (see below)
wordsintNo-Number of words for passphrase
prefixstringNo-Prefix for generated secret
separatorstringNo-Word separator for passphrase
uppercaseboolNotrueInclude uppercase letters
lowercaseboolNotrueInclude lowercase letters
digitsboolNotrueInclude digits
specialboolNofalseInclude special characters
charsetstringNo-Custom character set
hashboolNofalseAlso generate bcrypt hash
valuestringNo-Input value for encode/decode/hash
encodingstringNobase64Encoding: base64, base64url, hex
PatternDescription
alphanumericLetters and digits
alphaLetters only
numericDigits only
hexHexadecimal
base64Base64-safe characters
passwordStrong password with all character types
passphraseDiceware word-based password
pinNumeric PIN
uuidUUID v4 format
apikeyAPI key format (prefix_random)
name: secret-apikey
tasks:
- name: generate
secret:
length: 32
setvar: api_key
name: secret-passphrase
tasks:
- name: generate
secret:
pattern: passphrase
words: 4
setvar: memorable_password
## Result: "correct-horse-battery-staple"
name: secret-password
tasks:
- name: generate
secret:
pattern: password
length: 16
hash: true
setvar: user_password
## Result: {{user_password}} = "Kj#9mN$pL2@xQw4r"
## {{user_password_hash}} = bcrypt hash
name: secret-prefixed
tasks:
- name: generate
secret:
pattern: apikey
prefix: sk_live
length: 32
setvar: stripe_key
## Result: "sk_live_a1b2c3d4e5f6..."
name: secret-encode
vars:
username: admin
password: secret
tasks:
- name: encode
secret:
operation: encode
encoding: base64
value: "{{username}}:{{password}}"
setvar: basic_auth

Secret generation and encoding functions.

FunctionDescription
secret.generate()Generate random secrets/passwords
secret.encode()Encode data (base64, hex)
secret.decode()Decode encoded data
secret.hash()Hash value using bcrypt
secret.validate()Validate password strength
ParameterTypeDefaultDescription
patternstring"alphanumeric"Pattern: alphanumeric, hex, base64, passphrase
lengthint32Secret length
prefixstring-Prefix to add
uppercaseboolfalseInclude uppercase
lowercaseboolfalseInclude lowercase
digitsboolfalseInclude digits
specialboolfalseInclude special chars
charsetstring-Custom character set
hashboolfalseReturn bcrypt hash too
separatorstring"-"Word separator (passphrase)
wordsint-Word count (passphrase)
ParameterTypeDefaultDescription
datastring-Data to encode/decode
encodingstring"base64"Encoding: base64, base32, hex
// Generate API key
let key = secret.generate({
length: 32,
pattern: "alphanumeric"
})
log("API Key:", key.secret)
// Generate passphrase
let pass = secret.generate({
pattern: "passphrase",
words: 4,
separator: "-"
})
log("Passphrase:", pass.secret)
// Generate with hash
let pwd = secret.generate({
length: 16,
special: true,
hash: true
})
log("Password:", pwd.secret)
log("Hash:", pwd.hash)
// Base64 encode
let encoded = secret.encode({
data: "admin:password",
encoding: "base64"
})
log("Encoded:", encoded.encoded)
// Base64 decode
let decoded = secret.decode({
data: encoded.encoded,
encoding: "base64"
})
log("Decoded:", decoded.decoded)
// Hash password (bcrypt)
let hashed = secret.hash({
value: "mypassword"
})
log("Bcrypt hash:", hashed.hash)
// Validate password strength
let valid = secret.validate({
value: "WeakPwd"
})
if (!valid.success) {
log("Password too weak:", valid.error)
}

File encryption using AES.

ParameterTypeRequiredDescription
secretstringYesEncryption key (vault key)
sourcestringYesSource file path
destinationstringYesDestination file path
patternstringNoGlob pattern for multiple files
name: encrypt-file
tasks:
- name: encrypt
encrypt:
secret: my-vault-key
source: /data/file.txt
destination: /data/file.enc
name: decrypt-file
tasks:
- name: decrypt
decrypt:
secret: my-vault-key
source: /data/file.enc
destination: /data/file.txt

Encryption and decryption functions.

FunctionDescription
crypt.encryptFile()Encrypt a file
crypt.decryptFile()Decrypt a file
crypt.encrypt()Encrypt data in memory
crypt.decrypt()Decrypt data in memory
ParameterTypeDefaultDescription
secretstring-Encryption key/passphrase
sourcestring-Source file path
destinationstring-Destination file path
algorithmstring"aes-256-gcm"Algorithm: aes-256-gcm, aes-256-cbc, aes-128-gcm
overwriteboolfalseOverwrite existing file
iterationsint100000PBKDF2 iterations
ParameterTypeDefaultDescription
secretstring-Encryption key/passphrase
datastring-Data to encrypt/decrypt
algorithmstring"aes-256-gcm"Algorithm
iterationsint100000PBKDF2 iterations
// Encrypt file
let result = crypt.encryptFile({
secret: "my-secret-key",
source: "/data/sensitive.txt",
destination: "/data/sensitive.enc",
algorithm: "aes-256-gcm"
})
log("Encrypted to:", result.destination)
// Decrypt file
crypt.decryptFile({
secret: "my-secret-key",
source: "/data/sensitive.enc",
destination: "/data/sensitive.txt",
overwrite: true
})
// Encrypt data in memory (returns base64)
let encrypted = crypt.encrypt({
secret: "my-secret-key",
data: "sensitive information"
})
log("Encrypted:", encrypted.encrypted)
// Decrypt data in memory
let decrypted = crypt.decrypt({
secret: "my-secret-key",
data: encrypted.encrypted
})
log("Decrypted:", decrypted.decrypted)
// Higher security with more iterations
crypt.encryptFile({
secret: "my-secret-key",
source: "/data/critical.txt",
destination: "/data/critical.enc",
iterations: 500000
})

Generate cryptographic hashes.

ParameterTypeRequiredDefaultDescription
valuestringNo-String to hash
filestringNo-File to hash
algorithmstringNosha256Algorithm: sha256, sha512, sha1, md5
lengthintNo0Truncate hash to N characters
setvarstringYes-Variable to store the hash
name: hash-string
tasks:
- name: hash
hash:
value: "hello world"
algorithm: sha256
setvar: hash_result
name: hash-file
tasks:
- name: hash-file
hash:
file: /path/to/file.txt
algorithm: sha256
setvar: file_hash

Cryptographic hashing functions.

FunctionDescription
hash.string()Hash a string value
hash.file()Hash a file
hash.bytes()Hash byte data
ParameterTypeDefaultDescription
datastring-Data to hash (for string/bytes)
pathstring-File path (for file)
algorithmstring"sha256"Algorithm: sha256, sha512, sha1, md5, blake2b, xxhash
lengthint0Truncate hash to N characters (0 = full)
// Hash a string
let result = hash.string({
data: "hello world",
algorithm: "sha256"
})
log("Hash:", result.hash)
// Hash with truncation
let short = hash.string({
data: "hello world",
algorithm: "sha256",
length: 8
})
log("Short hash:", short.hash)
// Hash a file
let fileHash = hash.file({
path: "/path/to/file.txt",
algorithm: "sha256"
})
log("File hash:", fileHash.hash)
// Different algorithms
hash.string({ data: "test", algorithm: "md5" }) // MD5
hash.string({ data: "test", algorithm: "sha512" }) // SHA-512
hash.string({ data: "test", algorithm: "blake2b" }) // BLAKE2b
hash.string({ data: "test", algorithm: "xxhash" }) // xxHash (fast)

Generate unique identifiers (ULID, UUID, NanoID, KSUID, XID).

ParameterTypeRequiredDefaultDescription
typestringNoulidID type (see below)
setvarstringYes-Variable to store generated ID
TypeDescription
ulidULID (uppercase)
ulid-lowerULID (lowercase)
uuidUUID v4
uuidv4UUID v4
uuidv6UUID v6
uuidv7UUID v7
uuidv1UUID v1
name: gen-id
tasks:
- name: create-id
id:
type: uuidv7
setvar: user_id
name: gen-ulid
tasks:
- name: create-ulid
id:
setvar: request_id

Identifier generation functions (ULID, UUID).

FunctionDescription
id.generate()Generate unique identifier(s)
ParameterTypeDefaultDescription
typestring"ulid"ID type: ulid, uuid, nanoid, ksuid, xid
countint1Number of IDs to generate
// Generate single ULID (default)
let result = id.generate({})
log("ID:", result.id)
// Generate UUID v4
let uuid = id.generate({ type: "uuid" })
log("UUID:", uuid.id)
// Generate multiple IDs
let ids = id.generate({
type: "nanoid",
count: 5
})
log("Generated", ids.ids.length, "IDs")
// Available types
id.generate({ type: "ulid" }) // 01ARZ3NDEKTSV4RRFFQ69G5FAV
id.generate({ type: "uuid" }) // f47ac10b-58cc-4372-a567-0e02b2c3d479
id.generate({ type: "nanoid" }) // V1StGXR8_Z5jdHi6B-myT
id.generate({ type: "ksuid" }) // 0ujsswThIGTUYm2K8FjOOfXtY1K
id.generate({ type: "xid" }) // 9m4e2mr0ui3e8a215n4g

ACME certificate management — issue, renew, revoke, read, list.

Default CA is Let’s Encrypt; the caURL parameter accepts any ACME-compatible directory (ZeroSSL, step-ca, Buypass). Built on certmagic — supports HTTP-01, DNS-01, and TLS-ALPN-01 challenges. DNS-01 reuses the six libdns providers wired into the dns task.

This task replaces the lego-based acme task entirely. The old acme:/legodns: names are gone. The lego dependency is dropped along with its 181 transitively-imported DNS providers — net binary savings of 30–50 MB.

FieldTypeRequiredDefaultDescription
opstringNoobtainobtain / renew / revoke / info / list
caURLstringNoLE productionACME directory URL; shortcuts: letsencrypt, staging, zerossl
emailstringYes (obtain/renew/revoke)Account contact email
storagestringNo$XDG_DATA_HOME/letsencryptFilesystem path
keyTypestringNoECDSA-P256ECDSA-P256 / ECDSA-P384 / RSA-2048 / RSA-4096 / ED25519
timeoutdurationNoWall-clock cap
setvarstringNoCapture result map into a workflow variable
FieldTypeRequiredDefaultDescription
challengestringNodns-01Challenge type
mustStapleboolNofalseOCSP must-staple

DNS-01 fields: dnsProvider, dnsCredentials (same shape as the dns task), dnsPropagation, dnsResolvers.

HTTP-01 fields: httpAddress (default :80).

TLS-ALPN-01 fields: tlsAddress (default :443).

obtain / renew / info populate cert; list populates certs. Both shapes carry: domains, notBefore, notAfter, issuer, serial, fingerprint, daysRemaining, certPath, keyPath, fullchainPath.

revoke: { success, error }.

- name: cert
letsencrypt:
op: obtain
storage: /var/lib/letsencrypt
domains:
- example.com
- www.example.com
- api.example.com
challenge: dns-01
dnsProvider: cloudflare
dnsCredentials:
api_token: "{{ cf_token }}"
setvar: cert
- name: cert
letsencrypt:
op: obtain
caURL: staging
domains: ["dev.example.com"]
challenge: dns-01
dnsProvider: cloudflare
dnsCredentials: { api_token: "{{ cf_token }}" }
HTTP-01 (host directly reachable on port 80)
Section titled “HTTP-01 (host directly reachable on port 80)”
- name: cert
letsencrypt:
op: obtain
domains: ["app.example.com"]
challenge: http-01
- name: renew
letsencrypt:
op: renew
domains: ["example.com", "www.example.com"]
force: true
challenge: dns-01
dnsProvider: cloudflare
dnsCredentials: { api_token: "{{ cf_token }}" }
Read existing cert without touching the CA
Section titled “Read existing cert without touching the CA”
- name: info
letsencrypt:
op: info
storage: /var/lib/letsencrypt
domain: www.example.com
setvar: cert
- name: report
print:
message: "expires in {{ cert.cert.daysRemaining }} days"
- name: revoke
letsencrypt:
op: revoke
domain: oops.example.com
reason: 1 # keyCompromise (RFC 5280)
challenge: dns-01
dnsProvider: cloudflare
dnsCredentials: { api_token: "{{ cf_token }}" }

Same five verbs under the letsencrypt script namespace.

let result = letsencrypt.obtain({
storage: "/var/lib/letsencrypt",
domains: ["example.com", "www.example.com"],
challenge: "dns-01",
dnsProvider: "cloudflare",
dnsCredentials: { api_token: cfToken }
})
log("cert at " + result.cert.certPath)

See docs/namespaces/letsencrypt.md for full reference.