What You Build
If your credentials live in a password manager that CloudCruise has no built-in integration for, you can put a small HTTPS service in front of it. CloudCruise calls your service at run time to fetch the username, password, and one-time code of the item a vault credential is bound to. It works the same way as the 1Password integration: you rotate or update a login in your password manager, and your workflows use the new value on the next run. You host the API; CloudCruise calls it.- You implement the endpoints below on an HTTPS base URL you control.
- In CloudCruise you add a Custom provider connection and point it at your base URL.
- You bind vault credentials to items in your password manager by their
ref, your own item identifier. - When a workflow needs the credential, CloudCruise calls
POST /v1/items/resolveand uses the returned username, password, and TOTP seed.
All endpoints are
POST with a JSON body, including read operations. Item references travel in the body, never in the URL, so they are never altered by URL encoding and do not appear in access logs.
The full contract is an OpenAPI 3.1 file you can download to generate server stubs: custom-secret-provider-api.yaml. Each operation is also documented under API Reference → Custom Secret Provider API.
Creating a Connection
- Navigate to Workspace Settings → Integrations.
- In the Secret Providers section, add a Custom provider connection.
- The dialog generates a random signing secret (64 hexadecimal characters, as for webhooks) and shows it before the connection exists. You can replace it with your own secret in the same format, generated from a cryptographically secure random source (for example
openssl rand -hex 32). Prefer one secret per connection. - Deploy the signing secret on your side first.
- Enter a connection name, your base URL, and a Cache duration (see Caching and call volume), then click Connect.
POST /v1/capabilities request to your base URL. Your endpoint can only accept it once it knows the signing secret, which is why the secret must be deployed before you connect. If the call fails, the connection is not created.
CloudCruise stores the capabilities your endpoint reports. After you enable item listing, click Test connection again so CloudCruise picks it up.
A workspace can have up to 10 custom provider connections. Testing a connection, changing its base URL and browsing its items are limited to a few calls per minute; past that, CloudCruise answers 429 and you can retry shortly.
Then bind a credential to an item.
Request Authentication
Every request is signed with HMAC-SHA256 using the connection’s signing secret. Each request carries:
The signed string is six lines joined by
\n (no trailing newline):
https://pm.example.com/cloudcruise, the request goes to https://pm.example.com/cloudcruise/v1/items/resolve and the signed path is /v1/items/resolve. Use the literal path of the endpoint your handler implements, not the path as received, so no URL normalization is involved and a gateway that rewrites or strips a path prefix cannot break verification.
signature = hex(HMAC-SHA256(key = signing secret as UTF-8 bytes, message = signed string))
You must:
- Compute the body hash over the raw bytes you received, before any JSON parsing. Re-serialized JSON will not match.
- Accept the request if any
v1=value in the signature header matches, compared in constant time. - Reject requests whose timestamp is more than 300 seconds away from your clock, in either direction. Keep your server time synchronized (NTP).
- Serve over HTTPS with a publicly trusted certificate. Plain HTTP and self-signed certificates are rejected by CloudCruise.
401 response and error code invalid_signature: an unknown connection id, a missing, duplicated or malformed header, a timestamp outside the window and a wrong signature alike. Different answers would tell a caller which check failed and which connection ids exist. Verify the signature before you parse the body or act on it.
We strongly recommend rejecting a repeated X-CloudCruise-Request-Id: remember each id until its timestamp has left the 300-second window, that is, for 300 seconds past its signed timestamp rather than past its arrival, because a timestamp may be up to 300 seconds in the future. This matters most on the read endpoints: a replayed resolve returns the secret values to whoever replays it. It is a recommendation rather than a requirement only because it needs a small store of recent ids on a hot path; without it you rely on TLS and the 300-second window. CloudCruise never reuses an id, so this cannot reject a genuine request.
Record an id only after its signature and timestamp have verified, and check-and-store it in one atomic step (a set-if-absent with an expiry in your cache or database). An id recorded before verification lets an unauthenticated caller fill your store with random ids. Keep the store bounded.
You may additionally restrict access to CloudCruise’s egress IPs: 35.164.71.220, 54.191.200.70, 18.236.26.110 (the same addresses as webhook deliveries). Do not rely on this alone: the list can change, and CloudCruise announces such changes in advance.
Hardening checklist
- Keep the signing secret in a secret manager or in environment configuration, never in source control. Do not reuse it for anything else, including your webhook secret.
- Never log request or response bodies.
resolveresponses carry passwords and one-time-code seeds. Log the connection id, request id, endpoint and status only. - Limit how many bytes of the request body you read before hashing it. CloudCruise’s requests are small.
- Give each CloudCruise connection its own signing secret, and answer
403 forbiddenfor any item that connection should not read, so a connection can only resolve what you intend it to. - Rotate the signing secret as soon as you suspect it was exposed (see Rotating the Signing Secret).
Example verification (Node.js)
Test vector
Check your implementation against these exact values (ignore the timestamp window for this test):
The same request verified as
/v1/items/describe must fail; its signature would be a09211a0cccd4bf4b66f625b70f8f498b33dedb7fb0bed06bf1a6c17cb708369. Any change to the body bytes, including whitespace, must also fail.
Item References
Aref is your own identifier for one item: 1 to 512 printable ASCII characters (0x20 to 0x7E). CloudCruise treats it as opaque, stores it on the vault credential, and sends it back unchanged. Pick something stable: if an item’s ref changes, credentials bound to it stop resolving.
Binding credentials
Bind a vault credential to an item in the dashboard (Credentials source, then your connection and the item), or through the Vault API by passing the connection’ssecret_provider_id and the item’s ref as secret_ref. You can list your connections to find the connection id. A connection’s provider_type is custom_http.
If you implement POST /v1/items/list, users pick an item from a list in the dashboard and the items are also available through the API. Otherwise users type the ref.
Two-Factor Authentication (TOTP)
totp_seed is the item’s TOTP secret, not a one-time code. Return a base32 seed or an otpauth://totp/... URI; from a URI, CloudCruise reads only the secret parameter. CloudCruise generates codes itself with the standard parameters: SHA-1, 6 digits, 30-second period. Items using other parameters are not supported in this version.
CloudCruise trims the value and removes whitespace. A URI without a secret parameter, or a seed that is not valid base32, cannot be used.
Omit totp_seed for items without two-factor authentication. Only a workflow step that needs an authenticator code fails, with a reason such as custom provider returned no totp_seed for <ref> or custom provider returned an unusable totp_seed for <ref>: <why>. The other values of the item are used normally.
See Two-Factor Authentication for the other methods.
Caching and Call Volume
CloudCruise caches the resolved values of each credential for the cache duration (default 5 minutes, configurable from 0 to 24 hours on the connection, overridable per credential). The cache is encrypted with the workspace’s key. The TOTP seed is cached with the other values; one-time codes are generated fresh every time and never cached. The cache is cleared:- for one credential, when its binding or settings are edited,
- for the whole workspace, when connection settings change or a user clicks Clear cached secrets in Workspace Settings → Integrations.
resolve is called, unless a cached value exists:
- when a run is submitted for a specific credential, to check that it resolves,
- every time a run is handed to a browser, including after a requeue,
- when a user opens the credential in the dashboard, or an API client reads it through the Vault API,
- occasionally while CloudCruise analyses a failed run.
resolve call per bound credential per cache window; with caching off, expect at least one per run. More calls happen when:
- several runs start at once while the cache is empty; each may call
resolve, - a call failed, or returned none of the three values; such results are not cached, so the next run calls again.
describe is called each time a user opens a bound credential in the dashboard and when a user binds one. It is not cached; keep it cheap.
What CloudCruise holds, and for how long
- The cache is shared by all runs of the workspace, kept per credential, and encrypted with the workspace’s key. It never outlives the cache duration.
- A run gets the credential’s values each time it is handed to a browser and holds that copy while it runs and for up to 30 minutes after it ends. A requeued run is handed to a browser again and picks up the current values. Changing or revoking the item affects runs handed to a browser afterwards (once the cache expires or is cleared), not runs already in progress.
- When your service is unavailable, runs keep using a cached value until it expires. After that, a run submitted for a specific credential is rejected, and a run that is already queued fails when it is handed to a browser (temporary failures requeue it). There is no stale fallback beyond the cache duration.
- A cache duration of 0 means CloudCruise resolves the item for every run. The run still holds its copy as described above, and the browser running the workflow receives the values it has to type.
- Two separate authorizations. Your endpoint decides whether CloudCruise may obtain a secret from you. CloudCruise’s own access control decides who may use a secret CloudCruise has obtained: runs of the workspace, its members, and its API keys.
- Revoking access. Revoking the signing secret or removing the item’s access on your side stops CloudCruise from obtaining the secret again; clicking Clear cached secrets in CloudCruise removes the cached copies. Neither recalls copies already held by runs in progress, held for up to 30 minutes after a run ends, or read by API clients. Immediate revocation of every copy is not possible; change the password itself if it must stop working.
Timeouts, Retries, and Size Limits
- Answer promptly. CloudCruise gives each request a few seconds, so a slow answer is treated as a failure.
- On timeouts, connection errors,
429and5xx, CloudCruise retries a limited number of times within a short overall time limit. ARetry-Afterof up to 10 seconds is honoured. It never retries other4xxresponses. - Every retry is a new request with a new id and signature, so make your handlers safe to call more than once.
- Responses larger than 64 KiB (
list: 5 MiB) are rejected.
Network Rules
- The base URL must be HTTPS and its hostname must resolve only to public addresses. Private, loopback, link-local (including cloud metadata addresses) and other reserved addresses are rejected.
- CloudCruise checks the address it actually connects to on every request, not only when the connection is saved.
- Redirects are never followed. Any
3xxresponse is treated as an error. Configure the final URL as the base URL.
Errors
Return errors as{"error": {"code": "...", "message": "..."}}. The message is shown to CloudCruise users as plain text, truncated to 1000 characters and only when the body is a valid error object. It must not contain secret values or details about your infrastructure.
A 2xx response that is not valid JSON, misses a required property or has a property of the wrong type is treated as a provider error (invalid_response) and not retried. Unknown properties are ignored.
A failed resolve either rejects the run submission (when the run is submitted for a specific credential) or fails the run when it is handed to a browser. Both report the provider’s error, distinct from “credential not found” and from website errors. In the table, “fails” means whichever of the two applies.
A
400 from capabilities is also a failure: the connection is not created. Provider errors are reported separately from errors on the website being automated, so an outage on your side never looks like a site failure.
Rotating the Signing Secret
- Add a second signing secret to the connection in CloudCruise (generated, or your own in the same format).
- While both secrets are active, CloudCruise sends two signatures, comma-separated in
X-CloudCruise-Signature. A connection has at most two active secrets, so the header never holds more than twov1=values; you may reject one that does. - Deploy the new secret on your side. Your verification accepts the request if any signature matches, so the old secret keeps working while you deploy.
- Remove the old secret in CloudCruise.
Forward Compatibility and Versioning
The four endpoints described here will not change incompatibly withinv1. Within v1, CloudCruise may add optional request fields, optional response fields it understands, headers, and endpoints, all in backwards-compatible ways. Ignore request properties and headers you do not recognise. CloudCruise ignores response properties it does not recognise. Breaking changes are published under /v2, and v1 stays supported alongside it.
The capabilities response must always include item_listing and password_write; item_search is optional. password_write and item_search are reserved: return false for both in this version.
