Advanced — Provision secrets as RAM files
This lesson is written and checked for Windows with PowerShell. Linux and macOS hosts take a different delivery path; see Linux and macOS at the end before trying it elsewhere.
Lesson code: Complete runnable Echo reference.
In the Todo lessons, services received everything they needed
through environment variables. Some applications insist on reading a credential
from a file instead (a *_FILE variable, a JSON config, a key file). This
lesson shows how Service Lasso delivers such a file without ever writing the
secret to disk: Secrets Broker creates it in RAM and hands the service a private
path to it.
To keep your Todo stack untouched, the lesson uses a separate learning service,
echo-webdav, built from the Echo example. Once you have seen the pattern, the
same broker block works for any service whose app can read a file from the
directory it is given.
Outcome
Secrets Broker provisions a secret into a RAM file and returns a private WebDAV directory. Core passes that directory to Echo, Echo reads the file, and you confirm the result with a checker script and Service Admin's RAM files view. You also prove the file is recreated on restart and that launch fails when the secret is missing.
Provision secrets as RAM files
The secret value stays inside Broker until Echo downloads the file. Core never
receives the plaintext and never writes it to disk. Delivering secrets through
env is still supported separately.
Before you start
You need:
- A working Service Lasso learning host with Service Admin, for example the one from the Quick start. Use a separate services root from your Todo checkpoints.
- An initialized and unlocked Secrets Broker, signed in with permission to write secrets and to read the workspace inventory.
- Core built from
develop. Broker-provisioned secret files are not in a published Core release yet: the latest release,2026.9.22-f3de461, predates them. Use matching Broker and Service Admin builds that include the Secrets Broker → RAM files view. Older builds reject or ignore thebroker.filesdeclaration used below. - Node.js 22 or newer, Git, and the Go version listed in the Echo repository's
go.mod. Go is only needed to build the sample; the built service does not need it.
Publishing these docs does not upgrade installed binaries. Check the Core, Broker and Admin builds on your learning host before you start.
1. Prepare the service
In PowerShell, from a folder outside your host's services root:
git clone --branch develop --single-branch https://github.com/service-lasso/lasso-echoservice.git echo-secret-reference
Set-Location echo-secret-reference
$servicesRoot = Read-Host 'Existing services root for your learning host'
node examples/webdav/prepare.mjs $servicesRoot
The setup script builds Echo and writes the binary (echo-secret-demo.exe)
and a complete service.json into a new echo-webdav folder in your services
root. It refuses to run if echo-webdav already exists, so existing services
are never overwritten. If the build fails, the new folder is left in place for
inspection.
The parts of the generated manifest that matter for this lesson are the env
entries that tell Echo where to look, and the broker block:
{
"id": "echo-webdav",
"executable": "./echo-secret-demo.exe",
"env": {
"ECHO_SECRET_FILES_DIR": "${SERVICE_LASSO_SECRETS_DIR}",
"ECHO_SECRET_FILE_NAME": "demo-config.json"
},
"broker": {
"imports": [
{
"namespace": "shared/echo",
"ref": "echo.DEMO_CREDENTIAL",
"required": true
}
],
"files": [
{
"path": "demo-config.json",
"content": "{\"demoCredential\":\"${echo.DEMO_CREDENTIAL}\"}"
}
]
}
}
The full manifest, with endpoints and health checks, is
examples/webdav/service.json.
On Windows the setup script only changes the executable name to add .exe.
What each part does:
| Configuration | Meaning |
|---|---|
broker.imports[].namespace and ref | The stored secret this service may use. |
required: true | Broker must find and authorize this secret, or the service does not start. |
broker.files[] | Ask Broker to create the named file in RAM. |
path | The file name inside the private Broker directory, not a disk location. |
content | A template with no secret in it; Broker fills in ${echo.DEMO_CREDENTIAL} itself. |
${SERVICE_LASSO_SECRETS_DIR} | The private WebDAV directory Broker returns at launch. |
ECHO_SECRET_FILE_NAME | Echo appends demo-config.json to that directory and reads it. |
An import on its own does not create a file; the broker.files entry does.
Variable names such as ECHO_SECRET_FILES_DIR or *_FILE are conventions of
the consuming app, so use whatever your app understands.
- For a single-value file, use
${database.PASSWORD}as the wholecontentand pass${SERVICE_LASSO_SECRETS_DIR}/passwordto your app. - Packaged services can ship secret-free template files with
broker.templates[]({ source, target }) instead of inlinecontent. - Broker substitutes text and does not JSON-escape values. The lesson value is JSON-safe; put arbitrary raw credentials in a single-value file.
- Ordinary, non-secret configuration still belongs in
config.files, which is written beneath the service root.
Older manifests that declared secret files under config with an ephemeral
flag are rejected. Move the whole entry into broker.files (or
broker.templates) and remove the ephemeral flag.
2. Create the demo secret in Broker
In Service Admin, open Secrets Broker and create a secret with:
- namespace
shared/echo - ref
echo.DEMO_CREDENTIAL - value
synthetic-demo-credential
The full stored reference is shared/echo/echo.DEMO_CREDENTIAL. Use this
synthetic value for the lesson. Real credentials belong in Broker, never in a
checked-in manifest.
3. Start through Core
In Service Admin, refresh discovery, then Install, Configure and
Start echo-webdav. No manual manifest editing is needed.
When you press Start:
- Core sends Broker the file names, the secret-free templates and the allowed references, under a launch lease scoped to this service.
- Broker checks permissions, resolves the secret, creates the file in RAM and returns a private WebDAV directory.
- Core puts that directory in Echo's environment and starts Echo. The secret value never passes through Core.
- Echo reads and validates the JSON, and reports only safe status.
On Windows the directory arrives as a UNC path. Echo converts it to a loopback HTTP URL, so you do not need to map a drive or enable the WebClient service.
Starting the Echo binary directly does not work: only a start through Core asks Broker to provision the file.
4. Run the checker and inspect usage
In Service Admin, open Network and copy Echo's Service HTTP origin. It
looks like http://127.0.0.1:PORT; use the port actually allocated, which is
not always 4010. Then, from the echo-secret-reference folder:
$echoOrigin = Read-Host 'Echo Service HTTP origin, for example http://127.0.0.1:4010'
node examples/webdav/check.mjs $echoOrigin
On a freshly started instance with the lesson value, it prints:
{ "status": "loaded", "sizeBytes": 46, "reads": 2 }
sizeBytes is the length of {"demoCredential":"synthetic-demo-credential"}.
reads counts how often Echo has read the file: once when it started, plus
once more because the checker asks Echo to reread it. The checker fails unless
that count goes up by exactly one, which proves Echo really fetched the file
again rather than reporting a cached result.
You can query the same status yourself. GET /secret-file returns status
only; POST /secret-file makes Echo reread the file:
Invoke-WebRequest -Uri "$echoOrigin/secret-file" -UseBasicParsing | Select-Object -ExpandProperty Content
Invoke-WebRequest -Uri "$echoOrigin/secret-file" -Method Post -UseBasicParsing | Select-Object -ExpandProperty Content
The checker exits with an error if the file is unavailable, the origin is not loopback, the request is redirected, the status is invalid or the counter does not advance. A healthy Echo alone does not prove the file was delivered.
Now open Secrets Broker → RAM files in Service Admin, filter on
echo-webdav and select Refresh files. You see listener state, RAM use,
the owning service, file size, completed downloads, bytes served and last
access. demo-config.json should show the same 46 bytes and two completed
downloads, matching Echo's reads, if nothing else read it. Run the checker
again and both numbers go up.
Directory listings and HEAD requests do not count as downloads. The page also
refreshes every 30 seconds, and search and sort apply to the current page only.
File contents and access tokens are never shown.
5. Verify recreation and failure
- In Service Admin, Stop
echo-webdav. Its entry disappears from Secrets Broker → RAM files. - Start it again. Broker creates a fresh file at a new path from the current secret value, and the counters start again from zero.
- Stop
echo-webdav. In Secrets Broker, delete only the syntheticshared/echo/echo.DEMO_CREDENTIALsecret, then try Start. Launch must fail before Echo starts, because the import isrequired. Recreate the secret from step 2 and start again to recover. Do not touch real application secrets.
Good to know:
- Replacing the file invalidates the old path.
- Restarting Broker loses all RAM files; the next fresh launch provisions them again. Processes that are already running keep their existing access.
- A Core crash on its own does not revoke files Broker is still serving. If a revoke fails because Broker is unreachable, bring Broker back and retry the pending action.
- Recreating a file does not rotate the stored secret.
Troubleshooting
| Symptom | Check |
|---|---|
| Setup refuses the folder | echo-webdav already exists. Keep it, or use a separate learning host or services root. |
| Start fails before Echo launches | Broker is unlocked; the namespace and ref exist and are allowed; file names are relative; Broker has RAM to spare. There is no fallback to disk. |
| Echo reports the file unavailable | Echo's environment entries, that the binary came from prepare.mjs, and that the template produces valid JSON. |
| RAM files is empty | Start echo-webdav through Core. Imports used only in env do not create files. |
| RAM files denies access | Your account has workspace-read permission and Core, Broker and Admin are matching builds. |
| Another app rejects the path | The app must accept a Windows UNC path or an HTTP/WebDAV URL. |
File paths are credentials, even on loopback. Share only safe metadata (status, size, counts) in screenshots and support requests. Remember that an app can still copy or log the bytes it receives.
Linux and macOS
This lesson has not been written up for Linux or macOS yet. On those hosts Broker returns an HTTP directory instead of a UNC path, and apps that need a native file path require the explicit Linux tmpfs alternative. The Echo example README lists the equivalent commands.