Theme
The secret store Preview
A script usually needs a credential: an API token, a database password, a Slack webhook URL. The secret store is where those live, so they do not have to sit in the script itself.
js
var apiKey = GetSecret("stripe-api-key");You create the secret once in the Connector console, under Automation, then Secrets. From then on any script can read it by name.
Why not just put it in the script
Because a script is not a private place. Its source is visible to every Connector administrator, it is stored in the Connector's database, and it is therefore in every backup of that database. A credential pasted into a script has been copied further than you meant it to go, and there is no way to find all the copies later.
A secret is stored encrypted instead, and no part of the console ever shows it back to you.
Creating a secret
Automation, then Secrets, then Add secret.
| Field | Notes |
|---|---|
| Name | What your script passes to GetSecret(). Capitals do not matter: a secret stored as Stripe-API-Key is found by GetSecret("stripe-api-key") |
| What it is for | A note for whoever reads this list in a year. Not used by scripts |
| Value | The credential. Up to 64 KB, so a private key or a service account JSON file fits |
Two secrets cannot have names that differ only in capitalisation. That is deliberate: if both existed, GetSecret would have to pick one, and you would have no way to tell which.
Reading one from a script
js
function GetSecret(name): string;Returns the stored value, or an empty string when there is no secret by that name.
It returns an empty string rather than throwing
A missing secret does not stop your script. It hands back "", and your script carries on and authenticates with nothing.
js
var apiKey = GetSecret("stripe-api-key");
if (apiKey === "") {
Log.Error("stripe-api-key is not in the secret store");
Exit(1);
}Check it. The engine cannot check it for you, because a script that legitimately treats an absent secret as optional has to be allowed to.
A miss is not silent on the Connector's side, even though it is quiet on the script's side. The log records the name you asked for and the script that asked, so Activity will tell you what went wrong.
Changing and removing
Editing a secret lets you rename it, change its note, or replace the value. The value box opens empty every time, and leaving it empty keeps the current value: that is what lets you rename a secret you are not allowed to read.
Deleting is never refused. The list shows which scripts mention the secret by name, as a warning, but that list cannot be complete: a script is free to build a name while it runs, and no inspection can see that coming. After a delete, every script that reads the name gets "".
What this protects you from, and what it does not
An administrator who can write scripts can read every secret
Write only applies to the console, not to scripting. A script calls GetSecret(name) and receives the value, so anyone who can create a script can also write:
js
Log.Info(GetSecret("stripe-api-key"));and read any secret on this Connector out of the log.
The store is worth using anyway, because it removes the credential from places you cannot control:
| Without the store | With it |
|---|---|
| The credential is in the script source, on screen, for anyone browsing the scripts list | The script contains a name |
| It is in every database backup as readable text | It is in the backup encrypted, and unreadable without the machine's key file |
| Exporting or sharing a script hands over the credential with it | The script travels without it |
| Rotating it means editing every script that carries it | Rotating it is one edit in one place |
What it is not is a barrier between your own administrators and your credentials. If that is what you need, the control is who can reach the console, not this store.
Encrypted under this machine's key
Values are encrypted with a key file that lives in the Connector's own data directory and never leaves the machine. Neither SFTP.cloud nor Syncplify has it, and neither can read your secrets.
A database backup alone is not enough to restore them
Restore the Connector's database onto a different machine without also restoring that key file, and every secret in it becomes unreadable. The same is true of your encryption keys. Back up the whole data directory, not just the database.
Choosing what to store
The store makes a leaked credential less likely. It does not make one harmless, so it is still worth giving scripts the smallest credential that does the job.
| Instead of | Prefer |
|---|---|
| Your main database account | An account with rights to one table, read only where it can be |
| A cloud provider's root key | A scoped role, or the instance credential chain with no key at all |
| An Azure account key | A SAS token scoped to one container, with a real expiry |
| A shared Slack webhook | A webhook for a channel created for this purpose |
Coming from Syncplify Server
GetSecret is spelled the same and behaves the same. The differences are in where the store lives:
| Syncplify Server | Connector | |
|---|---|---|
| Scope | One store per virtual site | One store per Connector. There are no virtual sites here |
| Name matching | Capitals matter | Capitals do not matter |
| Permissions | A separate Secrets permission | Any Connector administrator |
A ported script that reads GetSecret needs no code change. It needs the secret to exist here, under the same name.